mirror of https://github.com/knative/client.git
[master] Auto-update dependencies (#936)
Produced via: `./hack/update-deps.sh --upgrade && ./hack/update-codegen.sh` /assign maximilien rhuss /cc maximilien rhuss
This commit is contained in:
parent
31296698cd
commit
7965358b58
8
go.mod
8
go.mod
|
|
@ -11,13 +11,13 @@ require (
|
||||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
||||||
gotest.tools v2.2.0+incompatible
|
gotest.tools v2.2.0+incompatible
|
||||||
k8s.io/api v0.18.1
|
k8s.io/api v0.18.1
|
||||||
k8s.io/apimachinery v0.18.5
|
k8s.io/apimachinery v0.18.6
|
||||||
k8s.io/cli-runtime v0.17.6
|
k8s.io/cli-runtime v0.17.6
|
||||||
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
|
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
|
||||||
k8s.io/code-generator v0.18.0
|
k8s.io/code-generator v0.18.0
|
||||||
knative.dev/eventing v0.16.1-0.20200715062032-28f9f61e6131
|
knative.dev/eventing v0.16.1-0.20200724032657-8d83431c07bd
|
||||||
knative.dev/pkg v0.0.0-20200714233132-cb1281d05cc8
|
knative.dev/pkg v0.0.0-20200724211057-f21f66204a5c
|
||||||
knative.dev/serving v0.16.1-0.20200715073232-81d40bfc82a6
|
knative.dev/serving v0.16.1-0.20200724203457-1517b1735305
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
108
go.sum
108
go.sum
|
|
@ -20,6 +20,8 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
cloud.google.com/go v0.60.0 h1:R+tDlceO7Ss+zyvtsdhTxacDyZ1k99xwskQ4FT7ruoM=
|
cloud.google.com/go v0.60.0 h1:R+tDlceO7Ss+zyvtsdhTxacDyZ1k99xwskQ4FT7ruoM=
|
||||||
cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU=
|
cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU=
|
||||||
|
cloud.google.com/go v0.61.0 h1:NLQf5e1OMspfNT1RAHOB3ublr1TW3YTXO8OiWwVjK2U=
|
||||||
|
cloud.google.com/go v0.61.0/go.mod h1:XukKJg4Y7QsUu0Hxg3qQKUWR4VuWivmyMK2+rUyxAqw=
|
||||||
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=
|
||||||
|
|
@ -35,28 +37,25 @@ cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w=
|
cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w=
|
||||||
|
cloud.google.com/go/pubsub v1.6.0/go.mod h1:I6DkrTv7tKIvDQTZt+6rAFo1446FEoVDJeLXTu4pCcE=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.9.0/go.mod h1:m+/etGaqZbylxaNT876QGXqEHp4PR2Rq5GMqICWb9bU=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
|
code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
|
||||||
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
|
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
|
||||||
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
|
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
|
||||||
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
|
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
|
||||||
contrib.go.opencensus.io/exporter/ocagent v0.6.0 h1:Z1n6UAyr0QwM284yUuh5Zd8JlvxUGAhFZcgMJkMPrGM=
|
contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200615190824-f8c219d2d895 h1:bXMXgHq+WAIkI2dQivk1yMyKVVqMj8emLmhEqQghPWw=
|
||||||
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
|
contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200615190824-f8c219d2d895/go.mod h1:IshRmMJBhDfFj5Y67nVhMYTTIze91RUeT73ipWKs/GY=
|
||||||
contrib.go.opencensus.io/exporter/ocagent v0.6.1-0.20200121232419-b3d61dbd6252 h1:78QgIAE2FeU2klDzCuergwddNYzuC9EihGyR2Eq+/XM=
|
|
||||||
contrib.go.opencensus.io/exporter/ocagent v0.6.1-0.20200121232419-b3d61dbd6252/go.mod h1:COXDBN+YYlzrujnt2M1Ym3DBY4O3GlMujpfhzvS27Rk=
|
|
||||||
contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg=
|
contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg=
|
||||||
contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A=
|
contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A=
|
||||||
contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0 h1:2O3c1g5CzMc1+Uah4Waot9Obm0yw70VXJzWaP6Fz3nw=
|
contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0 h1:2O3c1g5CzMc1+Uah4Waot9Obm0yw70VXJzWaP6Fz3nw=
|
||||||
contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0/go.mod h1:MjHoxkI7Ny27toPeFkRbXbzVjzIGkwOAptrAy8Mxtm8=
|
contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0/go.mod h1:MjHoxkI7Ny27toPeFkRbXbzVjzIGkwOAptrAy8Mxtm8=
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw=
|
contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw=
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.12.8/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
|
contrib.go.opencensus.io/exporter/stackdriver v0.12.8/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
|
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.1 h1:RX9W6FelAqTVnBi/bRXJLXr9n18v4QkQwZYIdnNS51I=
|
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.1/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
|
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.2 h1:5lKLBwUuq4S6pTbYaBtWmnay3eJfKNS3qL8M8HM5fM4=
|
contrib.go.opencensus.io/exporter/stackdriver v0.13.2 h1:5lKLBwUuq4S6pTbYaBtWmnay3eJfKNS3qL8M8HM5fM4=
|
||||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.2/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
|
contrib.go.opencensus.io/exporter/stackdriver v0.13.2/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
|
||||||
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
|
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
|
||||||
|
|
@ -116,6 +115,7 @@ github.com/GoogleCloudPlatform/cloud-builders/gcs-fetcher v0.0.0-20191203181535-
|
||||||
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
|
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
|
||||||
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
|
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
|
||||||
github.com/GoogleCloudPlatform/testgrid v0.0.7/go.mod h1:lmtHGBL0M/MLbu1tR9BWV7FGZ1FEFIdPqmJiHNCL7y8=
|
github.com/GoogleCloudPlatform/testgrid v0.0.7/go.mod h1:lmtHGBL0M/MLbu1tR9BWV7FGZ1FEFIdPqmJiHNCL7y8=
|
||||||
|
github.com/GoogleCloudPlatform/testgrid v0.0.13/go.mod h1:UlC/MvnkKjiVGijIKOHxnVyhDiTDCydw9H1XzmclQGU=
|
||||||
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
||||||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
|
|
@ -155,7 +155,7 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
|
||||||
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
|
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
|
||||||
github.com/andygrunwald/go-gerrit v0.0.0-20190120104749-174420ebee6c/go.mod h1:0iuRQp6WJ44ts+iihy5E/WlPqfg5RNeQxOmzRkxCdtk=
|
github.com/andygrunwald/go-gerrit v0.0.0-20190120104749-174420ebee6c/go.mod h1:0iuRQp6WJ44ts+iihy5E/WlPqfg5RNeQxOmzRkxCdtk=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
|
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
|
||||||
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
|
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
|
||||||
|
|
@ -335,6 +335,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsouza/fake-gcs-server v0.0.0-20180612165233-e85be23bdaa8/go.mod h1:1/HufuJ+eaDf4KTnYdS6HJMGvMRU8d4cYTuu/1QaBbI=
|
github.com/fsouza/fake-gcs-server v0.0.0-20180612165233-e85be23bdaa8/go.mod h1:1/HufuJ+eaDf4KTnYdS6HJMGvMRU8d4cYTuu/1QaBbI=
|
||||||
|
github.com/fsouza/fake-gcs-server v1.19.4/go.mod h1:I0/88nHCASqJJ5M7zVF0zKODkYTcuXFW5J5yajsNJnE=
|
||||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
|
|
@ -514,9 +515,13 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
||||||
|
github.com/google/go-cmp v0.5.1/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.1.1 h1:AG8FSAfXglim2l5qSrqp5VK2Xl03PiBf25NiTGGamws=
|
github.com/google/go-containerregistry v0.1.1 h1:AG8FSAfXglim2l5qSrqp5VK2Xl03PiBf25NiTGGamws=
|
||||||
github.com/google/go-containerregistry v0.1.1/go.mod h1:npTSyywOeILcgWqd+rvtzGWflIPPcBQhYoOONaY4ltM=
|
github.com/google/go-containerregistry v0.1.1/go.mod h1:npTSyywOeILcgWqd+rvtzGWflIPPcBQhYoOONaY4ltM=
|
||||||
|
github.com/google/go-containerregistry v0.1.2-0.20200717224239-a84993334b27 h1:UE29caIXS8tGBSgWvLOnFdOqV5fv672bfvkCS/9EHo0=
|
||||||
|
github.com/google/go-containerregistry v0.1.2-0.20200717224239-a84993334b27/go.mod h1:npTSyywOeILcgWqd+rvtzGWflIPPcBQhYoOONaY4ltM=
|
||||||
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/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
|
github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
|
||||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||||
|
|
@ -533,6 +538,7 @@ github.com/google/licenseclassifier v0.0.0-20200708223521-3d09a0ea2f39/go.mod h1
|
||||||
github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g=
|
github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
|
@ -541,6 +547,7 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
|
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
|
||||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||||
|
|
@ -569,9 +576,11 @@ github.com/goreleaser/nfpm v1.3.0/go.mod h1:w0p7Kc9TAUgWMyrub63ex3M2Mgw88M4GZXoT
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/csrf v1.6.2/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
|
github.com/gorilla/csrf v1.6.2/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
|
||||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
|
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.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.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.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
|
@ -589,11 +598,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
|
github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.12.2 h1:D0EVSTwQoQOyfY35QNSuPJA4jpZRtkoGYWQMB7XNg5o=
|
github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.12.2/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
|
|
||||||
github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE=
|
github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE=
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
|
|
@ -749,6 +756,7 @@ github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lL
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||||
|
github.com/mattn/go-zglob v0.0.2/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
|
@ -805,6 +813,8 @@ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
|
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/octago/sflags v0.2.0/go.mod h1:G0bjdxh4qPRycF74a2B8pU36iTp9QHGx0w0dFZXPt80=
|
github.com/octago/sflags v0.2.0/go.mod h1:G0bjdxh4qPRycF74a2B8pU36iTp9QHGx0w0dFZXPt80=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
|
|
@ -818,6 +828,8 @@ github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
|
||||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
||||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||||
|
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
|
@ -827,6 +839,8 @@ github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
|
||||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||||
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
|
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
|
||||||
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||||
|
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
|
|
@ -919,6 +933,10 @@ github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8/go.mod h1
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||||
|
github.com/rickb777/date v1.13.0 h1:+8AmwLuY1d/rldzdqvqTEg7107bZ8clW37x4nsdG3Hs=
|
||||||
|
github.com/rickb777/date v1.13.0/go.mod h1:GZf3LoGnxPWjX+/1TXOuzHefZFDovTyNLHDMd3qH70k=
|
||||||
|
github.com/rickb777/plural v1.2.1 h1:UitRAgR70+yHFt26Tmj/F9dU9aV6UfjGXSbO1DcC9/U=
|
||||||
|
github.com/rickb777/plural v1.2.1/go.mod h1:j058+3M5QQFgcZZ2oKIOekcygoZUL8gKW5yRO14BuAw=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
|
@ -1002,6 +1020,7 @@ github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
|
||||||
github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
||||||
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
|
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
|
||||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
|
github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A=
|
||||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU=
|
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU=
|
||||||
|
|
@ -1227,6 +1246,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||||
|
|
@ -1277,11 +1297,11 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
@ -1312,6 +1332,9 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6 h1:X9xIZ1YU8bLZA3l6gqDUHSFiD0GFI9S548h6C8nDtOY=
|
||||||
|
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
@ -1327,6 +1350,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqG
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
||||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||||
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
@ -1405,14 +1430,20 @@ golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roY
|
||||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512001501-aaeff5de670a/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200710042808-f1c4188a97a1 h1:rD1FcWVsRaMY+l8biE9jbWP5MS/CJJ/90a9TMkMgNrM=
|
golang.org/x/tools v0.0.0-20200709181711-e327e1019dfe/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200710042808-f1c4188a97a1/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200721032237-77f530d86f9a/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200721223218-6123e77877b2/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200723000907-a7c6fd066f6d h1:7k9BKfwmdbykG6l5ztniTrH0TP25yel8O7l26/yovMU=
|
||||||
|
golang.org/x/tools v0.0.0-20200723000907-a7c6fd066f6d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
|
@ -1448,6 +1479,7 @@ google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
|
||||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
|
google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
|
@ -1475,7 +1507,6 @@ google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98
|
||||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
|
||||||
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
|
@ -1492,14 +1523,19 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
|
||||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200603110839-e855014d5736/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200710124503-20a17af7bd0e h1:k+p/u26/lVeNEpdxSeUrm7rTvoFckBKaf7gTzgmHyDA=
|
google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200710124503-20a17af7bd0e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200721032028-5044d0edf986/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200722002428-88e341933a54 h1:ASrBgpl9XvkNTP0m39/j18mid7aoF21npu2ioIBxYnY=
|
||||||
|
google.golang.org/genproto v0.0.0-20200722002428-88e341933a54/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
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.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
|
@ -1508,7 +1544,6 @@ google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLD
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
|
@ -1646,28 +1681,29 @@ k8s.io/legacy-cloud-providers v0.17.4/go.mod h1:FikRNoD64ECjkxO36gkDgJeiQWwyZTuB
|
||||||
k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw=
|
k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw=
|
||||||
k8s.io/test-infra v0.0.0-20200514184223-ba32c8aae783/go.mod h1:bW6thaPZfL2hW7ecjx2WYwlP9KQLM47/xIJyttkVk5s=
|
k8s.io/test-infra v0.0.0-20200514184223-ba32c8aae783/go.mod h1:bW6thaPZfL2hW7ecjx2WYwlP9KQLM47/xIJyttkVk5s=
|
||||||
k8s.io/test-infra v0.0.0-20200617221206-ea73eaeab7ff/go.mod h1:L3+cRvwftUq8IW1TrHji5m3msnc4uck/7LsE/GR/aZk=
|
k8s.io/test-infra v0.0.0-20200617221206-ea73eaeab7ff/go.mod h1:L3+cRvwftUq8IW1TrHji5m3msnc4uck/7LsE/GR/aZk=
|
||||||
k8s.io/test-infra v0.0.0-20200710134549-5891a1a4cc17/go.mod h1:L3+cRvwftUq8IW1TrHji5m3msnc4uck/7LsE/GR/aZk=
|
k8s.io/test-infra v0.0.0-20200721115715-1af01ef6b4c8/go.mod h1:4cRZlOy5Ka3Ym/orCmNWL2dsE39pN0xHFT0WFrZe2HQ=
|
||||||
|
k8s.io/test-infra v0.0.0-20200722010006-526277bee528/go.mod h1:4cRZlOy5Ka3Ym/orCmNWL2dsE39pN0xHFT0WFrZe2HQ=
|
||||||
|
k8s.io/test-infra v0.0.0-20200723132140-b02d194a2d64/go.mod h1:4cRZlOy5Ka3Ym/orCmNWL2dsE39pN0xHFT0WFrZe2HQ=
|
||||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
k8s.io/utils v0.0.0-20200124190032-861946025e34 h1:HjlUD6M0K3P8nRXmr2B9o4F9dUy9TCj/aEpReeyi6+k=
|
k8s.io/utils v0.0.0-20200124190032-861946025e34 h1:HjlUD6M0K3P8nRXmr2B9o4F9dUy9TCj/aEpReeyi6+k=
|
||||||
k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
|
knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
|
||||||
knative.dev/caching v0.0.0-20200713162518-90ce4328c69e/go.mod h1:7I1DXX8uZX74qggUoUse5ZCaTuMIKyTVBZBpr/cmlaQ=
|
knative.dev/caching v0.0.0-20200723145958-d031ce9de55d/go.mod h1:z0tB8jJWOJj4SfbWGps++hjMQHSxB5XEiTyaRuyRtfE=
|
||||||
knative.dev/eventing v0.16.1-0.20200715062032-28f9f61e6131 h1:0/sqa96BMdcsMcQHgNVud3+lc1h7B6Se7jsv/XIVDL4=
|
knative.dev/eventing v0.16.1-0.20200724032657-8d83431c07bd h1:3Etn1vLNy1o0UE3kmUVedC/ZPHMYqKIsr2xAt3YArIY=
|
||||||
knative.dev/eventing v0.16.1-0.20200715062032-28f9f61e6131/go.mod h1:L57bxLUQcqgiC+VpbBAqiXu0L4SgY9ts7OZHjtoOVww=
|
knative.dev/eventing v0.16.1-0.20200724032657-8d83431c07bd/go.mod h1:D7x216MQznRHiu3V7Y5I29/xCRkHxl9i21T6LrZPQt8=
|
||||||
knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
|
knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
|
||||||
knative.dev/networking v0.0.0-20200713162319-e2731eead7e8 h1:BYQ/DJ1CQ0TQHzrrgdlg3zmL3djM/c4N4utLSEh9Fr8=
|
knative.dev/networking v0.0.0-20200723155758-cc457d7322d6 h1:E3icpGu2JG84UXvrG/36FovPwVmBWs1q6R6xZzcO6dM=
|
||||||
knative.dev/networking v0.0.0-20200713162319-e2731eead7e8/go.mod h1:9LCtmPUoygQ+M1ujGZeYcytAF3bDR42rlINsBhge06o=
|
knative.dev/networking v0.0.0-20200723155758-cc457d7322d6/go.mod h1:Xd6H9nzGwHI/tfEnvrm7dQjYP1s/CbZL8J941HyUaSE=
|
||||||
knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
|
knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
|
||||||
knative.dev/pkg v0.0.0-20200713031612-b09a159e12c9/go.mod h1:aWPsPIHISvZetAm/2pnz+v6Ro5EYaX704Z/Zd9rTZ4M=
|
knative.dev/pkg v0.0.0-20200723060257-ae9c3f7fa8d3/go.mod h1:pOJ+tu5k/SgHPGmecWqFguxJcIZozyDWlTlyldGcYGM=
|
||||||
knative.dev/pkg v0.0.0-20200714163019-3a916efe5c2e/go.mod h1:2xVLIH5SNUripobZvOEz3w/Ta9xqMkw7QmFIa2cbDFY=
|
knative.dev/pkg v0.0.0-20200724055557-c36f46cc8c80/go.mod h1:GtoTEupsOzadgRKT4GgPWukbhAcINwDDGcKibTyd1Fk=
|
||||||
knative.dev/pkg v0.0.0-20200714180919-c49f5b61e264/go.mod h1:yFXTzV2GIB30Qs6pdJNCbtKaIEhxH9fsmrrltAqfjWE=
|
knative.dev/pkg v0.0.0-20200724211057-f21f66204a5c h1:jJs9rQhkCexFr9m6+sYIPq/0DtRe+typQB64ffbXydM=
|
||||||
knative.dev/pkg v0.0.0-20200714233132-cb1281d05cc8 h1:pTcMEoNX1bwbLAsjA7hTsoO4gh3XyxmqDlKygm6mf+E=
|
knative.dev/pkg v0.0.0-20200724211057-f21f66204a5c/go.mod h1:jVP9M8uft3EYhWF8K00zKiNCvyfGy3tm0L2w9edCRqw=
|
||||||
knative.dev/pkg v0.0.0-20200714233132-cb1281d05cc8/go.mod h1:yFXTzV2GIB30Qs6pdJNCbtKaIEhxH9fsmrrltAqfjWE=
|
knative.dev/serving v0.16.1-0.20200724203457-1517b1735305 h1:Bqn8mTuMMWdnmbJzRPvEM69p71npap/YQPIxuNvkChE=
|
||||||
knative.dev/serving v0.16.1-0.20200715073232-81d40bfc82a6 h1:Z2zzsfHz6g4F59cNW78GXAnprdJ7Ez1al+s8jQqXseQ=
|
knative.dev/serving v0.16.1-0.20200724203457-1517b1735305/go.mod h1:txxxmKATqqQv9j/s7K6PI6BAZ3cOAddJE72LHUsTxDY=
|
||||||
knative.dev/serving v0.16.1-0.20200715073232-81d40bfc82a6/go.mod h1:N8K6wnL96n2SYnYARwLx99UrMJrw8nPCXxWwStBKf+Q=
|
knative.dev/test-infra v0.0.0-20200721175154-c98db9bd4d5d/go.mod h1:kzRhTm5L08eDQFRl8NKSAN93lz6IZWQMs+2TjTCN+VA=
|
||||||
knative.dev/test-infra v0.0.0-20200710160019-5b9732bc24f7/go.mod h1:vtT6dLs/iNj8pKcfag8CSVqHKNMgyCFtU/g1pV7Bovs=
|
knative.dev/test-infra v0.0.0-20200722142057-3ca910b5a25e/go.mod h1:oHmDsPmq+zcc3b+Z94Kgmrz1JnmZEz36jmKuvL2Lw7o=
|
||||||
knative.dev/test-infra v0.0.0-20200713045417-850e4e37918d/go.mod h1:vtT6dLs/iNj8pKcfag8CSVqHKNMgyCFtU/g1pV7Bovs=
|
knative.dev/test-infra v0.0.0-20200723182457-517b66ba19c1/go.mod h1:Y3sNbLSTA11kRcLvTzRsZCxO+GQuw7KV7+PL+iD+9CA=
|
||||||
knative.dev/test-infra v0.0.0-20200713220518-5a4c4cad5372/go.mod h1:vtT6dLs/iNj8pKcfag8CSVqHKNMgyCFtU/g1pV7Bovs=
|
|
||||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||||
|
|
@ -1685,7 +1721,7 @@ rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sigs.k8s.io/boskos v0.0.0-20200526191642-45fc818e2d00/go.mod h1:L1ubP7d1CCMSQSjKiZv6dGbh7b4kfoG+dFPj8cfYDnI=
|
sigs.k8s.io/boskos v0.0.0-20200526191642-45fc818e2d00/go.mod h1:L1ubP7d1CCMSQSjKiZv6dGbh7b4kfoG+dFPj8cfYDnI=
|
||||||
sigs.k8s.io/boskos v0.0.0-20200617235605-f289ba6555ba/go.mod h1:ZO5RV+VxJS9mb6DvZ1yAjywoyq/wQ8b0vDoZxcIA5kE=
|
sigs.k8s.io/boskos v0.0.0-20200717180850-7299d535c033/go.mod h1:ZO5RV+VxJS9mb6DvZ1yAjywoyq/wQ8b0vDoZxcIA5kE=
|
||||||
sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8=
|
sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8=
|
||||||
sigs.k8s.io/controller-runtime v0.5.4/go.mod h1:JZUwSMVbxDupo0lTJSSFP5pimEyxGynROImSsqIOx1A=
|
sigs.k8s.io/controller-runtime v0.5.4/go.mod h1:JZUwSMVbxDupo0lTJSSFP5pimEyxGynROImSsqIOx1A=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
5a4c4cad53724b4e74412981008ae34252c2e086
|
d5ec9cdc6b33bb0040747130db664579553ceb45
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,19 @@ function go_test_e2e() {
|
||||||
report_go_test -v -race -count=1 ${go_options} $@ "${test_options}"
|
report_go_test -v -race -count=1 ${go_options} $@ "${test_options}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Dumps the k8s api server metrics. Spins up a proxy, waits a little bit and
|
||||||
|
# dumps the metrics to ${ARTIFACTS}/k8s.metrics.txt
|
||||||
|
function dump_metrics() {
|
||||||
|
header ">> Starting kube proxy"
|
||||||
|
kubectl proxy --port=8080 &
|
||||||
|
local proxy_pid=$!
|
||||||
|
sleep 5
|
||||||
|
header ">> Grabbing k8s metrics"
|
||||||
|
curl -s http://localhost:8080/metrics > ${ARTIFACTS}/k8s.metrics.txt
|
||||||
|
# Clean up proxy so it doesn't interfere with job shutting down
|
||||||
|
kill $proxy_pid || true
|
||||||
|
}
|
||||||
|
|
||||||
# Dump info about the test cluster. If dump_extra_cluster_info() is defined, calls it too.
|
# Dump info about the test cluster. If dump_extra_cluster_info() is defined, calls it too.
|
||||||
# This is intended to be called when a test fails to provide debugging information.
|
# This is intended to be called when a test fails to provide debugging information.
|
||||||
function dump_cluster_state() {
|
function dump_cluster_state() {
|
||||||
|
|
@ -410,6 +423,7 @@ function success() {
|
||||||
echo "**************************************"
|
echo "**************************************"
|
||||||
echo "*** E2E TESTS PASSED ***"
|
echo "*** E2E TESTS PASSED ***"
|
||||||
echo "**************************************"
|
echo "**************************************"
|
||||||
|
dump_metrics
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,6 +433,7 @@ function fail_test() {
|
||||||
set_test_return_code 1
|
set_test_return_code 1
|
||||||
[[ -n $1 ]] && echo "ERROR: $1"
|
[[ -n $1 ]] && echo "ERROR: $1"
|
||||||
dump_cluster_state
|
dump_cluster_state
|
||||||
|
dump_metrics
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,9 @@ function wait_until_pods_running() {
|
||||||
echo -n "Waiting until all pods in namespace $1 are up"
|
echo -n "Waiting until all pods in namespace $1 are up"
|
||||||
local failed_pod=""
|
local failed_pod=""
|
||||||
for i in {1..150}; do # timeout after 5 minutes
|
for i in {1..150}; do # timeout after 5 minutes
|
||||||
local pods="$(kubectl get pods --no-headers -n $1 2>/dev/null)"
|
# List all pods. Ignore Terminating pods as those have either been replaced through
|
||||||
|
# a deployment or terminated on purpose (through chaosduck for example).
|
||||||
|
local pods="$(kubectl get pods --no-headers -n $1 2>/dev/null | grep -v Terminating)"
|
||||||
# All pods must be running (ignore ImagePull error to allow the pod to retry)
|
# All pods must be running (ignore ImagePull error to allow the pod to retry)
|
||||||
local not_running_pods=$(echo "${pods}" | grep -v Running | grep -v Completed | grep -v ErrImagePull | grep -v ImagePullBackOff)
|
local not_running_pods=$(echo "${pods}" | grep -v Running | grep -v Completed | grep -v ErrImagePull | grep -v ImagePullBackOff)
|
||||||
if [[ -n "${pods}" ]] && [[ -z "${not_running_pods}" ]]; then
|
if [[ -n "${pods}" ]] && [[ -z "${not_running_pods}" ]]; then
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ readonly PRESUBMIT_TEST_FAIL_FAST=${PRESUBMIT_TEST_FAIL_FAST:-0}
|
||||||
readonly NO_PRESUBMIT_FILES=(\.png \.gitignore \.gitattributes ^OWNERS ^OWNERS_ALIASES ^AUTHORS)
|
readonly NO_PRESUBMIT_FILES=(\.png \.gitignore \.gitattributes ^OWNERS ^OWNERS_ALIASES ^AUTHORS)
|
||||||
|
|
||||||
# Flag if this is a presubmit run or not.
|
# Flag if this is a presubmit run or not.
|
||||||
(( IS_PROW )) && [[ -n "${PULL_PULL_SHA}" ]] && IS_PRESUBMIT=1 || IS_PRESUBMIT=0
|
(( IS_PROW )) && [[ ${JOB_TYPE} == "presubmit" ]] && IS_PRESUBMIT=1 || IS_PRESUBMIT=0
|
||||||
readonly IS_PRESUBMIT
|
readonly IS_PRESUBMIT
|
||||||
|
|
||||||
# List of changed files on presubmit, LF separated.
|
# List of changed files on presubmit, LF separated.
|
||||||
|
|
@ -109,7 +109,8 @@ function run_build_tests() {
|
||||||
# Parameters: $1 - report name.
|
# Parameters: $1 - report name.
|
||||||
# $2... - command (test) to run.
|
# $2... - command (test) to run.
|
||||||
function report_build_test() {
|
function report_build_test() {
|
||||||
local report="$(mktemp)"
|
local report
|
||||||
|
report="$(mktemp)"
|
||||||
local report_name="$1"
|
local report_name="$1"
|
||||||
shift
|
shift
|
||||||
local errors=""
|
local errors=""
|
||||||
|
|
@ -163,7 +164,8 @@ function default_build_test_runner() {
|
||||||
[[ -z "${go_pkg_dirs}" ]] && return ${failed}
|
[[ -z "${go_pkg_dirs}" ]] && return ${failed}
|
||||||
# Ensure all the code builds
|
# Ensure all the code builds
|
||||||
subheader "Checking that go code builds"
|
subheader "Checking that go code builds"
|
||||||
local report="$(mktemp)"
|
local report
|
||||||
|
report="$(mktemp)"
|
||||||
local errors_go1=""
|
local errors_go1=""
|
||||||
local errors_go2=""
|
local errors_go2=""
|
||||||
if ! capture_output "${report}" go build -v ./... ; then
|
if ! capture_output "${report}" go build -v ./... ; then
|
||||||
|
|
@ -172,10 +174,12 @@ function default_build_test_runner() {
|
||||||
errors_go1="$(grep -v '^\(github\.com\|knative\.dev\)/' "${report}" | sort | uniq)"
|
errors_go1="$(grep -v '^\(github\.com\|knative\.dev\)/' "${report}" | sort | uniq)"
|
||||||
fi
|
fi
|
||||||
# Get all build tags in go code (ignore /vendor, /hack and /third_party)
|
# Get all build tags in go code (ignore /vendor, /hack and /third_party)
|
||||||
local tags="$(grep -r '// +build' . \
|
local tags
|
||||||
|
tags="$(grep -r '// +build' . \
|
||||||
| grep -v '^./vendor/' | grep -v '^./hack/' | grep -v '^./third_party' \
|
| grep -v '^./vendor/' | grep -v '^./hack/' | grep -v '^./third_party' \
|
||||||
| cut -f3 -d' ' | sort | uniq | tr '\n' ' ')"
|
| cut -f3 -d' ' | sort | uniq | tr '\n' ' ')"
|
||||||
local tagged_pkgs="$(grep -r '// +build' . \
|
local tagged_pkgs
|
||||||
|
tagged_pkgs="$(grep -r '// +build' . \
|
||||||
| grep -v '^./vendor/' | grep -v '^./hack/' | grep -v '^./third_party' \
|
| grep -v '^./vendor/' | grep -v '^./hack/' | grep -v '^./third_party' \
|
||||||
| grep ":// +build " | cut -f1 -d: | xargs dirname \
|
| grep ":// +build " | cut -f1 -d: | xargs dirname \
|
||||||
| sort | uniq | tr '\n' ' ')"
|
| sort | uniq | tr '\n' ' ')"
|
||||||
|
|
@ -190,7 +194,8 @@ function default_build_test_runner() {
|
||||||
rm -f e2e.test
|
rm -f e2e.test
|
||||||
done
|
done
|
||||||
|
|
||||||
local errors_go="$(echo -e "${errors_go1}\n${errors_go2}" | uniq)"
|
local errors_go
|
||||||
|
errors_go="$(echo -e "${errors_go1}\n${errors_go2}" | uniq)"
|
||||||
create_junit_xml _build_tests Build_Go "${errors_go}"
|
create_junit_xml _build_tests Build_Go "${errors_go}"
|
||||||
# Check that we don't have any forbidden licenses in our images.
|
# Check that we don't have any forbidden licenses in our images.
|
||||||
subheader "Checking for forbidden licenses"
|
subheader "Checking for forbidden licenses"
|
||||||
|
|
@ -266,17 +271,16 @@ function run_integration_tests() {
|
||||||
|
|
||||||
# Default integration test runner that runs all `test/e2e-*tests.sh`.
|
# Default integration test runner that runs all `test/e2e-*tests.sh`.
|
||||||
function default_integration_test_runner() {
|
function default_integration_test_runner() {
|
||||||
# options is always empty.
|
|
||||||
# TODO: remove it or indeed allow passing options.
|
|
||||||
local options=""
|
|
||||||
local failed=0
|
local failed=0
|
||||||
for e2e_test in $(find test/ -name e2e-*tests.sh); do
|
find test/ ! -name "$(printf "*\n*")" -name "e2e-*tests.sh" > tmp
|
||||||
|
while IFS= read -r e2e_test
|
||||||
|
do
|
||||||
echo "Running integration test ${e2e_test}"
|
echo "Running integration test ${e2e_test}"
|
||||||
if ! ${e2e_test} ${options}; then
|
if ! ${e2e_test}; then
|
||||||
failed=1
|
failed=1
|
||||||
step_failed "${e2e_test} ${options}"
|
step_failed "${e2e_test}"
|
||||||
fi
|
fi
|
||||||
done
|
done < tmp
|
||||||
return ${failed}
|
return ${failed}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,7 +328,7 @@ function main() {
|
||||||
# (https://github.com/kubernetes/test-infra/blob/09bd4c6709dc64308406443f8996f90cf3b40ed1/jenkins/bootstrap.py#L588)
|
# (https://github.com/kubernetes/test-infra/blob/09bd4c6709dc64308406443f8996f90cf3b40ed1/jenkins/bootstrap.py#L588)
|
||||||
# TODO(chaodaiG): follow up on https://github.com/kubernetes/test-infra/blob/0fabd2ea816daa8c15d410c77a0c93c0550b283f/prow/initupload/run.go#L49
|
# TODO(chaodaiG): follow up on https://github.com/kubernetes/test-infra/blob/0fabd2ea816daa8c15d410c77a0c93c0550b283f/prow/initupload/run.go#L49
|
||||||
echo ">> node name"
|
echo ">> node name"
|
||||||
echo "$(curl -H "Metadata-Flavor: Google" 'http://169.254.169.254/computeMetadata/v1/instance/name' 2> /dev/null)"
|
curl -H "Metadata-Flavor: Google" 'http://169.254.169.254/computeMetadata/v1/instance/name' 2> /dev/null
|
||||||
echo ">> pod name"
|
echo ">> pod name"
|
||||||
echo "${HOSTNAME}"
|
echo "${HOSTNAME}"
|
||||||
fi
|
fi
|
||||||
|
|
@ -336,6 +340,15 @@ function main() {
|
||||||
while [[ $# -ne 0 ]]; do
|
while [[ $# -ne 0 ]]; do
|
||||||
local parameter=$1
|
local parameter=$1
|
||||||
case ${parameter} in
|
case ${parameter} in
|
||||||
|
--help|-h)
|
||||||
|
echo "Usage: ./presubmit-tests.sh [options...]"
|
||||||
|
echo " --build-tests: run build tests."
|
||||||
|
echo " --unit-tests: run unit tests."
|
||||||
|
echo " --integration-tests: run integration tests, basically all the e2e-*tests.sh."
|
||||||
|
echo " --all-tests: run build tests, unit tests and integration tests in sequence."
|
||||||
|
echo " --run-test: run custom tests. Can be used to run multiple tests that need different args."
|
||||||
|
echo " For example, ./presubmit-tests.sh --run-test \"e2e-tests1.sh arg1\" \"e2e-tests2.sh arg2\"."
|
||||||
|
;;
|
||||||
--build-tests) RUN_BUILD_TESTS=1 ;;
|
--build-tests) RUN_BUILD_TESTS=1 ;;
|
||||||
--unit-tests) RUN_UNIT_TESTS=1 ;;
|
--unit-tests) RUN_UNIT_TESTS=1 ;;
|
||||||
--integration-tests) RUN_INTEGRATION_TESTS=1 ;;
|
--integration-tests) RUN_INTEGRATION_TESTS=1 ;;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2009,2014 Google Inc. All rights reserved.
|
Copyright (c) 2015 The Go Authors & Rick Beton. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2016, Rick Beton
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of plural nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
@ -128,7 +128,7 @@ func newUnexportedFilter(typs ...interface{}) unexportedFilter {
|
||||||
for _, typ := range typs {
|
for _, typ := range typs {
|
||||||
t := reflect.TypeOf(typ)
|
t := reflect.TypeOf(typ)
|
||||||
if t == nil || t.Kind() != reflect.Struct {
|
if t == nil || t.Kind() != reflect.Struct {
|
||||||
panic(fmt.Sprintf("invalid struct type: %T", typ))
|
panic(fmt.Sprintf("%T must be a non-pointer struct", typ))
|
||||||
}
|
}
|
||||||
ux.m[t] = true
|
ux.m[t] = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func newStructFilter(typ interface{}, names ...string) structFilter {
|
||||||
|
|
||||||
t := reflect.TypeOf(typ)
|
t := reflect.TypeOf(typ)
|
||||||
if t == nil || t.Kind() != reflect.Struct {
|
if t == nil || t.Kind() != reflect.Struct {
|
||||||
panic(fmt.Sprintf("%T must be a struct", typ))
|
panic(fmt.Sprintf("%T must be a non-pointer struct", typ))
|
||||||
}
|
}
|
||||||
var ft fieldTree
|
var ft fieldTree
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package cmp
|
package cmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -125,21 +126,20 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind,
|
||||||
// implementations crash when doing so.
|
// implementations crash when doing so.
|
||||||
if (t.Kind() != reflect.Ptr && t.Kind() != reflect.Interface) || !v.IsNil() {
|
if (t.Kind() != reflect.Ptr && t.Kind() != reflect.Interface) || !v.IsNil() {
|
||||||
var prefix, strVal string
|
var prefix, strVal string
|
||||||
|
func() {
|
||||||
|
// Swallow and ignore any panics from String or Error.
|
||||||
|
defer func() { recover() }()
|
||||||
switch v := v.Interface().(type) {
|
switch v := v.Interface().(type) {
|
||||||
case error:
|
case error:
|
||||||
prefix, strVal = "e", v.Error()
|
strVal = v.Error()
|
||||||
|
prefix = "e"
|
||||||
case fmt.Stringer:
|
case fmt.Stringer:
|
||||||
prefix, strVal = "s", v.String()
|
strVal = v.String()
|
||||||
|
prefix = "s"
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
if prefix != "" {
|
if prefix != "" {
|
||||||
maxLen := len(strVal)
|
return opts.formatString(prefix, strVal)
|
||||||
if opts.LimitVerbosity {
|
|
||||||
maxLen = (1 << opts.verbosity()) << 5 // 32, 64, 128, 256, etc...
|
|
||||||
}
|
|
||||||
if len(strVal) > maxLen+len(textEllipsis) {
|
|
||||||
return textLine(prefix + formatString(strVal[:maxLen]) + string(textEllipsis))
|
|
||||||
}
|
|
||||||
return textLine(prefix + formatString(strVal))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,14 +171,7 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind,
|
||||||
case reflect.Complex64, reflect.Complex128:
|
case reflect.Complex64, reflect.Complex128:
|
||||||
return textLine(fmt.Sprint(v.Complex()))
|
return textLine(fmt.Sprint(v.Complex()))
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
maxLen := v.Len()
|
return opts.formatString("", v.String())
|
||||||
if opts.LimitVerbosity {
|
|
||||||
maxLen = (1 << opts.verbosity()) << 5 // 32, 64, 128, 256, etc...
|
|
||||||
}
|
|
||||||
if v.Len() > maxLen+len(textEllipsis) {
|
|
||||||
return textLine(formatString(v.String()[:maxLen]) + string(textEllipsis))
|
|
||||||
}
|
|
||||||
return textLine(formatString(v.String()))
|
|
||||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||||
return textLine(formatPointer(value.PointerOf(v), true))
|
return textLine(formatPointer(value.PointerOf(v), true))
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
|
|
@ -210,6 +203,17 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind,
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
return textNil
|
return textNil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether this is a []byte of text data.
|
||||||
|
if t.Elem() == reflect.TypeOf(byte(0)) {
|
||||||
|
b := v.Bytes()
|
||||||
|
isPrintSpace := func(r rune) bool { return unicode.IsPrint(r) && unicode.IsSpace(r) }
|
||||||
|
if len(b) > 0 && utf8.Valid(b) && len(bytes.TrimFunc(b, isPrintSpace)) == 0 {
|
||||||
|
out = opts.formatString("", string(b))
|
||||||
|
return opts.WithTypeMode(emitType).FormatType(t, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
maxLen := v.Len()
|
maxLen := v.Len()
|
||||||
|
|
@ -295,6 +299,49 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (opts formatOptions) formatString(prefix, s string) textNode {
|
||||||
|
maxLen := len(s)
|
||||||
|
maxLines := strings.Count(s, "\n") + 1
|
||||||
|
if opts.LimitVerbosity {
|
||||||
|
maxLen = (1 << opts.verbosity()) << 5 // 32, 64, 128, 256, etc...
|
||||||
|
maxLines = (1 << opts.verbosity()) << 2 // 4, 8, 16, 32, 64, etc...
|
||||||
|
}
|
||||||
|
|
||||||
|
// For multiline strings, use the triple-quote syntax,
|
||||||
|
// but only use it when printing removed or inserted nodes since
|
||||||
|
// we only want the extra verbosity for those cases.
|
||||||
|
lines := strings.Split(strings.TrimSuffix(s, "\n"), "\n")
|
||||||
|
isTripleQuoted := len(lines) >= 4 && (opts.DiffMode == '-' || opts.DiffMode == '+')
|
||||||
|
for i := 0; i < len(lines) && isTripleQuoted; i++ {
|
||||||
|
lines[i] = strings.TrimPrefix(strings.TrimSuffix(lines[i], "\r"), "\r") // trim leading/trailing carriage returns for legacy Windows endline support
|
||||||
|
isPrintable := func(r rune) bool {
|
||||||
|
return unicode.IsPrint(r) || r == '\t' // specially treat tab as printable
|
||||||
|
}
|
||||||
|
line := lines[i]
|
||||||
|
isTripleQuoted = !strings.HasPrefix(strings.TrimPrefix(line, prefix), `"""`) && !strings.HasPrefix(line, "...") && strings.TrimFunc(line, isPrintable) == "" && len(line) <= maxLen
|
||||||
|
}
|
||||||
|
if isTripleQuoted {
|
||||||
|
var list textList
|
||||||
|
list = append(list, textRecord{Diff: opts.DiffMode, Value: textLine(prefix + `"""`), ElideComma: true})
|
||||||
|
for i, line := range lines {
|
||||||
|
if numElided := len(lines) - i; i == maxLines-1 && numElided > 1 {
|
||||||
|
comment := commentString(fmt.Sprintf("%d elided lines", numElided))
|
||||||
|
list = append(list, textRecord{Diff: opts.DiffMode, Value: textEllipsis, ElideComma: true, Comment: comment})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
list = append(list, textRecord{Diff: opts.DiffMode, Value: textLine(line), ElideComma: true})
|
||||||
|
}
|
||||||
|
list = append(list, textRecord{Diff: opts.DiffMode, Value: textLine(prefix + `"""`), ElideComma: true})
|
||||||
|
return &textWrap{Prefix: "(", Value: list, Suffix: ")"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the string as a single-line quoted string.
|
||||||
|
if len(s) > maxLen+len(textEllipsis) {
|
||||||
|
return textLine(prefix + formatString(s[:maxLen]) + string(textEllipsis))
|
||||||
|
}
|
||||||
|
return textLine(prefix + formatString(s))
|
||||||
|
}
|
||||||
|
|
||||||
// formatMapKey formats v as if it were a map key.
|
// formatMapKey formats v as if it were a map key.
|
||||||
// The result is guaranteed to be a single line.
|
// The result is guaranteed to be a single line.
|
||||||
func formatMapKey(v reflect.Value, disambiguate bool, ptrs *pointerReferences) string {
|
func formatMapKey(v reflect.Value, disambiguate bool, ptrs *pointerReferences) string {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.4.3
|
|
||||||
- 1.5.3
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v ./...
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# How to contribute
|
|
||||||
|
|
||||||
We definitely welcome patches and contribution to this project!
|
|
||||||
|
|
||||||
### Legal requirements
|
|
||||||
|
|
||||||
In order to protect both you and ourselves, you will need to sign the
|
|
||||||
[Contributor License Agreement](https://cla.developers.google.com/clas).
|
|
||||||
|
|
||||||
You may have already signed it for other Google projects.
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
Paul Borman <borman@google.com>
|
|
||||||
bmatsuo
|
|
||||||
shawnps
|
|
||||||
theory
|
|
||||||
jboverfelt
|
|
||||||
dsymonds
|
|
||||||
cd1
|
|
||||||
wallclockbuilder
|
|
||||||
dansouza
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
# uuid 
|
|
||||||
The uuid package generates and inspects UUIDs based on
|
|
||||||
[RFC 4122](http://tools.ietf.org/html/rfc4122)
|
|
||||||
and DCE 1.1: Authentication and Security Services.
|
|
||||||
|
|
||||||
This package is based on the github.com/pborman/uuid package (previously named
|
|
||||||
code.google.com/p/go-uuid). It differs from these earlier packages in that
|
|
||||||
a UUID is a 16 byte array rather than a byte slice. One loss due to this
|
|
||||||
change is the ability to represent an invalid UUID (vs a NIL UUID).
|
|
||||||
|
|
||||||
###### Install
|
|
||||||
`go get github.com/google/uuid`
|
|
||||||
|
|
||||||
###### Documentation
|
|
||||||
[](http://godoc.org/github.com/google/uuid)
|
|
||||||
|
|
||||||
Full `go doc` style documentation for the package can be viewed online without
|
|
||||||
installing this package by using the GoDoc site here:
|
|
||||||
http://godoc.org/github.com/google/uuid
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Domain represents a Version 2 domain
|
|
||||||
type Domain byte
|
|
||||||
|
|
||||||
// Domain constants for DCE Security (Version 2) UUIDs.
|
|
||||||
const (
|
|
||||||
Person = Domain(0)
|
|
||||||
Group = Domain(1)
|
|
||||||
Org = Domain(2)
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDCESecurity returns a DCE Security (Version 2) UUID.
|
|
||||||
//
|
|
||||||
// The domain should be one of Person, Group or Org.
|
|
||||||
// On a POSIX system the id should be the users UID for the Person
|
|
||||||
// domain and the users GID for the Group. The meaning of id for
|
|
||||||
// the domain Org or on non-POSIX systems is site defined.
|
|
||||||
//
|
|
||||||
// For a given domain/id pair the same token may be returned for up to
|
|
||||||
// 7 minutes and 10 seconds.
|
|
||||||
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
|
|
||||||
uuid, err := NewUUID()
|
|
||||||
if err == nil {
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
|
|
||||||
uuid[9] = byte(domain)
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], id)
|
|
||||||
}
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
|
||||||
// domain with the id returned by os.Getuid.
|
|
||||||
//
|
|
||||||
// NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
func NewDCEPerson() (UUID, error) {
|
|
||||||
return NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
|
||||||
// domain with the id returned by os.Getgid.
|
|
||||||
//
|
|
||||||
// NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
func NewDCEGroup() (UUID, error) {
|
|
||||||
return NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain returns the domain for a Version 2 UUID. Domains are only defined
|
|
||||||
// for Version 2 UUIDs.
|
|
||||||
func (uuid UUID) Domain() Domain {
|
|
||||||
return Domain(uuid[9])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
|
|
||||||
// UUIDs.
|
|
||||||
func (uuid UUID) ID() uint32 {
|
|
||||||
return binary.BigEndian.Uint32(uuid[0:4])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) String() string {
|
|
||||||
switch d {
|
|
||||||
case Person:
|
|
||||||
return "Person"
|
|
||||||
case Group:
|
|
||||||
return "Group"
|
|
||||||
case Org:
|
|
||||||
return "Org"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("Domain%d", int(d))
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package uuid generates and inspects UUIDs.
|
|
||||||
//
|
|
||||||
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
|
|
||||||
// Services.
|
|
||||||
//
|
|
||||||
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
|
|
||||||
// maps or compared directly.
|
|
||||||
package uuid
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
module github.com/google/uuid
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Well known namespace IDs and UUIDs
|
|
||||||
var (
|
|
||||||
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
Nil UUID // empty UUID, all zeros
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewHash returns a new UUID derived from the hash of space concatenated with
|
|
||||||
// data generated by h. The hash should be at least 16 byte in length. The
|
|
||||||
// first 16 bytes of the hash are used to form the UUID. The version of the
|
|
||||||
// UUID will be the lower 4 bits of version. NewHash is used to implement
|
|
||||||
// NewMD5 and NewSHA1.
|
|
||||||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
|
||||||
h.Reset()
|
|
||||||
h.Write(space[:])
|
|
||||||
h.Write(data)
|
|
||||||
s := h.Sum(nil)
|
|
||||||
var uuid UUID
|
|
||||||
copy(uuid[:], s)
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
|
||||||
// supplied name space and data. It is the same as calling:
|
|
||||||
//
|
|
||||||
// NewHash(md5.New(), space, data, 3)
|
|
||||||
func NewMD5(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(md5.New(), space, data, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
|
||||||
// supplied name space and data. It is the same as calling:
|
|
||||||
//
|
|
||||||
// NewHash(sha1.New(), space, data, 5)
|
|
||||||
func NewSHA1(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(sha1.New(), space, data, 5)
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
|
||||||
func (uuid UUID) MarshalText() ([]byte, error) {
|
|
||||||
var js [36]byte
|
|
||||||
encodeHex(js[:], uuid)
|
|
||||||
return js[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
|
||||||
func (uuid *UUID) UnmarshalText(data []byte) error {
|
|
||||||
id, err := ParseBytes(data)
|
|
||||||
if err == nil {
|
|
||||||
*uuid = id
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary implements encoding.BinaryMarshaler.
|
|
||||||
func (uuid UUID) MarshalBinary() ([]byte, error) {
|
|
||||||
return uuid[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
|
||||||
func (uuid *UUID) UnmarshalBinary(data []byte) error {
|
|
||||||
if len(data) != 16 {
|
|
||||||
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
|
|
||||||
}
|
|
||||||
copy(uuid[:], data)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
nodeMu sync.Mutex
|
|
||||||
ifname string // name of interface being used
|
|
||||||
nodeID [6]byte // hardware for version 1 UUIDs
|
|
||||||
zeroID [6]byte // nodeID with only 0's
|
|
||||||
)
|
|
||||||
|
|
||||||
// NodeInterface returns the name of the interface from which the NodeID was
|
|
||||||
// derived. The interface "user" is returned if the NodeID was set by
|
|
||||||
// SetNodeID.
|
|
||||||
func NodeInterface() string {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
return ifname
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
|
|
||||||
// If name is "" then the first usable interface found will be used or a random
|
|
||||||
// Node ID will be generated. If a named interface cannot be found then false
|
|
||||||
// is returned.
|
|
||||||
//
|
|
||||||
// SetNodeInterface never fails when name is "".
|
|
||||||
func SetNodeInterface(name string) bool {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
return setNodeInterface(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setNodeInterface(name string) bool {
|
|
||||||
iname, addr := getHardwareInterface(name) // null implementation for js
|
|
||||||
if iname != "" && addr != nil {
|
|
||||||
ifname = iname
|
|
||||||
copy(nodeID[:], addr)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// We found no interfaces with a valid hardware address. If name
|
|
||||||
// does not specify a specific interface generate a random Node ID
|
|
||||||
// (section 4.1.6)
|
|
||||||
if name == "" {
|
|
||||||
ifname = "random"
|
|
||||||
randomBits(nodeID[:])
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
|
|
||||||
// if not already set.
|
|
||||||
func NodeID() []byte {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
if nodeID == zeroID {
|
|
||||||
setNodeInterface("")
|
|
||||||
}
|
|
||||||
nid := nodeID
|
|
||||||
return nid[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
|
|
||||||
// of id are used. If id is less than 6 bytes then false is returned and the
|
|
||||||
// Node ID is not set.
|
|
||||||
func SetNodeID(id []byte) bool {
|
|
||||||
if len(id) < 6 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
copy(nodeID[:], id)
|
|
||||||
ifname = "user"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
|
|
||||||
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) NodeID() []byte {
|
|
||||||
var node [6]byte
|
|
||||||
copy(node[:], uuid[10:])
|
|
||||||
return node[:]
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build js
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
// getHardwareInterface returns nil values for the JS version of the code.
|
|
||||||
// This remvoves the "net" dependency, because it is not used in the browser.
|
|
||||||
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
|
|
||||||
func getHardwareInterface(name string) (string, []byte) { return "", nil }
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
// Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !js
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
var interfaces []net.Interface // cached list of interfaces
|
|
||||||
|
|
||||||
// getHardwareInterface returns the name and hardware address of interface name.
|
|
||||||
// If name is "" then the name and hardware address of one of the system's
|
|
||||||
// interfaces is returned. If no interfaces are found (name does not exist or
|
|
||||||
// there are no interfaces) then "", nil is returned.
|
|
||||||
//
|
|
||||||
// Only addresses of at least 6 bytes are returned.
|
|
||||||
func getHardwareInterface(name string) (string, []byte) {
|
|
||||||
if interfaces == nil {
|
|
||||||
var err error
|
|
||||||
interfaces, err = net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, ifs := range interfaces {
|
|
||||||
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
|
|
||||||
return ifs.Name, ifs.HardwareAddr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
|
|
||||||
// Currently, database types that map to string and []byte are supported. Please
|
|
||||||
// consult database-specific driver documentation for matching types.
|
|
||||||
func (uuid *UUID) Scan(src interface{}) error {
|
|
||||||
switch src := src.(type) {
|
|
||||||
case nil:
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case string:
|
|
||||||
// if an empty UUID comes from a table, we return a null UUID
|
|
||||||
if src == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// see Parse for required string format
|
|
||||||
u, err := Parse(src)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Scan: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
*uuid = u
|
|
||||||
|
|
||||||
case []byte:
|
|
||||||
// if an empty UUID comes from a table, we return a null UUID
|
|
||||||
if len(src) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// assumes a simple slice of bytes if 16 bytes
|
|
||||||
// otherwise attempts to parse
|
|
||||||
if len(src) != 16 {
|
|
||||||
return uuid.Scan(string(src))
|
|
||||||
}
|
|
||||||
copy((*uuid)[:], src)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements sql.Valuer so that UUIDs can be written to databases
|
|
||||||
// transparently. Currently, UUIDs map to strings. Please consult
|
|
||||||
// database-specific driver documentation for matching types.
|
|
||||||
func (uuid UUID) Value() (driver.Value, error) {
|
|
||||||
return uuid.String(), nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
|
|
||||||
// 1582.
|
|
||||||
type Time int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
lillian = 2299160 // Julian day of 15 Oct 1582
|
|
||||||
unix = 2440587 // Julian day of 1 Jan 1970
|
|
||||||
epoch = unix - lillian // Days between epochs
|
|
||||||
g1582 = epoch * 86400 // seconds between epochs
|
|
||||||
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
timeMu sync.Mutex
|
|
||||||
lasttime uint64 // last time we returned
|
|
||||||
clockSeq uint16 // clock sequence for this run
|
|
||||||
|
|
||||||
timeNow = time.Now // for testing
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnixTime converts t the number of seconds and nanoseconds using the Unix
|
|
||||||
// epoch of 1 Jan 1970.
|
|
||||||
func (t Time) UnixTime() (sec, nsec int64) {
|
|
||||||
sec = int64(t - g1582ns100)
|
|
||||||
nsec = (sec % 10000000) * 100
|
|
||||||
sec /= 10000000
|
|
||||||
return sec, nsec
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
|
|
||||||
// clock sequence as well as adjusting the clock sequence as needed. An error
|
|
||||||
// is returned if the current time cannot be determined.
|
|
||||||
func GetTime() (Time, uint16, error) {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
return getTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTime() (Time, uint16, error) {
|
|
||||||
t := timeNow()
|
|
||||||
|
|
||||||
// If we don't have a clock sequence already, set one.
|
|
||||||
if clockSeq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
now := uint64(t.UnixNano()/100) + g1582ns100
|
|
||||||
|
|
||||||
// If time has gone backwards with this clock sequence then we
|
|
||||||
// increment the clock sequence
|
|
||||||
if now <= lasttime {
|
|
||||||
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
|
|
||||||
}
|
|
||||||
lasttime = now
|
|
||||||
return Time(now), clockSeq, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the current clock sequence, generating one if not
|
|
||||||
// already set. The clock sequence is only used for Version 1 UUIDs.
|
|
||||||
//
|
|
||||||
// The uuid package does not use global static storage for the clock sequence or
|
|
||||||
// the last time a UUID was generated. Unless SetClockSequence is used, a new
|
|
||||||
// random clock sequence is generated the first time a clock sequence is
|
|
||||||
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
|
|
||||||
func ClockSequence() int {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
return clockSequence()
|
|
||||||
}
|
|
||||||
|
|
||||||
func clockSequence() int {
|
|
||||||
if clockSeq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
return int(clockSeq & 0x3fff)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
|
|
||||||
// -1 causes a new sequence to be generated.
|
|
||||||
func SetClockSequence(seq int) {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
setClockSequence(seq)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setClockSequence(seq int) {
|
|
||||||
if seq == -1 {
|
|
||||||
var b [2]byte
|
|
||||||
randomBits(b[:]) // clock sequence
|
|
||||||
seq = int(b[0])<<8 | int(b[1])
|
|
||||||
}
|
|
||||||
oldSeq := clockSeq
|
|
||||||
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
|
||||||
if oldSeq != clockSeq {
|
|
||||||
lasttime = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
|
||||||
// uuid. The time is only defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) Time() Time {
|
|
||||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
|
||||||
return Time(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the clock sequence encoded in uuid.
|
|
||||||
// The clock sequence is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) ClockSequence() int {
|
|
||||||
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// randomBits completely fills slice b with random data.
|
|
||||||
func randomBits(b []byte) {
|
|
||||||
if _, err := io.ReadFull(rander, b); err != nil {
|
|
||||||
panic(err.Error()) // rand should never fail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xvalues returns the value of a byte as a hexadecimal digit or 255.
|
|
||||||
var xvalues = [256]byte{
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
}
|
|
||||||
|
|
||||||
// xtob converts hex characters x1 and x2 into a byte.
|
|
||||||
func xtob(x1, x2 byte) (byte, bool) {
|
|
||||||
b1 := xvalues[x1]
|
|
||||||
b2 := xvalues[x2]
|
|
||||||
return (b1 << 4) | b2, b1 != 255 && b2 != 255
|
|
||||||
}
|
|
||||||
|
|
@ -1,245 +0,0 @@
|
||||||
// Copyright 2018 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
|
||||||
// 4122.
|
|
||||||
type UUID [16]byte
|
|
||||||
|
|
||||||
// A Version represents a UUID's version.
|
|
||||||
type Version byte
|
|
||||||
|
|
||||||
// A Variant represents a UUID's variant.
|
|
||||||
type Variant byte
|
|
||||||
|
|
||||||
// Constants returned by Variant.
|
|
||||||
const (
|
|
||||||
Invalid = Variant(iota) // Invalid UUID
|
|
||||||
RFC4122 // The variant specified in RFC4122
|
|
||||||
Reserved // Reserved, NCS backward compatibility.
|
|
||||||
Microsoft // Reserved, Microsoft Corporation backward compatibility.
|
|
||||||
Future // Reserved for future definition.
|
|
||||||
)
|
|
||||||
|
|
||||||
var rander = rand.Reader // random function
|
|
||||||
|
|
||||||
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
|
||||||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
|
|
||||||
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
|
|
||||||
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
|
|
||||||
func Parse(s string) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
switch len(s) {
|
|
||||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36:
|
|
||||||
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36 + 9:
|
|
||||||
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
|
|
||||||
}
|
|
||||||
s = s[9:]
|
|
||||||
|
|
||||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
||||||
case 36 + 2:
|
|
||||||
s = s[1:]
|
|
||||||
|
|
||||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
case 32:
|
|
||||||
var ok bool
|
|
||||||
for i := range uuid {
|
|
||||||
uuid[i], ok = xtob(s[i*2], s[i*2+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
default:
|
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
|
|
||||||
}
|
|
||||||
// s is now at least 36 bytes long
|
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
for i, x := range [16]int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34} {
|
|
||||||
v, ok := xtob(s[x], s[x+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
|
|
||||||
func ParseBytes(b []byte) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
switch len(b) {
|
|
||||||
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
|
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
|
|
||||||
}
|
|
||||||
b = b[9:]
|
|
||||||
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
||||||
b = b[1:]
|
|
||||||
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
var ok bool
|
|
||||||
for i := 0; i < 32; i += 2 {
|
|
||||||
uuid[i/2], ok = xtob(b[i], b[i+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
default:
|
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
|
|
||||||
}
|
|
||||||
// s is now at least 36 bytes long
|
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
for i, x := range [16]int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34} {
|
|
||||||
v, ok := xtob(b[x], b[x+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParse is like Parse but panics if the string cannot be parsed.
|
|
||||||
// It simplifies safe initialization of global variables holding compiled UUIDs.
|
|
||||||
func MustParse(s string) UUID {
|
|
||||||
uuid, err := Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`uuid: Parse(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
|
|
||||||
// does not have a length of 16. The bytes are copied from the slice.
|
|
||||||
func FromBytes(b []byte) (uuid UUID, err error) {
|
|
||||||
err = uuid.UnmarshalBinary(b)
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must returns uuid if err is nil and panics otherwise.
|
|
||||||
func Must(uuid UUID, err error) UUID {
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
// , or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) String() string {
|
|
||||||
var buf [36]byte
|
|
||||||
encodeHex(buf[:], uuid)
|
|
||||||
return string(buf[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// URN returns the RFC 2141 URN form of uuid,
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) URN() string {
|
|
||||||
var buf [36 + 9]byte
|
|
||||||
copy(buf[:], "urn:uuid:")
|
|
||||||
encodeHex(buf[9:], uuid)
|
|
||||||
return string(buf[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeHex(dst []byte, uuid UUID) {
|
|
||||||
hex.Encode(dst, uuid[:4])
|
|
||||||
dst[8] = '-'
|
|
||||||
hex.Encode(dst[9:13], uuid[4:6])
|
|
||||||
dst[13] = '-'
|
|
||||||
hex.Encode(dst[14:18], uuid[6:8])
|
|
||||||
dst[18] = '-'
|
|
||||||
hex.Encode(dst[19:23], uuid[8:10])
|
|
||||||
dst[23] = '-'
|
|
||||||
hex.Encode(dst[24:], uuid[10:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variant returns the variant encoded in uuid.
|
|
||||||
func (uuid UUID) Variant() Variant {
|
|
||||||
switch {
|
|
||||||
case (uuid[8] & 0xc0) == 0x80:
|
|
||||||
return RFC4122
|
|
||||||
case (uuid[8] & 0xe0) == 0xc0:
|
|
||||||
return Microsoft
|
|
||||||
case (uuid[8] & 0xe0) == 0xe0:
|
|
||||||
return Future
|
|
||||||
default:
|
|
||||||
return Reserved
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version returns the version of uuid.
|
|
||||||
func (uuid UUID) Version() Version {
|
|
||||||
return Version(uuid[6] >> 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Version) String() string {
|
|
||||||
if v > 15 {
|
|
||||||
return fmt.Sprintf("BAD_VERSION_%d", v)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("VERSION_%d", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Variant) String() string {
|
|
||||||
switch v {
|
|
||||||
case RFC4122:
|
|
||||||
return "RFC4122"
|
|
||||||
case Reserved:
|
|
||||||
return "Reserved"
|
|
||||||
case Microsoft:
|
|
||||||
return "Microsoft"
|
|
||||||
case Future:
|
|
||||||
return "Future"
|
|
||||||
case Invalid:
|
|
||||||
return "Invalid"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("BadVariant%d", int(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRand sets the random number generator to r, which implements io.Reader.
|
|
||||||
// If r.Read returns an error when the package requests random data then
|
|
||||||
// a panic will be issued.
|
|
||||||
//
|
|
||||||
// Calling SetRand with nil sets the random number generator to the default
|
|
||||||
// generator.
|
|
||||||
func SetRand(r io.Reader) {
|
|
||||||
if r == nil {
|
|
||||||
rander = rand.Reader
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rander = r
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
|
|
||||||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
|
||||||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
|
||||||
// be set NewUUID returns nil. If clock sequence has not been set by
|
|
||||||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
|
||||||
// return the current NewUUID returns nil and an error.
|
|
||||||
//
|
|
||||||
// In most cases, New should be used.
|
|
||||||
func NewUUID() (UUID, error) {
|
|
||||||
nodeMu.Lock()
|
|
||||||
if nodeID == zeroID {
|
|
||||||
setNodeInterface("")
|
|
||||||
}
|
|
||||||
nodeMu.Unlock()
|
|
||||||
|
|
||||||
var uuid UUID
|
|
||||||
now, seq, err := GetTime()
|
|
||||||
if err != nil {
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeLow := uint32(now & 0xffffffff)
|
|
||||||
timeMid := uint16((now >> 32) & 0xffff)
|
|
||||||
timeHi := uint16((now >> 48) & 0x0fff)
|
|
||||||
timeHi |= 0x1000 // Version 1
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], timeLow)
|
|
||||||
binary.BigEndian.PutUint16(uuid[4:], timeMid)
|
|
||||||
binary.BigEndian.PutUint16(uuid[6:], timeHi)
|
|
||||||
binary.BigEndian.PutUint16(uuid[8:], seq)
|
|
||||||
copy(uuid[10:], nodeID[:])
|
|
||||||
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
// New creates a new random UUID or panics. New is equivalent to
|
|
||||||
// the expression
|
|
||||||
//
|
|
||||||
// uuid.Must(uuid.NewRandom())
|
|
||||||
func New() UUID {
|
|
||||||
return Must(NewRandom())
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRandom returns a Random (Version 4) UUID.
|
|
||||||
//
|
|
||||||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
|
||||||
// package.
|
|
||||||
//
|
|
||||||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
|
||||||
//
|
|
||||||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
|
||||||
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
|
||||||
// means the probability is about 0.00000000006 (6 × 10−11),
|
|
||||||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
|
||||||
// year and having one duplicate.
|
|
||||||
func NewRandom() (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
_, err := io.ReadFull(rander, uuid[:])
|
|
||||||
if err != nil {
|
|
||||||
return Nil, err
|
|
||||||
}
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
2
vendor/github.com/google/uuid/LICENSE → vendor/github.com/rickb777/date/LICENSE
generated
vendored
2
vendor/github.com/google/uuid/LICENSE → vendor/github.com/rickb777/date/LICENSE
generated
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2009,2014 Google Inc. All rights reserved.
|
Copyright (c) 2015 The Go Authors & Rick Beton. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2016 Rick Beton. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package period provides functionality for periods of time using ISO-8601 conventions.
|
||||||
|
// This deals with years, months, weeks/days, hours, minutes and seconds.
|
||||||
|
//
|
||||||
|
// Because of the vagaries of calendar systems, the meaning of year lengths, month lengths
|
||||||
|
// and even day lengths depends on context. So a period is not necessarily a fixed duration
|
||||||
|
// of time in terms of seconds.
|
||||||
|
//
|
||||||
|
// See https://en.wikipedia.org/wiki/ISO_8601#Durations
|
||||||
|
//
|
||||||
|
// Example representations:
|
||||||
|
//
|
||||||
|
// * "P2Y" is two years;
|
||||||
|
//
|
||||||
|
// * "P6M" is six months;
|
||||||
|
//
|
||||||
|
// * "P4D" is four days;
|
||||||
|
//
|
||||||
|
// * "P1W" is one week (seven days);
|
||||||
|
//
|
||||||
|
// * "PT3H" is three hours.
|
||||||
|
//
|
||||||
|
// * "PT20M" is twenty minutes.
|
||||||
|
//
|
||||||
|
// * "PT30S" is thirty seconds.
|
||||||
|
//
|
||||||
|
// These can be combined, for example:
|
||||||
|
//
|
||||||
|
// * "P3Y6M4W1D" is three years, 6 months, 4 weeks and one day.
|
||||||
|
//
|
||||||
|
// * "P2DT12H" is 2 days and 12 hours.
|
||||||
|
//
|
||||||
|
// Also, decimal fractions are supported to one decimal place. To comply with
|
||||||
|
// the standard, only the last non-zero component is allowed to have a fraction.
|
||||||
|
// For example
|
||||||
|
//
|
||||||
|
// * "P2.5Y" is 2.5 years.
|
||||||
|
//
|
||||||
|
// * "PT12M7.5S" is 12 minutes and 7.5 seconds.
|
||||||
|
//
|
||||||
|
package period
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
// Copyright 2015 Rick Beton. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package period
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rickb777/plural"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Format converts the period to human-readable form using the default localisation.
|
||||||
|
func (period Period) Format() string {
|
||||||
|
return period.FormatWithPeriodNames(PeriodYearNames, PeriodMonthNames, PeriodWeekNames, PeriodDayNames, PeriodHourNames, PeriodMinuteNames, PeriodSecondNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatWithPeriodNames converts the period to human-readable form in a localisable way.
|
||||||
|
func (period Period) FormatWithPeriodNames(yearNames, monthNames, weekNames, dayNames, hourNames, minNames, secNames plural.Plurals) string {
|
||||||
|
period = period.Abs()
|
||||||
|
|
||||||
|
parts := make([]string, 0)
|
||||||
|
parts = appendNonBlank(parts, yearNames.FormatFloat(absFloat10(period.years)))
|
||||||
|
parts = appendNonBlank(parts, monthNames.FormatFloat(absFloat10(period.months)))
|
||||||
|
|
||||||
|
if period.days > 0 || (period.IsZero()) {
|
||||||
|
if len(weekNames) > 0 {
|
||||||
|
weeks := period.days / 70
|
||||||
|
mdays := period.days % 70
|
||||||
|
//fmt.Printf("%v %#v - %d %d\n", period, period, weeks, mdays)
|
||||||
|
if weeks > 0 {
|
||||||
|
parts = appendNonBlank(parts, weekNames.FormatInt(int(weeks)))
|
||||||
|
}
|
||||||
|
if mdays > 0 || weeks == 0 {
|
||||||
|
parts = appendNonBlank(parts, dayNames.FormatFloat(absFloat10(mdays)))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parts = appendNonBlank(parts, dayNames.FormatFloat(absFloat10(period.days)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parts = appendNonBlank(parts, hourNames.FormatFloat(absFloat10(period.hours)))
|
||||||
|
parts = appendNonBlank(parts, minNames.FormatFloat(absFloat10(period.minutes)))
|
||||||
|
parts = appendNonBlank(parts, secNames.FormatFloat(absFloat10(period.seconds)))
|
||||||
|
|
||||||
|
return strings.Join(parts, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendNonBlank(parts []string, s string) []string {
|
||||||
|
if s == "" {
|
||||||
|
return parts
|
||||||
|
}
|
||||||
|
return append(parts, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeriodDayNames provides the English default format names for the days part of the period.
|
||||||
|
// This is a sequence of plurals where the first match is used, otherwise the last one is used.
|
||||||
|
// The last one must include a "%v" placeholder for the number.
|
||||||
|
var PeriodDayNames = plural.FromZero("%v days", "%v day", "%v days")
|
||||||
|
|
||||||
|
// PeriodWeekNames is as for PeriodDayNames but for weeks.
|
||||||
|
var PeriodWeekNames = plural.FromZero("", "%v week", "%v weeks")
|
||||||
|
|
||||||
|
// PeriodMonthNames is as for PeriodDayNames but for months.
|
||||||
|
var PeriodMonthNames = plural.FromZero("", "%v month", "%v months")
|
||||||
|
|
||||||
|
// PeriodYearNames is as for PeriodDayNames but for years.
|
||||||
|
var PeriodYearNames = plural.FromZero("", "%v year", "%v years")
|
||||||
|
|
||||||
|
// PeriodHourNames is as for PeriodDayNames but for hours.
|
||||||
|
var PeriodHourNames = plural.FromZero("", "%v hour", "%v hours")
|
||||||
|
|
||||||
|
// PeriodMinuteNames is as for PeriodDayNames but for minutes.
|
||||||
|
var PeriodMinuteNames = plural.FromZero("", "%v minute", "%v minutes")
|
||||||
|
|
||||||
|
// PeriodSecondNames is as for PeriodDayNames but for seconds.
|
||||||
|
var PeriodSecondNames = plural.FromZero("", "%v second", "%v seconds")
|
||||||
|
|
||||||
|
// String converts the period to ISO-8601 form.
|
||||||
|
func (period Period) String() string {
|
||||||
|
if period.IsZero() {
|
||||||
|
return "P0D"
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
if period.Sign() < 0 {
|
||||||
|
buf.WriteByte('-')
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteByte('P')
|
||||||
|
|
||||||
|
if period.years != 0 {
|
||||||
|
fmt.Fprintf(buf, "%gY", absFloat10(period.years))
|
||||||
|
}
|
||||||
|
if period.months != 0 {
|
||||||
|
fmt.Fprintf(buf, "%gM", absFloat10(period.months))
|
||||||
|
}
|
||||||
|
if period.days != 0 {
|
||||||
|
if period.days%70 == 0 {
|
||||||
|
fmt.Fprintf(buf, "%gW", absFloat10(period.days/7))
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(buf, "%gD", absFloat10(period.days))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if period.hours != 0 || period.minutes != 0 || period.seconds != 0 {
|
||||||
|
buf.WriteByte('T')
|
||||||
|
}
|
||||||
|
if period.hours != 0 {
|
||||||
|
fmt.Fprintf(buf, "%gH", absFloat10(period.hours))
|
||||||
|
}
|
||||||
|
if period.minutes != 0 {
|
||||||
|
fmt.Fprintf(buf, "%gM", absFloat10(period.minutes))
|
||||||
|
}
|
||||||
|
if period.seconds != 0 {
|
||||||
|
fmt.Fprintf(buf, "%gS", absFloat10(period.seconds))
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func absFloat10(v int16) float32 {
|
||||||
|
f := float32(v) / 10
|
||||||
|
if v < 0 {
|
||||||
|
return -f
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package period
|
||||||
|
|
||||||
|
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||||
|
// This also provides support for gob encoding.
|
||||||
|
func (period Period) MarshalBinary() ([]byte, error) {
|
||||||
|
// binary method would take more space in many cases, so we simply use text
|
||||||
|
return period.MarshalText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||||
|
// This also provides support for gob encoding.
|
||||||
|
func (period *Period) UnmarshalBinary(data []byte) error {
|
||||||
|
return period.UnmarshalText(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements the encoding.TextMarshaler interface for Periods.
|
||||||
|
func (period Period) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(period.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements the encoding.TextUnmarshaler interface for Periods.
|
||||||
|
func (period *Period) UnmarshalText(data []byte) (err error) {
|
||||||
|
u, err := Parse(string(data))
|
||||||
|
if err == nil {
|
||||||
|
*period = u
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
// Copyright 2015 Rick Beton. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package period
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MustParse is as per Parse except that it panics if the string cannot be parsed.
|
||||||
|
// This is intended for setup code; don't use it for user inputs.
|
||||||
|
func MustParse(value string) Period {
|
||||||
|
d, err := Parse(value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses strings that specify periods using ISO-8601 rules.
|
||||||
|
//
|
||||||
|
// In addition, a plus or minus sign can precede the period, e.g. "-P10D"
|
||||||
|
//
|
||||||
|
// The value is normalised, e.g. multiple of 12 months become years so "P24M"
|
||||||
|
// is the same as "P2Y". However, this is done without loss of precision, so
|
||||||
|
// for example whole numbers of days do not contribute to the months tally
|
||||||
|
// because the number of days per month is variable.
|
||||||
|
//
|
||||||
|
// The zero value can be represented in several ways: all of the following
|
||||||
|
// are equivalent: "P0Y", "P0M", "P0W", "P0D", "PT0H", PT0M", PT0S", and "P0".
|
||||||
|
// The canonical zero is "P0D".
|
||||||
|
func Parse(period string) (Period, error) {
|
||||||
|
return ParseWithNormalise(period, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseWithNormalise parses strings that specify periods using ISO-8601 rules
|
||||||
|
// with an option to specify whether to normalise parsed period components.
|
||||||
|
//
|
||||||
|
// In addition, a plus or minus sign can precede the period, e.g. "-P10D"
|
||||||
|
|
||||||
|
// The returned value is only normalised when normalise is set to `true`, and
|
||||||
|
// normalisation will convert e.g. multiple of 12 months into years so "P24M"
|
||||||
|
// is the same as "P2Y". However, this is done without loss of precision, so
|
||||||
|
// for example whole numbers of days do not contribute to the months tally
|
||||||
|
// because the number of days per month is variable.
|
||||||
|
//
|
||||||
|
// The zero value can be represented in several ways: all of the following
|
||||||
|
// are equivalent: "P0Y", "P0M", "P0W", "P0D", "PT0H", PT0M", PT0S", and "P0".
|
||||||
|
// The canonical zero is "P0D".
|
||||||
|
func ParseWithNormalise(period string, normalise bool) (Period, error) {
|
||||||
|
if period == "" {
|
||||||
|
return Period{}, fmt.Errorf("cannot parse a blank string as a period")
|
||||||
|
}
|
||||||
|
|
||||||
|
if period == "P0" {
|
||||||
|
return Period{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := period64{}
|
||||||
|
pcopy := period
|
||||||
|
if pcopy[0] == '-' {
|
||||||
|
result.neg = true
|
||||||
|
pcopy = pcopy[1:]
|
||||||
|
} else if pcopy[0] == '+' {
|
||||||
|
pcopy = pcopy[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if pcopy[0] != 'P' {
|
||||||
|
return Period{}, fmt.Errorf("expected 'P' period mark at the start: %s", period)
|
||||||
|
}
|
||||||
|
pcopy = pcopy[1:]
|
||||||
|
|
||||||
|
st := parseState{period, pcopy, false, nil}
|
||||||
|
t := strings.IndexByte(pcopy, 'T')
|
||||||
|
if t >= 0 {
|
||||||
|
st.pcopy = pcopy[t+1:]
|
||||||
|
|
||||||
|
result.hours, st = parseField(st, 'H')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'H' marker: %s", period)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.minutes, st = parseField(st, 'M')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'M' marker: %s", period)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.seconds, st = parseField(st, 'S')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'S' marker: %s", period)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(st.pcopy) != 0 {
|
||||||
|
return Period{}, fmt.Errorf("unexpected remaining components %s: %s", st.pcopy, period)
|
||||||
|
}
|
||||||
|
|
||||||
|
st.pcopy = pcopy[:t]
|
||||||
|
}
|
||||||
|
|
||||||
|
result.years, st = parseField(st, 'Y')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'Y' marker: %s", period)
|
||||||
|
}
|
||||||
|
result.months, st = parseField(st, 'M')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'M' marker: %s", period)
|
||||||
|
}
|
||||||
|
weeks, st := parseField(st, 'W')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'W' marker: %s", period)
|
||||||
|
}
|
||||||
|
|
||||||
|
days, st := parseField(st, 'D')
|
||||||
|
if st.err != nil {
|
||||||
|
return Period{}, fmt.Errorf("expected a number before the 'D' marker: %s", period)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(st.pcopy) != 0 {
|
||||||
|
return Period{}, fmt.Errorf("unexpected remaining components %s: %s", st.pcopy, period)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.days = weeks*7 + days
|
||||||
|
//fmt.Printf("%#v\n", st)
|
||||||
|
|
||||||
|
if !st.ok {
|
||||||
|
return Period{}, fmt.Errorf("expected 'Y', 'M', 'W', 'D', 'H', 'M', or 'S' marker: %s", period)
|
||||||
|
}
|
||||||
|
|
||||||
|
if normalise {
|
||||||
|
return result.normalise64(true).toPeriod(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toPeriod(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type parseState struct {
|
||||||
|
period, pcopy string
|
||||||
|
ok bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseField(st parseState, mark byte) (int64, parseState) {
|
||||||
|
//fmt.Printf("%c %#v\n", mark, st)
|
||||||
|
r := int64(0)
|
||||||
|
m := strings.IndexByte(st.pcopy, mark)
|
||||||
|
if m > 0 {
|
||||||
|
r, st.err = parseDecimalFixedPoint(st.pcopy[:m], st.period)
|
||||||
|
if st.err != nil {
|
||||||
|
return 0, st
|
||||||
|
}
|
||||||
|
st.pcopy = st.pcopy[m+1:]
|
||||||
|
st.ok = true
|
||||||
|
}
|
||||||
|
return r, st
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixed-point three decimal places
|
||||||
|
func parseDecimalFixedPoint(s, original string) (int64, error) {
|
||||||
|
//was := s
|
||||||
|
dec := strings.IndexByte(s, '.')
|
||||||
|
if dec < 0 {
|
||||||
|
dec = strings.IndexByte(s, ',')
|
||||||
|
}
|
||||||
|
|
||||||
|
if dec >= 0 {
|
||||||
|
dp := len(s) - dec
|
||||||
|
if dp > 1 {
|
||||||
|
s = s[:dec] + s[dec+1:dec+2]
|
||||||
|
} else {
|
||||||
|
s = s[:dec] + s[dec+1:] + "0"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s = s + "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
return strconv.ParseInt(s, 10, 64)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,746 @@
|
||||||
|
// Copyright 2015 Rick Beton. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package period
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const daysPerYearE4 int64 = 3652425 // 365.2425 days by the Gregorian rule
|
||||||
|
const daysPerMonthE4 int64 = 304369 // 30.4369 days per month
|
||||||
|
const daysPerMonthE6 int64 = 30436875 // 30.436875 days per month
|
||||||
|
|
||||||
|
const oneE4 int64 = 10000
|
||||||
|
const oneE5 int64 = 100000
|
||||||
|
const oneE6 int64 = 1000000
|
||||||
|
const oneE7 int64 = 10000000
|
||||||
|
|
||||||
|
const hundredMs = 100 * time.Millisecond
|
||||||
|
|
||||||
|
// reminder: int64 overflow is after 9,223,372,036,854,775,807 (math.MaxInt64)
|
||||||
|
|
||||||
|
// Period holds a period of time and provides conversion to/from ISO-8601 representations.
|
||||||
|
// Therefore there are six fields: years, months, days, hours, minutes, and seconds.
|
||||||
|
//
|
||||||
|
// In the ISO representation, decimal fractions are supported, although only the last non-zero
|
||||||
|
// component is allowed to have a fraction according to the Standard. For example "P2.5Y"
|
||||||
|
// is 2.5 years.
|
||||||
|
//
|
||||||
|
// However, in this implementation, the precision is limited to one decimal place only, by
|
||||||
|
// means of integers with fixed point arithmetic. (This avoids using float32 in the struct,
|
||||||
|
// so there are no problems testing equality using ==.)
|
||||||
|
//
|
||||||
|
// The implementation limits the range of possible values to ± 2^16 / 10 in each field.
|
||||||
|
// Note in particular that the range of years is limited to approximately ± 3276.
|
||||||
|
//
|
||||||
|
// The concept of weeks exists in string representations of periods, but otherwise weeks
|
||||||
|
// are unimportant. The period contains a number of days from which the number of weeks can
|
||||||
|
// be calculated when needed.
|
||||||
|
//
|
||||||
|
// Note that although fractional weeks can be parsed, they will never be returned via String().
|
||||||
|
// This is because the number of weeks is always inferred from the number of days.
|
||||||
|
//
|
||||||
|
type Period struct {
|
||||||
|
years, months, days, hours, minutes, seconds int16
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewYMD creates a simple period without any fractional parts. The fields are initialised verbatim
|
||||||
|
// without any normalisation; e.g. 12 months will not become 1 year. Use the Normalise method if you
|
||||||
|
// need to.
|
||||||
|
//
|
||||||
|
// All the parameters must have the same sign (otherwise a panic occurs).
|
||||||
|
func NewYMD(years, months, days int) Period {
|
||||||
|
return New(years, months, days, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHMS creates a simple period without any fractional parts. The fields are initialised verbatim
|
||||||
|
// without any normalisation; e.g. 120 seconds will not become 2 minutes. Use the Normalise method
|
||||||
|
// if you need to.
|
||||||
|
//
|
||||||
|
// All the parameters must have the same sign (otherwise a panic occurs).
|
||||||
|
func NewHMS(hours, minutes, seconds int) Period {
|
||||||
|
return New(0, 0, 0, hours, minutes, seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a simple period without any fractional parts. The fields are initialised verbatim
|
||||||
|
// without any normalisation; e.g. 120 seconds will not become 2 minutes. Use the Normalise method
|
||||||
|
// if you need to.
|
||||||
|
//
|
||||||
|
// All the parameters must have the same sign (otherwise a panic occurs).
|
||||||
|
func New(years, months, days, hours, minutes, seconds int) Period {
|
||||||
|
if (years >= 0 && months >= 0 && days >= 0 && hours >= 0 && minutes >= 0 && seconds >= 0) ||
|
||||||
|
(years <= 0 && months <= 0 && days <= 0 && hours <= 0 && minutes <= 0 && seconds <= 0) {
|
||||||
|
return Period{
|
||||||
|
int16(years) * 10, int16(months) * 10, int16(days) * 10,
|
||||||
|
int16(hours) * 10, int16(minutes) * 10, int16(seconds) * 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("Periods must have homogeneous signs; got P%dY%dM%dDT%dH%dM%dS",
|
||||||
|
years, months, days, hours, minutes, seconds))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO NewFloat
|
||||||
|
|
||||||
|
// NewOf converts a time duration to a Period, and also indicates whether the conversion is precise.
|
||||||
|
// Any time duration that spans more than ± 3276 hours will be approximated by assuming that there
|
||||||
|
// are 24 hours per day, 365.2425 days per year (as per Gregorian calendar rules), and a month
|
||||||
|
// being 1/12 of that (approximately 30.4369 days).
|
||||||
|
//
|
||||||
|
// The result is not always fully normalised; for time differences less than 3276 hours (about 4.5 months),
|
||||||
|
// it will contain zero in the years, months and days fields but the number of days may be up to 3275; this
|
||||||
|
// reduces errors arising from the variable lengths of months. For larger time differences, greater than
|
||||||
|
// 3276 hours, the days, months and years fields are used as well.
|
||||||
|
func NewOf(duration time.Duration) (p Period, precise bool) {
|
||||||
|
var sign int16 = 1
|
||||||
|
d := duration
|
||||||
|
if duration < 0 {
|
||||||
|
sign = -1
|
||||||
|
d = -duration
|
||||||
|
}
|
||||||
|
|
||||||
|
sign10 := sign * 10
|
||||||
|
|
||||||
|
totalHours := int64(d / time.Hour)
|
||||||
|
|
||||||
|
// check for 16-bit overflow - occurs near the 4.5 month mark
|
||||||
|
if totalHours < 3277 {
|
||||||
|
// simple HMS case
|
||||||
|
minutes := d % time.Hour / time.Minute
|
||||||
|
seconds := d % time.Minute / hundredMs
|
||||||
|
return Period{0, 0, 0, sign10 * int16(totalHours), sign10 * int16(minutes), sign * int16(seconds)}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDays := totalHours / 24 // ignoring daylight savings adjustments
|
||||||
|
|
||||||
|
if totalDays < 3277 {
|
||||||
|
hours := totalHours - totalDays*24
|
||||||
|
minutes := d % time.Hour / time.Minute
|
||||||
|
seconds := d % time.Minute / hundredMs
|
||||||
|
return Period{0, 0, sign10 * int16(totalDays), sign10 * int16(hours), sign10 * int16(minutes), sign * int16(seconds)}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO it is uncertain whether this is too imprecise and should be improved
|
||||||
|
years := (oneE4 * totalDays) / daysPerYearE4
|
||||||
|
months := ((oneE4 * totalDays) / daysPerMonthE4) - (12 * years)
|
||||||
|
hours := totalHours - totalDays*24
|
||||||
|
totalDays = ((totalDays * oneE4) - (daysPerMonthE4 * months) - (daysPerYearE4 * years)) / oneE4
|
||||||
|
return Period{sign10 * int16(years), sign10 * int16(months), sign10 * int16(totalDays), sign10 * int16(hours), 0, 0}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Between converts the span between two times to a period. Based on the Gregorian conversion
|
||||||
|
// algorithms of `time.Time`, the resultant period is precise.
|
||||||
|
//
|
||||||
|
// To improve precision, result is not always fully normalised; for time differences less than 3276 hours
|
||||||
|
// (about 4.5 months), it will contain zero in the years, months and days fields but the number of hours
|
||||||
|
// may be up to 3275; this reduces errors arising from the variable lengths of months. For larger time
|
||||||
|
// differences (greater than 3276 hours) the days, months and years fields are used as well.
|
||||||
|
//
|
||||||
|
// Remember that the resultant period does not retain any knowledge of the calendar, so any subsequent
|
||||||
|
// computations applied to the period can only be precise if they concern either the date (year, month,
|
||||||
|
// day) part, or the clock (hour, minute, second) part, but not both.
|
||||||
|
func Between(t1, t2 time.Time) (p Period) {
|
||||||
|
if t1.Location() != t2.Location() {
|
||||||
|
t2 = t2.In(t1.Location())
|
||||||
|
}
|
||||||
|
|
||||||
|
sign := 1
|
||||||
|
if t2.Before(t1) {
|
||||||
|
t1, t2, sign = t2, t1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
year, month, day, hour, min, sec, hundredth := daysDiff(t1, t2)
|
||||||
|
|
||||||
|
if sign < 0 {
|
||||||
|
p = New(-year, -month, -day, -hour, -min, -sec)
|
||||||
|
p.seconds -= int16(hundredth)
|
||||||
|
} else {
|
||||||
|
p = New(year, month, day, hour, min, sec)
|
||||||
|
p.seconds += int16(hundredth)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func daysDiff(t1, t2 time.Time) (year, month, day, hour, min, sec, hundredth int) {
|
||||||
|
duration := t2.Sub(t1)
|
||||||
|
|
||||||
|
hh1, mm1, ss1 := t1.Clock()
|
||||||
|
hh2, mm2, ss2 := t2.Clock()
|
||||||
|
|
||||||
|
day = int(duration / (24 * time.Hour))
|
||||||
|
|
||||||
|
hour = int(hh2 - hh1)
|
||||||
|
min = int(mm2 - mm1)
|
||||||
|
sec = int(ss2 - ss1)
|
||||||
|
hundredth = (t2.Nanosecond() - t1.Nanosecond()) / 100000000
|
||||||
|
|
||||||
|
// Normalize negative values
|
||||||
|
if sec < 0 {
|
||||||
|
sec += 60
|
||||||
|
min--
|
||||||
|
}
|
||||||
|
|
||||||
|
if min < 0 {
|
||||||
|
min += 60
|
||||||
|
hour--
|
||||||
|
}
|
||||||
|
|
||||||
|
if hour < 0 {
|
||||||
|
hour += 24
|
||||||
|
// no need to reduce day - it's calculated differently.
|
||||||
|
}
|
||||||
|
|
||||||
|
// test 16bit storage limit (with 1 fixed decimal place)
|
||||||
|
if day > 3276 {
|
||||||
|
y1, m1, d1 := t1.Date()
|
||||||
|
y2, m2, d2 := t2.Date()
|
||||||
|
year = y2 - y1
|
||||||
|
month = int(m2 - m1)
|
||||||
|
day = d2 - d1
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZero returns true if applied to a zero-length period.
|
||||||
|
func (period Period) IsZero() bool {
|
||||||
|
return period == Period{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPositive returns true if any field is greater than zero. By design, this also implies that
|
||||||
|
// all the other fields are greater than or equal to zero.
|
||||||
|
func (period Period) IsPositive() bool {
|
||||||
|
return period.years > 0 || period.months > 0 || period.days > 0 ||
|
||||||
|
period.hours > 0 || period.minutes > 0 || period.seconds > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNegative returns true if any field is negative. By design, this also implies that
|
||||||
|
// all the other fields are negative or zero.
|
||||||
|
func (period Period) IsNegative() bool {
|
||||||
|
return period.years < 0 || period.months < 0 || period.days < 0 ||
|
||||||
|
period.hours < 0 || period.minutes < 0 || period.seconds < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign returns +1 for positive periods and -1 for negative periods. If the period is zero, it returns zero.
|
||||||
|
func (period Period) Sign() int {
|
||||||
|
if period.IsZero() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if period.IsNegative() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlyYMD returns a new Period with only the year, month and day fields. The hour,
|
||||||
|
// minute and second fields are zeroed.
|
||||||
|
func (period Period) OnlyYMD() Period {
|
||||||
|
return Period{period.years, period.months, period.days, 0, 0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlyHMS returns a new Period with only the hour, minute and second fields. The year,
|
||||||
|
// month and day fields are zeroed.
|
||||||
|
func (period Period) OnlyHMS() Period {
|
||||||
|
return Period{0, 0, 0, period.hours, period.minutes, period.seconds}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abs converts a negative period to a positive one.
|
||||||
|
func (period Period) Abs() Period {
|
||||||
|
return Period{absInt16(period.years), absInt16(period.months), absInt16(period.days),
|
||||||
|
absInt16(period.hours), absInt16(period.minutes), absInt16(period.seconds)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func absInt16(v int16) int16 {
|
||||||
|
if v < 0 {
|
||||||
|
return -v
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negate changes the sign of the period.
|
||||||
|
func (period Period) Negate() Period {
|
||||||
|
return Period{-period.years, -period.months, -period.days, -period.hours, -period.minutes, -period.seconds}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds two periods together. Use this method along with Negate in order to subtract periods.
|
||||||
|
//
|
||||||
|
// The result is not normalised and may overflow arithmetically (to make this unlikely, use Normalise on
|
||||||
|
// the inputs before adding them).
|
||||||
|
func (period Period) Add(that Period) Period {
|
||||||
|
return Period{
|
||||||
|
period.years + that.years,
|
||||||
|
period.months + that.months,
|
||||||
|
period.days + that.days,
|
||||||
|
period.hours + that.hours,
|
||||||
|
period.minutes + that.minutes,
|
||||||
|
period.seconds + that.seconds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale a period by a multiplication factor. Obviously, this can both enlarge and shrink it,
|
||||||
|
// and change the sign if negative. The result is normalised.
|
||||||
|
//
|
||||||
|
// Bear in mind that the internal representation is limited by fixed-point arithmetic with one
|
||||||
|
// decimal place; each field is only int16.
|
||||||
|
//
|
||||||
|
// Known issue: scaling by a large reduction factor (i.e. much less than one) doesn't work properly.
|
||||||
|
func (period Period) Scale(factor float32) Period {
|
||||||
|
|
||||||
|
if -0.5 < factor && factor < 0.5 {
|
||||||
|
d, pr1 := period.Duration()
|
||||||
|
mul := float64(d) * float64(factor)
|
||||||
|
p2, pr2 := NewOf(time.Duration(mul))
|
||||||
|
return p2.Normalise(pr1 && pr2)
|
||||||
|
}
|
||||||
|
|
||||||
|
y := int64(float32(period.years) * factor)
|
||||||
|
m := int64(float32(period.months) * factor)
|
||||||
|
d := int64(float32(period.days) * factor)
|
||||||
|
hh := int64(float32(period.hours) * factor)
|
||||||
|
mm := int64(float32(period.minutes) * factor)
|
||||||
|
ss := int64(float32(period.seconds) * factor)
|
||||||
|
|
||||||
|
return (&period64{y, m, d, hh, mm, ss, false}).normalise64(true).toPeriod()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Years gets the whole number of years in the period.
|
||||||
|
// The result is the number of years and does not include any other field.
|
||||||
|
func (period Period) Years() int {
|
||||||
|
return int(period.YearsFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
// YearsFloat gets the number of years in the period, including a fraction if any is present.
|
||||||
|
// The result is the number of years and does not include any other field.
|
||||||
|
func (period Period) YearsFloat() float32 {
|
||||||
|
return float32(period.years) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// Months gets the whole number of months in the period.
|
||||||
|
// The result is the number of months and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that after normalisation, whole multiple of 12 months are added to
|
||||||
|
// the number of years, so the number of months will be reduced correspondingly.
|
||||||
|
func (period Period) Months() int {
|
||||||
|
return int(period.MonthsFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
// MonthsFloat gets the number of months in the period.
|
||||||
|
// The result is the number of months and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that after normalisation, whole multiple of 12 months are added to
|
||||||
|
// the number of years, so the number of months will be reduced correspondingly.
|
||||||
|
func (period Period) MonthsFloat() float32 {
|
||||||
|
return float32(period.months) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// Days gets the whole number of days in the period. This includes the implied
|
||||||
|
// number of weeks but does not include any other field.
|
||||||
|
func (period Period) Days() int {
|
||||||
|
return int(period.DaysFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
// DaysFloat gets the number of days in the period. This includes the implied
|
||||||
|
// number of weeks but does not include any other field.
|
||||||
|
func (period Period) DaysFloat() float32 {
|
||||||
|
return float32(period.days) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// Weeks calculates the number of whole weeks from the number of days. If the result
|
||||||
|
// would contain a fraction, it is truncated.
|
||||||
|
// The result is the number of weeks and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that weeks are synthetic: they are internally represented using days.
|
||||||
|
// See ModuloDays(), which returns the number of days excluding whole weeks.
|
||||||
|
func (period Period) Weeks() int {
|
||||||
|
return int(period.days) / 70
|
||||||
|
}
|
||||||
|
|
||||||
|
// WeeksFloat calculates the number of weeks from the number of days.
|
||||||
|
// The result is the number of weeks and does not include any other field.
|
||||||
|
func (period Period) WeeksFloat() float32 {
|
||||||
|
return float32(period.days) / 70
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModuloDays calculates the whole number of days remaining after the whole number of weeks
|
||||||
|
// has been excluded.
|
||||||
|
func (period Period) ModuloDays() int {
|
||||||
|
days := absInt16(period.days) % 70
|
||||||
|
f := int(days / 10)
|
||||||
|
if period.days < 0 {
|
||||||
|
return -f
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hours gets the whole number of hours in the period.
|
||||||
|
// The result is the number of hours and does not include any other field.
|
||||||
|
func (period Period) Hours() int {
|
||||||
|
return int(period.HoursFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
// HoursFloat gets the number of hours in the period.
|
||||||
|
// The result is the number of hours and does not include any other field.
|
||||||
|
func (period Period) HoursFloat() float32 {
|
||||||
|
return float32(period.hours) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minutes gets the whole number of minutes in the period.
|
||||||
|
// The result is the number of minutes and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that after normalisation, whole multiple of 60 minutes are added to
|
||||||
|
// the number of hours, so the number of minutes will be reduced correspondingly.
|
||||||
|
func (period Period) Minutes() int {
|
||||||
|
return int(period.MinutesFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinutesFloat gets the number of minutes in the period.
|
||||||
|
// The result is the number of minutes and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that after normalisation, whole multiple of 60 minutes are added to
|
||||||
|
// the number of hours, so the number of minutes will be reduced correspondingly.
|
||||||
|
func (period Period) MinutesFloat() float32 {
|
||||||
|
return float32(period.minutes) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seconds gets the whole number of seconds in the period.
|
||||||
|
// The result is the number of seconds and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that after normalisation, whole multiple of 60 seconds are added to
|
||||||
|
// the number of minutes, so the number of seconds will be reduced correspondingly.
|
||||||
|
func (period Period) Seconds() int {
|
||||||
|
return int(period.SecondsFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecondsFloat gets the number of seconds in the period.
|
||||||
|
// The result is the number of seconds and does not include any other field.
|
||||||
|
//
|
||||||
|
// Note that after normalisation, whole multiple of 60 seconds are added to
|
||||||
|
// the number of minutes, so the number of seconds will be reduced correspondingly.
|
||||||
|
func (period Period) SecondsFloat() float32 {
|
||||||
|
return float32(period.seconds) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTo adds the period to a time, returning the result.
|
||||||
|
// A flag is also returned that is true when the conversion was precise and false otherwise.
|
||||||
|
//
|
||||||
|
// When the period specifies hours, minutes and seconds only, the result is precise.
|
||||||
|
// Also, when the period specifies whole years, months and days (i.e. without fractions), the
|
||||||
|
// result is precise. However, when years, months or days contains fractions, the result
|
||||||
|
// is only an approximation (it assumes that all days are 24 hours and every year is 365.2425
|
||||||
|
// days, as per Gregorian calendar rules).
|
||||||
|
func (period Period) AddTo(t time.Time) (time.Time, bool) {
|
||||||
|
wholeYears := (period.years % 10) == 0
|
||||||
|
wholeMonths := (period.months % 10) == 0
|
||||||
|
wholeDays := (period.days % 10) == 0
|
||||||
|
|
||||||
|
if wholeYears && wholeMonths && wholeDays {
|
||||||
|
// in this case, time.AddDate provides an exact solution
|
||||||
|
stE3 := totalSecondsE3(period)
|
||||||
|
t1 := t.AddDate(int(period.years/10), int(period.months/10), int(period.days/10))
|
||||||
|
return t1.Add(stE3 * time.Millisecond), true
|
||||||
|
}
|
||||||
|
|
||||||
|
d, precise := period.Duration()
|
||||||
|
return t.Add(d), precise
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationApprox converts a period to the equivalent duration in nanoseconds.
|
||||||
|
// When the period specifies hours, minutes and seconds only, the result is precise.
|
||||||
|
// however, when the period specifies years, months and days, it is impossible to be precise
|
||||||
|
// because the result may depend on knowing date and timezone information, so the duration
|
||||||
|
// is estimated on the basis of a year being 365.2425 days (as per Gregorian calendar rules)
|
||||||
|
// and a month being 1/12 of a that; days are all assumed to be 24 hours long.
|
||||||
|
func (period Period) DurationApprox() time.Duration {
|
||||||
|
d, _ := period.Duration()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration converts a period to the equivalent duration in nanoseconds.
|
||||||
|
// A flag is also returned that is true when the conversion was precise and false otherwise.
|
||||||
|
//
|
||||||
|
// When the period specifies hours, minutes and seconds only, the result is precise.
|
||||||
|
// however, when the period specifies years, months and days, it is impossible to be precise
|
||||||
|
// because the result may depend on knowing date and timezone information, so the duration
|
||||||
|
// is estimated on the basis of a year being 365.2425 days as per Gregorian calendar rules)
|
||||||
|
// and a month being 1/12 of a that; days are all assumed to be 24 hours long.
|
||||||
|
func (period Period) Duration() (time.Duration, bool) {
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
tdE6 := time.Duration(totalDaysApproxE7(period) * 8640)
|
||||||
|
stE3 := totalSecondsE3(period)
|
||||||
|
return tdE6*time.Microsecond + stE3*time.Millisecond, tdE6 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func totalSecondsE3(period Period) time.Duration {
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
// and these are divided by 1E1
|
||||||
|
hhE3 := time.Duration(period.hours) * 360000
|
||||||
|
mmE3 := time.Duration(period.minutes) * 6000
|
||||||
|
ssE3 := time.Duration(period.seconds) * 100
|
||||||
|
return hhE3 + mmE3 + ssE3
|
||||||
|
}
|
||||||
|
|
||||||
|
func totalDaysApproxE7(period Period) int64 {
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
ydE6 := int64(period.years) * (daysPerYearE4 * 100)
|
||||||
|
mdE6 := int64(period.months) * daysPerMonthE6
|
||||||
|
ddE6 := int64(period.days) * oneE6
|
||||||
|
return ydE6 + mdE6 + ddE6
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalDaysApprox gets the approximate total number of days in the period. The approximation assumes
|
||||||
|
// a year is 365.2425 days as per Gregorian calendar rules) and a month is 1/12 of that. Whole
|
||||||
|
// multiples of 24 hours are also included in the calculation.
|
||||||
|
func (period Period) TotalDaysApprox() int {
|
||||||
|
pn := period.Normalise(false)
|
||||||
|
tdE6 := totalDaysApproxE7(pn)
|
||||||
|
hE6 := (int64(pn.hours) * oneE6) / 24
|
||||||
|
return int((tdE6 + hE6) / oneE7)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalMonthsApprox gets the approximate total number of months in the period. The days component
|
||||||
|
// is included by approximation, assuming a year is 365.2425 days (as per Gregorian calendar rules)
|
||||||
|
// and a month is 1/12 of that. Whole multiples of 24 hours are also included in the calculation.
|
||||||
|
func (period Period) TotalMonthsApprox() int {
|
||||||
|
pn := period.Normalise(false)
|
||||||
|
mE1 := int64(pn.years)*12 + int64(pn.months)
|
||||||
|
hE1 := int64(pn.hours) / 24
|
||||||
|
dE1 := ((int64(pn.days) + hE1) * oneE6) / daysPerMonthE6
|
||||||
|
return int((mE1 + dE1) / 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalise attempts to simplify the fields. It operates in either precise or imprecise mode.
|
||||||
|
//
|
||||||
|
// Because the number of hours per day is imprecise (due to daylight savings etc), and because
|
||||||
|
// the number of days per month is variable in the Gregorian calendar, there is a reluctance
|
||||||
|
// to transfer time too or from the days element. To give control over this, there are two modes.
|
||||||
|
//
|
||||||
|
// In precise mode:
|
||||||
|
// Multiples of 60 seconds become minutes.
|
||||||
|
// Multiples of 60 minutes become hours.
|
||||||
|
// Multiples of 12 months become years.
|
||||||
|
//
|
||||||
|
// Additionally, in imprecise mode:
|
||||||
|
// Multiples of 24 hours become days.
|
||||||
|
// Multiples of approx. 30.4 days become months.
|
||||||
|
//
|
||||||
|
// Note that leap seconds are disregarded: every minute is assumed to have 60 seconds.
|
||||||
|
func (period Period) Normalise(precise bool) Period {
|
||||||
|
const limit = 32670 - (32670 / 60)
|
||||||
|
|
||||||
|
// can we use a quicker algorithm for HHMMSS with int16 arithmetic?
|
||||||
|
if period.years == 0 && period.months == 0 &&
|
||||||
|
(!precise || period.days == 0) &&
|
||||||
|
period.hours > -limit && period.hours < limit {
|
||||||
|
|
||||||
|
return period.normaliseHHMMSS(precise)
|
||||||
|
}
|
||||||
|
|
||||||
|
// can we use a quicker algorithm for YYMM with int16 arithmetic?
|
||||||
|
if (period.years != 0 || period.months != 0) && //period.months%10 == 0 &&
|
||||||
|
period.days == 0 && period.hours == 0 && period.minutes == 0 && period.seconds == 0 {
|
||||||
|
|
||||||
|
return period.normaliseYYMM()
|
||||||
|
}
|
||||||
|
|
||||||
|
// do things the no-nonsense way using int64 arithmetic
|
||||||
|
return period.toPeriod64().normalise64(precise).toPeriod()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (period Period) normaliseHHMMSS(precise bool) Period {
|
||||||
|
s := period.Sign()
|
||||||
|
ap := period.Abs()
|
||||||
|
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
ap.minutes += (ap.seconds / 600) * 10
|
||||||
|
ap.seconds = ap.seconds % 600
|
||||||
|
|
||||||
|
ap.hours += (ap.minutes / 600) * 10
|
||||||
|
ap.minutes = ap.minutes % 600
|
||||||
|
|
||||||
|
// up to 36 hours stays as hours
|
||||||
|
if !precise && ap.hours > 360 {
|
||||||
|
ap.days += (ap.hours / 240) * 10
|
||||||
|
ap.hours = ap.hours % 240
|
||||||
|
}
|
||||||
|
|
||||||
|
d10 := ap.days % 10
|
||||||
|
if d10 != 0 && (ap.hours != 0 || ap.minutes != 0 || ap.seconds != 0) {
|
||||||
|
ap.hours += d10 * 24
|
||||||
|
ap.days -= d10
|
||||||
|
}
|
||||||
|
|
||||||
|
hh10 := ap.hours % 10
|
||||||
|
if hh10 != 0 {
|
||||||
|
ap.minutes += hh10 * 60
|
||||||
|
ap.hours -= hh10
|
||||||
|
}
|
||||||
|
|
||||||
|
mm10 := ap.minutes % 10
|
||||||
|
if mm10 != 0 {
|
||||||
|
ap.seconds += mm10 * 60
|
||||||
|
ap.minutes -= mm10
|
||||||
|
}
|
||||||
|
|
||||||
|
if s < 0 {
|
||||||
|
return ap.Negate()
|
||||||
|
}
|
||||||
|
return ap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (period Period) normaliseYYMM() Period {
|
||||||
|
s := period.Sign()
|
||||||
|
ap := period.Abs()
|
||||||
|
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
if ap.months > 129 {
|
||||||
|
ap.years += (ap.months / 120) * 10
|
||||||
|
ap.months = ap.months % 120
|
||||||
|
}
|
||||||
|
|
||||||
|
y10 := ap.years % 10
|
||||||
|
if y10 != 0 && (ap.years < 10 || ap.months != 0) {
|
||||||
|
ap.months += y10 * 12
|
||||||
|
ap.years -= y10
|
||||||
|
}
|
||||||
|
|
||||||
|
if s < 0 {
|
||||||
|
return ap.Negate()
|
||||||
|
}
|
||||||
|
return ap
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// used for stages in arithmetic
|
||||||
|
type period64 struct {
|
||||||
|
years, months, days, hours, minutes, seconds int64
|
||||||
|
neg bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (period Period) toPeriod64() *period64 {
|
||||||
|
return &period64{
|
||||||
|
int64(period.years), int64(period.months), int64(period.days),
|
||||||
|
int64(period.hours), int64(period.minutes), int64(period.seconds),
|
||||||
|
false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *period64) toPeriod() Period {
|
||||||
|
if p.neg {
|
||||||
|
return Period{
|
||||||
|
int16(-p.years), int16(-p.months), int16(-p.days),
|
||||||
|
int16(-p.hours), int16(-p.minutes), int16(-p.seconds),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Period{
|
||||||
|
int16(p.years), int16(p.months), int16(p.days),
|
||||||
|
int16(p.hours), int16(p.minutes), int16(p.seconds),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *period64) normalise64(precise bool) *period64 {
|
||||||
|
return p.abs().rippleUp(precise).moveFractionToRight()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *period64) abs() *period64 {
|
||||||
|
|
||||||
|
if !p.neg {
|
||||||
|
if p.years < 0 {
|
||||||
|
p.years = -p.years
|
||||||
|
p.neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.months < 0 {
|
||||||
|
p.months = -p.months
|
||||||
|
p.neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.days < 0 {
|
||||||
|
p.days = -p.days
|
||||||
|
p.neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.hours < 0 {
|
||||||
|
p.hours = -p.hours
|
||||||
|
p.neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.minutes < 0 {
|
||||||
|
p.minutes = -p.minutes
|
||||||
|
p.neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.seconds < 0 {
|
||||||
|
p.seconds = -p.seconds
|
||||||
|
p.neg = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *period64) rippleUp(precise bool) *period64 {
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
|
||||||
|
p.minutes = p.minutes + (p.seconds/600)*10
|
||||||
|
p.seconds = p.seconds % 600
|
||||||
|
|
||||||
|
p.hours = p.hours + (p.minutes/600)*10
|
||||||
|
p.minutes = p.minutes % 600
|
||||||
|
|
||||||
|
// 32670-(32670/60)-(32670/3600) = 32760 - 546 - 9.1 = 32204.9
|
||||||
|
if !precise || p.hours > 32204 {
|
||||||
|
p.days += (p.hours / 240) * 10
|
||||||
|
p.hours = p.hours % 240
|
||||||
|
}
|
||||||
|
|
||||||
|
if !precise || p.days > 32760 {
|
||||||
|
dE6 := p.days * oneE6
|
||||||
|
p.months += dE6 / daysPerMonthE6
|
||||||
|
p.days = (dE6 % daysPerMonthE6) / oneE6
|
||||||
|
}
|
||||||
|
|
||||||
|
p.years = p.years + (p.months/120)*10
|
||||||
|
p.months = p.months % 120
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// moveFractionToRight applies the rule that only the smallest field is permitted to have a decimal fraction.
|
||||||
|
func (p *period64) moveFractionToRight() *period64 {
|
||||||
|
// remember that the fields are all fixed-point 1E1
|
||||||
|
|
||||||
|
y10 := p.years % 10
|
||||||
|
if y10 != 0 && (p.months != 0 || p.days != 0 || p.hours != 0 || p.minutes != 0 || p.seconds != 0) {
|
||||||
|
p.months += y10 * 12
|
||||||
|
p.years = (p.years / 10) * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
m10 := p.months % 10
|
||||||
|
if m10 != 0 && (p.days != 0 || p.hours != 0 || p.minutes != 0 || p.seconds != 0) {
|
||||||
|
p.days += (m10 * daysPerMonthE6) / oneE6
|
||||||
|
p.months = (p.months / 10) * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
d10 := p.days % 10
|
||||||
|
if d10 != 0 && (p.hours != 0 || p.minutes != 0 || p.seconds != 0) {
|
||||||
|
p.hours += d10 * 24
|
||||||
|
p.days = (p.days / 10) * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
hh10 := p.hours % 10
|
||||||
|
if hh10 != 0 && (p.minutes != 0 || p.seconds != 0) {
|
||||||
|
p.minutes += hh10 * 60
|
||||||
|
p.hours = (p.hours / 10) * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
mm10 := p.minutes % 10
|
||||||
|
if mm10 != 0 && p.seconds != 0 {
|
||||||
|
p.seconds += mm10 * 60
|
||||||
|
p.minutes = (p.minutes / 10) * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj/
|
||||||
|
_test/
|
||||||
|
vendor/
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
*.out
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- tip
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go get -t -v .
|
||||||
|
- go get github.com/mattn/goveralls
|
||||||
|
|
||||||
|
script:
|
||||||
|
- ./build+test.sh
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2016, Rick Beton
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of plural nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# plural - Simple Go API for Pluralisation.
|
||||||
|
|
||||||
|
[](https://godoc.org/github.com/rickb777/plural)
|
||||||
|
[](https://travis-ci.org/rickb777/plural)
|
||||||
|
[](https://coveralls.io/github/rickb777/plural?branch=master)
|
||||||
|
[](https://goreportcard.com/report/github.com/rickb777/plural)
|
||||||
|
[](https://github.com/rickb777/plural/issues)
|
||||||
|
|
||||||
|
Package plural provides simple support for localising plurals in a flexible range of different styles.
|
||||||
|
|
||||||
|
There are considerable differences around the world in the way plurals are handled. This is a simple
|
||||||
|
but competent API for catering with these differences when presenting to people formatted text with numbers.
|
||||||
|
|
||||||
|
This package is able to format **countable things** and **continuous values**. It can handle integers
|
||||||
|
and floating point numbers equally and this allows you to decide to what extent each is appropriate.
|
||||||
|
|
||||||
|
For example, `2 cars` might weigh `1.6 tonnes`; both categories are covered.
|
||||||
|
|
||||||
|
This API is deliberately simple; it doesn't address the full gamut of internationalisation. If that's
|
||||||
|
what you need, you should consider products such as https://github.com/nicksnyder/go-i18n instead.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
go get -u github.com/rickb777/plural
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
This library has been in reliable production use for some time. Versioning follows the well-known semantic version pattern.
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
cd $(dirname $0)
|
||||||
|
PATH=$HOME/go/bin:$GOPATH/bin:$PATH
|
||||||
|
|
||||||
|
if ! type -p goveralls; then
|
||||||
|
echo go get github.com/mattn/goveralls
|
||||||
|
go get github.com/mattn/goveralls
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo date...
|
||||||
|
go test -v -covermode=count -coverprofile=date.out .
|
||||||
|
go tool cover -func=date.out
|
||||||
|
[ -z "$COVERALLS_TOKEN" ] || goveralls -coverprofile=date.out -service=travis-ci -repotoken $COVERALLS_TOKEN
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2016 Rick Beton. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package plural provides simple support for localising plurals in a flexible range of different styles.
|
||||||
|
//
|
||||||
|
// There are considerable differences around the world in the way plurals are handled. This is
|
||||||
|
// a simple but competent API for catering with these differences when presenting to people formatted text with numbers.
|
||||||
|
//
|
||||||
|
// This package is able to format countable things and continuous values. It can handle integers
|
||||||
|
// and floating point numbers equally and this allows you to decide to what extent each is appropriate.
|
||||||
|
//
|
||||||
|
// For example, "2 cars" might weigh "1.6 tonnes"; both categories are covered.
|
||||||
|
//
|
||||||
|
// This API is deliberately simple; it doesn't address the full gamut of internationalisation. If that's
|
||||||
|
// what you need, you should consider products such as https://github.com/nicksnyder/go-i18n instead.
|
||||||
|
//
|
||||||
|
// Please see the examples and associated api documentation.
|
||||||
|
//
|
||||||
|
package plural
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/rickb777/plural
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
package plural
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Case is the inner element of this API and describes one case. When the number to be described
|
||||||
|
// matches the number here, the corresponding format string will be used. If the format string
|
||||||
|
// includes '%', then fmt.Sprintf will be used. Otherwise the format string will be returned verbatim.
|
||||||
|
type Case struct {
|
||||||
|
Number int
|
||||||
|
Format string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plurals provides a list of plural cases in the order they will be searched.
|
||||||
|
// For plurals of continuous ranges (e.g. weight), the cases must be in ascending number order.
|
||||||
|
// For plurals of discrete ranges (i.e. integers), the cases can be in any order you require,
|
||||||
|
// but will conventionally be in ascending number order.
|
||||||
|
// If no match is found, the last case will be used.
|
||||||
|
type Plurals []Case
|
||||||
|
|
||||||
|
// Format searches through the plural cases for the first match. If none is found, the last
|
||||||
|
// case is used. The value passed in can be any number type, or pointer to a number type, except
|
||||||
|
// complex numbers are not supported. The value will be converted to an int in order to
|
||||||
|
// find the first case that matches.
|
||||||
|
// The only possible error arises if value has a type that is not numeric.
|
||||||
|
// It panics if 'plurals' is empty.
|
||||||
|
func (plurals Plurals) Format(value interface{}) (string, error) {
|
||||||
|
switch x := value.(type) {
|
||||||
|
case int:
|
||||||
|
return plurals.FormatInt(x), nil
|
||||||
|
case int8:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case int16:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case int32:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case int64:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case uint8:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case uint16:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case uint32:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case uint64:
|
||||||
|
return plurals.FormatInt(int(x)), nil
|
||||||
|
case float32:
|
||||||
|
return plurals.FormatFloat(x), nil
|
||||||
|
case float64:
|
||||||
|
return plurals.FormatFloat(float32(x)), nil
|
||||||
|
|
||||||
|
case *int:
|
||||||
|
return plurals.FormatInt(*x), nil
|
||||||
|
case *int8:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *int16:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *int32:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *int64:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *uint:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *uint8:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *uint16:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *uint32:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *uint64:
|
||||||
|
return plurals.FormatInt(int(*x)), nil
|
||||||
|
case *float32:
|
||||||
|
return plurals.FormatFloat(*x), nil
|
||||||
|
case *float64:
|
||||||
|
return plurals.FormatFloat(float32(*x)), nil
|
||||||
|
|
||||||
|
case nil:
|
||||||
|
return "", fmt.Errorf("Unexpected nil value for %s", plurals)
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("Unexpected type %T for %v", x, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatInt expresses an int in plural form. It panics if 'plurals' is empty.
|
||||||
|
func (plurals Plurals) FormatInt(value int) string {
|
||||||
|
for _, c := range plurals {
|
||||||
|
if value == c.Number {
|
||||||
|
return c.FormatInt(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := plurals[len(plurals)-1]
|
||||||
|
return c.FormatInt(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatFloat expresses a float32 in plural form. It panics if 'plurals' is empty.
|
||||||
|
func (plurals Plurals) FormatFloat(value float32) string {
|
||||||
|
for _, c := range plurals {
|
||||||
|
if value <= float32(c.Number) {
|
||||||
|
return c.FormatFloat(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := plurals[len(plurals)-1]
|
||||||
|
return c.FormatFloat(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatInt renders a specific case with a given value.
|
||||||
|
func (c Case) FormatInt(value int) string {
|
||||||
|
if strings.IndexByte(c.Format, '%') < 0 {
|
||||||
|
return c.Format
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(c.Format, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatFloat renders a specific case with a given value.
|
||||||
|
func (c Case) FormatFloat(value float32) string {
|
||||||
|
if strings.IndexByte(c.Format, '%') < 0 {
|
||||||
|
return c.Format
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(c.Format, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// String implements io.Stringer.
|
||||||
|
func (plurals Plurals) String() string {
|
||||||
|
ss := make([]string, 0, len(plurals))
|
||||||
|
for _, c := range plurals {
|
||||||
|
ss = append(ss, c.String())
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Plurals(%s)", strings.Join(ss, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements io.Stringer.
|
||||||
|
func (c Case) String() string {
|
||||||
|
return fmt.Sprintf("{%v -> %q}", c.Number, c.Format)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ByOrdinal constructs a simple set of cases using small ordinals (0, 1, 2, 3 etc), which is a
|
||||||
|
// common requirement. It is an alias for FromZero.
|
||||||
|
func ByOrdinal(zeroth string, rest ...string) Plurals {
|
||||||
|
return FromZero(zeroth, rest...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromZero constructs a simple set of cases using small ordinals (0, 1, 2, 3 etc), which is a
|
||||||
|
// common requirement. It prevents creation of a Plurals list that is empty, which would be invalid.
|
||||||
|
//
|
||||||
|
// The 'zeroth' string becomes Case{0, first}. The rest are appended similarly. Notice that the
|
||||||
|
// counting starts from zero.
|
||||||
|
//
|
||||||
|
// So
|
||||||
|
//
|
||||||
|
// FromZero("nothing", "%v thing", "%v things")
|
||||||
|
//
|
||||||
|
// is simply a shorthand for
|
||||||
|
//
|
||||||
|
// Plurals{Case{0, "nothing"}, Case{1, "%v thing"}, Case{2, "%v things"}}
|
||||||
|
//
|
||||||
|
// which would also be valid but a little more verbose.
|
||||||
|
//
|
||||||
|
// This helper function is less flexible than constructing Plurals directly, but covers many common
|
||||||
|
// situations.
|
||||||
|
func FromZero(zeroth string, rest ...string) Plurals {
|
||||||
|
p := make(Plurals, 0, len(rest)+1)
|
||||||
|
p = append(p, Case{0, zeroth})
|
||||||
|
for i, c := range rest {
|
||||||
|
p = append(p, Case{i+1, c})
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOne constructs a simple set of cases using small positive numbers (1, 2, 3 etc), which is a
|
||||||
|
// common requirement. It prevents creation of a Plurals list that is empty, which would be invalid.
|
||||||
|
//
|
||||||
|
// The 'first' string becomes Case{1, first}. The rest are appended similarly. Notice that the
|
||||||
|
// counting starts from one.
|
||||||
|
//
|
||||||
|
// So
|
||||||
|
//
|
||||||
|
// FromOne("%v thing", "%v things")
|
||||||
|
//
|
||||||
|
// is simply a shorthand for
|
||||||
|
//
|
||||||
|
// Plurals{Case{1, "%v thing"}, Case{2, "%v things"}}
|
||||||
|
//
|
||||||
|
// which would also be valid but a little more verbose.
|
||||||
|
//
|
||||||
|
// Note the behaviour of formatting when the count is zero. As a consequence of Format evaluating
|
||||||
|
// the cases in order, FromOne(...).FormatInt(0) will pick the last case you provide, not the first.
|
||||||
|
//
|
||||||
|
// This helper function is less flexible than constructing Plurals directly, but covers many common
|
||||||
|
// situations.
|
||||||
|
func FromOne(first string, rest ...string) Plurals {
|
||||||
|
p := make(Plurals, 0, len(rest)+1)
|
||||||
|
p = append(p, Case{1, first})
|
||||||
|
for i, c := range rest {
|
||||||
|
p = append(p, Case{i+2, c})
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
@ -325,6 +325,7 @@ includes_OpenBSD='
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
#include <sys/sched.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -507,6 +508,8 @@ ccflags="$@"
|
||||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||||
$2 ~ /^CAN_/ ||
|
$2 ~ /^CAN_/ ||
|
||||||
$2 ~ /^CAP_/ ||
|
$2 ~ /^CAP_/ ||
|
||||||
|
$2 ~ /^CP_/ ||
|
||||||
|
$2 ~ /^CPUSTATES$/ ||
|
||||||
$2 ~ /^ALG_/ ||
|
$2 ~ /^ALG_/ ||
|
||||||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
|
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
|
||||||
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
|
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
|
||||||
|
|
|
||||||
|
|
@ -527,6 +527,23 @@ func SysctlClockinfo(name string) (*Clockinfo, error) {
|
||||||
return &ci, nil
|
return &ci, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SysctlTimeval(name string) (*Timeval, error) {
|
||||||
|
mib, err := sysctlmib(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tv Timeval
|
||||||
|
n := uintptr(unsafe.Sizeof(tv))
|
||||||
|
if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if n != unsafe.Sizeof(tv) {
|
||||||
|
return nil, EIO
|
||||||
|
}
|
||||||
|
return &tv, nil
|
||||||
|
}
|
||||||
|
|
||||||
//sys utimes(path string, timeval *[2]Timeval) (err error)
|
//sys utimes(path string, timeval *[2]Timeval) (err error)
|
||||||
|
|
||||||
func Utimes(path string, tv []Timeval) error {
|
func Utimes(path string, tv []Timeval) error {
|
||||||
|
|
|
||||||
|
|
@ -2122,6 +2122,18 @@ func Klogset(typ int, arg int) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoteIovec is Iovec with the pointer replaced with an integer.
|
||||||
|
// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
|
||||||
|
// refers to a location in a different process' address space, which
|
||||||
|
// would confuse the Go garbage collector.
|
||||||
|
type RemoteIovec struct {
|
||||||
|
Base uintptr
|
||||||
|
Len int
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
|
||||||
|
//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unimplemented
|
* Unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,13 @@ const (
|
||||||
BRKINT = 0x2
|
BRKINT = 0x2
|
||||||
CFLUSH = 0xf
|
CFLUSH = 0xf
|
||||||
CLOCAL = 0x8000
|
CLOCAL = 0x8000
|
||||||
|
CPUSTATES = 0x6
|
||||||
|
CP_IDLE = 0x5
|
||||||
|
CP_INTR = 0x4
|
||||||
|
CP_NICE = 0x1
|
||||||
|
CP_SPIN = 0x3
|
||||||
|
CP_SYS = 0x2
|
||||||
|
CP_USER = 0x0
|
||||||
CREAD = 0x800
|
CREAD = 0x800
|
||||||
CRTSCTS = 0x10000
|
CRTSCTS = 0x10000
|
||||||
CS5 = 0x0
|
CS5 = 0x0
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,13 @@ const (
|
||||||
CLOCK_REALTIME = 0x0
|
CLOCK_REALTIME = 0x0
|
||||||
CLOCK_THREAD_CPUTIME_ID = 0x4
|
CLOCK_THREAD_CPUTIME_ID = 0x4
|
||||||
CLOCK_UPTIME = 0x5
|
CLOCK_UPTIME = 0x5
|
||||||
|
CPUSTATES = 0x6
|
||||||
|
CP_IDLE = 0x5
|
||||||
|
CP_INTR = 0x4
|
||||||
|
CP_NICE = 0x1
|
||||||
|
CP_SPIN = 0x3
|
||||||
|
CP_SYS = 0x2
|
||||||
|
CP_USER = 0x0
|
||||||
CREAD = 0x800
|
CREAD = 0x800
|
||||||
CRTSCTS = 0x10000
|
CRTSCTS = 0x10000
|
||||||
CS5 = 0x0
|
CS5 = 0x0
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,13 @@ const (
|
||||||
BRKINT = 0x2
|
BRKINT = 0x2
|
||||||
CFLUSH = 0xf
|
CFLUSH = 0xf
|
||||||
CLOCAL = 0x8000
|
CLOCAL = 0x8000
|
||||||
|
CPUSTATES = 0x6
|
||||||
|
CP_IDLE = 0x5
|
||||||
|
CP_INTR = 0x4
|
||||||
|
CP_NICE = 0x1
|
||||||
|
CP_SPIN = 0x3
|
||||||
|
CP_SYS = 0x2
|
||||||
|
CP_USER = 0x0
|
||||||
CREAD = 0x800
|
CREAD = 0x800
|
||||||
CRTSCTS = 0x10000
|
CRTSCTS = 0x10000
|
||||||
CS5 = 0x0
|
CS5 = 0x0
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,13 @@ const (
|
||||||
CLOCK_REALTIME = 0x0
|
CLOCK_REALTIME = 0x0
|
||||||
CLOCK_THREAD_CPUTIME_ID = 0x4
|
CLOCK_THREAD_CPUTIME_ID = 0x4
|
||||||
CLOCK_UPTIME = 0x5
|
CLOCK_UPTIME = 0x5
|
||||||
|
CPUSTATES = 0x6
|
||||||
|
CP_IDLE = 0x5
|
||||||
|
CP_INTR = 0x4
|
||||||
|
CP_NICE = 0x1
|
||||||
|
CP_SPIN = 0x3
|
||||||
|
CP_SYS = 0x2
|
||||||
|
CP_USER = 0x0
|
||||||
CREAD = 0x800
|
CREAD = 0x800
|
||||||
CRTSCTS = 0x10000
|
CRTSCTS = 0x10000
|
||||||
CS5 = 0x0
|
CS5 = 0x0
|
||||||
|
|
|
||||||
|
|
@ -1847,6 +1847,52 @@ func openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error)
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(localIov) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&localIov[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(remoteIov) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&remoteIov[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PROCESS_VM_READV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) {
|
||||||
|
var _p0 unsafe.Pointer
|
||||||
|
if len(localIov) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&localIov[0])
|
||||||
|
} else {
|
||||||
|
_p0 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
var _p1 unsafe.Pointer
|
||||||
|
if len(remoteIov) > 0 {
|
||||||
|
_p1 = unsafe.Pointer(&remoteIov[0])
|
||||||
|
} else {
|
||||||
|
_p1 = unsafe.Pointer(&_zero)
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall6(SYS_PROCESS_VM_WRITEV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func pipe2(p *[2]_C_int, flags int) (err error) {
|
func pipe2(p *[2]_C_int, flags int) (err error) {
|
||||||
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
|
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,9 @@ func Every(interval time.Duration) Limit {
|
||||||
//
|
//
|
||||||
// The methods AllowN, ReserveN, and WaitN consume n tokens.
|
// The methods AllowN, ReserveN, and WaitN consume n tokens.
|
||||||
type Limiter struct {
|
type Limiter struct {
|
||||||
|
mu sync.Mutex
|
||||||
limit Limit
|
limit Limit
|
||||||
burst int
|
burst int
|
||||||
|
|
||||||
mu sync.Mutex
|
|
||||||
tokens float64
|
tokens float64
|
||||||
// last is the last time the limiter's tokens field was updated
|
// last is the last time the limiter's tokens field was updated
|
||||||
last time.Time
|
last time.Time
|
||||||
|
|
@ -76,6 +75,8 @@ func (lim *Limiter) Limit() Limit {
|
||||||
// Burst values allow more events to happen at once.
|
// Burst values allow more events to happen at once.
|
||||||
// A zero Burst allows no events, unless limit == Inf.
|
// A zero Burst allows no events, unless limit == Inf.
|
||||||
func (lim *Limiter) Burst() int {
|
func (lim *Limiter) Burst() int {
|
||||||
|
lim.mu.Lock()
|
||||||
|
defer lim.mu.Unlock()
|
||||||
return lim.burst
|
return lim.burst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +230,7 @@ func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
|
||||||
lim.mu.Unlock()
|
lim.mu.Unlock()
|
||||||
|
|
||||||
if n > burst && limit != Inf {
|
if n > burst && limit != Inf {
|
||||||
return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst)
|
return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, burst)
|
||||||
}
|
}
|
||||||
// Check if ctx is already cancelled
|
// Check if ctx is already cancelled
|
||||||
select {
|
select {
|
||||||
|
|
@ -359,6 +360,7 @@ func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duratio
|
||||||
|
|
||||||
// advance calculates and returns an updated state for lim resulting from the passage of time.
|
// advance calculates and returns an updated state for lim resulting from the passage of time.
|
||||||
// lim is not changed.
|
// lim is not changed.
|
||||||
|
// advance requires that lim.mu is held.
|
||||||
func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) {
|
func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) {
|
||||||
last := lim.last
|
last := lim.last
|
||||||
if now.Before(last) {
|
if now.Before(last) {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/rickb777/date/period"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
duckv1 "knative.dev/pkg/apis/duck/v1"
|
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||||
)
|
)
|
||||||
|
|
@ -42,7 +42,9 @@ type DeliverySpec struct {
|
||||||
BackoffPolicy *BackoffPolicyType `json:"backoffPolicy,omitempty"`
|
BackoffPolicy *BackoffPolicyType `json:"backoffPolicy,omitempty"`
|
||||||
|
|
||||||
// BackoffDelay is the delay before retrying.
|
// BackoffDelay is the delay before retrying.
|
||||||
// More information on Duration format: https://www.ietf.org/rfc/rfc3339.txt
|
// More information on Duration format:
|
||||||
|
// - https://www.iso.org/iso-8601-date-and-time-format.html
|
||||||
|
// - https://en.wikipedia.org/wiki/ISO_8601
|
||||||
//
|
//
|
||||||
// For linear policy, backoff delay is the time interval between retries.
|
// For linear policy, backoff delay is the time interval between retries.
|
||||||
// For exponential policy , backoff delay is backoffDelay*2^<numberOfRetries>.
|
// For exponential policy , backoff delay is backoffDelay*2^<numberOfRetries>.
|
||||||
|
|
@ -67,7 +69,7 @@ func (ds *DeliverySpec) Validate(ctx context.Context) *apis.FieldError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ds.BackoffDelay != nil {
|
if ds.BackoffDelay != nil {
|
||||||
_, te := time.Parse(time.RFC3339, *ds.BackoffDelay)
|
_, te := period.Parse(*ds.BackoffDelay)
|
||||||
if te != nil {
|
if te != nil {
|
||||||
errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay"))
|
errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
fuzz "github.com/google/gofuzz"
|
||||||
|
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
)
|
||||||
|
|
||||||
|
var linear = BackoffPolicyLinear
|
||||||
|
var exponential = BackoffPolicyExponential
|
||||||
|
var bops = []*BackoffPolicyType{nil, &linear, &exponential}
|
||||||
|
|
||||||
|
// FuzzerFuncs includes fuzzing funcs for knative.dev/duck v1 types
|
||||||
|
// In particular it makes sure that Delivery has only valid BackoffPolicyType in it.
|
||||||
|
//
|
||||||
|
// For other examples see
|
||||||
|
// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go
|
||||||
|
var FuzzerFuncs = fuzzer.MergeFuzzerFuncs(
|
||||||
|
func(codecs serializer.CodecFactory) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(ds *DeliverySpec, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(ds) // fuzz the DeliverySpec
|
||||||
|
if ds.BackoffPolicy != nil && *ds.BackoffPolicy == "" {
|
||||||
|
ds.BackoffPolicy = nil
|
||||||
|
} else {
|
||||||
|
ds.BackoffPolicy = bops[rand.Intn(3)]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -38,6 +38,8 @@ func (source *DeliverySpec) ConvertTo(ctx context.Context, to apis.Convertible)
|
||||||
} else if *source.BackoffPolicy == BackoffPolicyExponential {
|
} else if *source.BackoffPolicy == BackoffPolicyExponential {
|
||||||
exponential := eventingduckv1.BackoffPolicyExponential
|
exponential := eventingduckv1.BackoffPolicyExponential
|
||||||
sink.BackoffPolicy = &exponential
|
sink.BackoffPolicy = &exponential
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("unknown BackoffPolicy, got: %q", *source.BackoffPolicy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sink.DeadLetterSink = source.DeadLetterSink
|
sink.DeadLetterSink = source.DeadLetterSink
|
||||||
|
|
@ -60,7 +62,10 @@ func (sink *DeliverySpec) ConvertFrom(ctx context.Context, from apis.Convertible
|
||||||
} else if *source.BackoffPolicy == eventingduckv1.BackoffPolicyExponential {
|
} else if *source.BackoffPolicy == eventingduckv1.BackoffPolicyExponential {
|
||||||
exponential := BackoffPolicyExponential
|
exponential := BackoffPolicyExponential
|
||||||
sink.BackoffPolicy = &exponential
|
sink.BackoffPolicy = &exponential
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("unknown BackoffPolicy, got: %q", *source.BackoffPolicy)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
sink.DeadLetterSink = source.DeadLetterSink
|
sink.DeadLetterSink = source.DeadLetterSink
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,11 @@ package v1beta1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
duckv1 "knative.dev/pkg/apis/duck/v1"
|
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||||
|
|
||||||
|
"github.com/rickb777/date/period"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeliverySpec contains the delivery options for event senders,
|
// DeliverySpec contains the delivery options for event senders,
|
||||||
|
|
@ -42,7 +43,9 @@ type DeliverySpec struct {
|
||||||
BackoffPolicy *BackoffPolicyType `json:"backoffPolicy,omitempty"`
|
BackoffPolicy *BackoffPolicyType `json:"backoffPolicy,omitempty"`
|
||||||
|
|
||||||
// BackoffDelay is the delay before retrying.
|
// BackoffDelay is the delay before retrying.
|
||||||
// More information on Duration format: https://www.ietf.org/rfc/rfc3339.txt
|
// More information on Duration format:
|
||||||
|
// - https://www.iso.org/iso-8601-date-and-time-format.html
|
||||||
|
// - https://en.wikipedia.org/wiki/ISO_8601
|
||||||
//
|
//
|
||||||
// For linear policy, backoff delay is the time interval between retries.
|
// For linear policy, backoff delay is the time interval between retries.
|
||||||
// For exponential policy , backoff delay is backoffDelay*2^<numberOfRetries>.
|
// For exponential policy , backoff delay is backoffDelay*2^<numberOfRetries>.
|
||||||
|
|
@ -67,7 +70,7 @@ func (ds *DeliverySpec) Validate(ctx context.Context) *apis.FieldError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ds.BackoffDelay != nil {
|
if ds.BackoffDelay != nil {
|
||||||
_, te := time.Parse(time.RFC3339, *ds.BackoffDelay)
|
_, te := period.Parse(*ds.BackoffDelay)
|
||||||
if te != nil {
|
if te != nil {
|
||||||
errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay"))
|
errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ const (
|
||||||
// EventTypesAnnotationKey is the annotation key to specify
|
// EventTypesAnnotationKey is the annotation key to specify
|
||||||
// if a Source has event types defines in its CRD.
|
// if a Source has event types defines in its CRD.
|
||||||
EventTypesAnnotationKey = "registry.knative.dev/eventTypes"
|
EventTypesAnnotationKey = "registry.knative.dev/eventTypes"
|
||||||
|
|
||||||
|
// BrokerChannelAddressStatusAnnotationKey is the broker status
|
||||||
|
// annotation key used to specify the address of its channel.
|
||||||
|
BrokerChannelAddressStatusAnnotationKey = "knative.dev/channelAddress"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
fuzz "github.com/google/gofuzz"
|
||||||
|
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
pkgfuzzer "knative.dev/pkg/apis/testing/fuzzer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FuzzerFuncs includes fuzzing funcs for knative.dev/eventing v1 types
|
||||||
|
//
|
||||||
|
// For other examples see
|
||||||
|
// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go
|
||||||
|
var FuzzerFuncs = fuzzer.MergeFuzzerFuncs(
|
||||||
|
func(codecs serializer.CodecFactory) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(s *TriggerStatus, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(s) // fuzz the status object
|
||||||
|
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
s.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
s.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&s.Status, c)
|
||||||
|
},
|
||||||
|
func(s *BrokerStatus, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(s) // fuzz the status object
|
||||||
|
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
s.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
s.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&s.Status, c)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -33,7 +33,7 @@ func (source *Trigger) ConvertTo(_ context.Context, to apis.Convertible) error {
|
||||||
sink.Spec.Subscriber = source.Spec.Subscriber
|
sink.Spec.Subscriber = source.Spec.Subscriber
|
||||||
if source.Spec.Filter != nil {
|
if source.Spec.Filter != nil {
|
||||||
sink.Spec.Filter = &v1.TriggerFilter{
|
sink.Spec.Filter = &v1.TriggerFilter{
|
||||||
Attributes: make(v1.TriggerFilterAttributes, 0),
|
Attributes: make(v1.TriggerFilterAttributes),
|
||||||
}
|
}
|
||||||
for k, v := range source.Spec.Filter.Attributes {
|
for k, v := range source.Spec.Filter.Attributes {
|
||||||
sink.Spec.Filter.Attributes[k] = v
|
sink.Spec.Filter.Attributes[k] = v
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
fuzz "github.com/google/gofuzz"
|
||||||
|
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
pkgfuzzer "knative.dev/pkg/apis/testing/fuzzer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FuzzerFuncs includes fuzzing funcs for knative.dev/flows v1 types
|
||||||
|
//
|
||||||
|
// For other examples see
|
||||||
|
// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go
|
||||||
|
var FuzzerFuncs = fuzzer.MergeFuzzerFuncs(
|
||||||
|
func(codecs serializer.CodecFactory) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(s *SequenceStatus, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(s) // fuzz the status object
|
||||||
|
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
s.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
s.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&s.Status, c)
|
||||||
|
},
|
||||||
|
func(s *ParallelStatus, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(s) // fuzz the status object
|
||||||
|
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
s.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
s.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&s.Status, c)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
fuzz "github.com/google/gofuzz"
|
||||||
|
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"knative.dev/eventing/pkg/apis/messaging"
|
||||||
|
pkgfuzzer "knative.dev/pkg/apis/testing/fuzzer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FuzzerFuncs includes fuzzing funcs for knative.dev/messaging v1 types
|
||||||
|
//
|
||||||
|
// For other examples see
|
||||||
|
// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go
|
||||||
|
var FuzzerFuncs = fuzzer.MergeFuzzerFuncs(
|
||||||
|
func(codecs serializer.CodecFactory) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(ch *Channel, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(ch) // fuzz the Channel
|
||||||
|
if ch != nil {
|
||||||
|
if ch.Annotations == nil {
|
||||||
|
ch.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
ch.Annotations[messaging.SubscribableDuckVersionAnnotation] = "v1"
|
||||||
|
}
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
ch.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
ch.Status.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&ch.Status, c)
|
||||||
|
},
|
||||||
|
func(imc *InMemoryChannel, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(imc) // fuzz the InMemoryChannel
|
||||||
|
if imc != nil {
|
||||||
|
if imc.Annotations == nil {
|
||||||
|
imc.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
imc.Annotations[messaging.SubscribableDuckVersionAnnotation] = "v1"
|
||||||
|
}
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
imc.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
imc.Status.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&imc.Status, c)
|
||||||
|
},
|
||||||
|
func(s *SubscriptionStatus, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(s) // fuzz the status object
|
||||||
|
|
||||||
|
// Clear the random fuzzed condition
|
||||||
|
s.Status.SetConditions(nil)
|
||||||
|
|
||||||
|
// Fuzz the known conditions except their type value
|
||||||
|
s.InitializeConditions()
|
||||||
|
pkgfuzzer.FuzzConditions(&s.Status, c)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"knative.dev/eventing/pkg/apis/messaging"
|
"knative.dev/eventing/pkg/apis/messaging"
|
||||||
v1 "knative.dev/eventing/pkg/apis/messaging/v1"
|
v1 "knative.dev/eventing/pkg/apis/messaging/v1"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
|
"knative.dev/pkg/kmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertTo implements apis.Convertible
|
// ConvertTo implements apis.Convertible
|
||||||
|
|
@ -30,10 +31,9 @@ func (source *Channel) ConvertTo(ctx context.Context, obj apis.Convertible) erro
|
||||||
switch sink := obj.(type) {
|
switch sink := obj.(type) {
|
||||||
case *v1.Channel:
|
case *v1.Channel:
|
||||||
sink.ObjectMeta = source.ObjectMeta
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
if sink.Annotations == nil {
|
|
||||||
sink.Annotations = make(map[string]string)
|
// Does a deep copy, adds our duck version.
|
||||||
}
|
sink.Annotations = kmeta.UnionMaps(source.Annotations, map[string]string{messaging.SubscribableDuckVersionAnnotation: "v1"})
|
||||||
sink.Annotations[messaging.SubscribableDuckVersionAnnotation] = "v1"
|
|
||||||
source.Status.ConvertTo(ctx, &sink.Status)
|
source.Status.ConvertTo(ctx, &sink.Status)
|
||||||
return source.Spec.ConvertTo(ctx, &sink.Spec)
|
return source.Spec.ConvertTo(ctx, &sink.Spec)
|
||||||
default:
|
default:
|
||||||
|
|
@ -60,10 +60,11 @@ func (source *ChannelSpec) ConvertTo(ctx context.Context, sink *v1.ChannelSpec)
|
||||||
|
|
||||||
// ConvertTo helps implement apis.Convertible
|
// ConvertTo helps implement apis.Convertible
|
||||||
func (source *ChannelStatus) ConvertTo(ctx context.Context, sink *v1.ChannelStatus) {
|
func (source *ChannelStatus) ConvertTo(ctx context.Context, sink *v1.ChannelStatus) {
|
||||||
source.Status.ConvertTo(ctx, &sink.Status)
|
sink.Status = source.Status
|
||||||
sink.AddressStatus.Address = source.AddressStatus.Address
|
sink.AddressStatus.Address = source.AddressStatus.Address
|
||||||
source.SubscribableStatus.ConvertTo(ctx, &sink.SubscribableStatus)
|
source.SubscribableStatus.ConvertTo(ctx, &sink.SubscribableStatus)
|
||||||
sink.Channel = source.Channel
|
sink.Channel = source.Channel
|
||||||
|
sink.DeadLetterChannel = source.DeadLetterChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertFrom implements apis.Convertible.
|
// ConvertFrom implements apis.Convertible.
|
||||||
|
|
@ -74,10 +75,9 @@ func (sink *Channel) ConvertFrom(ctx context.Context, obj apis.Convertible) erro
|
||||||
sink.ObjectMeta = source.ObjectMeta
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
sink.Status.ConvertFrom(ctx, source.Status)
|
sink.Status.ConvertFrom(ctx, source.Status)
|
||||||
sink.Spec.ConvertFrom(ctx, source.Spec)
|
sink.Spec.ConvertFrom(ctx, source.Spec)
|
||||||
if sink.Annotations == nil {
|
// Does a deep copy, adds our duck version.
|
||||||
sink.Annotations = make(map[string]string)
|
sink.Annotations = kmeta.UnionMaps(source.Annotations, map[string]string{messaging.SubscribableDuckVersionAnnotation: "v1beta1"})
|
||||||
}
|
|
||||||
sink.Annotations[messaging.SubscribableDuckVersionAnnotation] = "v1beta1"
|
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown version, got: %T", source)
|
return fmt.Errorf("unknown version, got: %T", source)
|
||||||
|
|
@ -101,8 +101,9 @@ func (sink *ChannelSpec) ConvertFrom(ctx context.Context, source v1.ChannelSpec)
|
||||||
|
|
||||||
// ConvertFrom helps implement apis.Convertible
|
// ConvertFrom helps implement apis.Convertible
|
||||||
func (sink *ChannelStatus) ConvertFrom(ctx context.Context, source v1.ChannelStatus) {
|
func (sink *ChannelStatus) ConvertFrom(ctx context.Context, source v1.ChannelStatus) {
|
||||||
source.Status.ConvertTo(ctx, &sink.Status)
|
sink.Status = source.Status
|
||||||
sink.Channel = source.Channel
|
sink.Channel = source.Channel
|
||||||
sink.SubscribableStatus.ConvertFrom(ctx, &source.SubscribableStatus)
|
sink.SubscribableStatus.ConvertFrom(ctx, &source.SubscribableStatus)
|
||||||
sink.AddressStatus.Address = source.AddressStatus.Address
|
sink.AddressStatus.Address = source.AddressStatus.Address
|
||||||
|
sink.DeadLetterChannel = source.DeadLetterChannel
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ import (
|
||||||
|
|
||||||
eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1"
|
eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1"
|
||||||
eventingduckv1beta1 "knative.dev/eventing/pkg/apis/duck/v1beta1"
|
eventingduckv1beta1 "knative.dev/eventing/pkg/apis/duck/v1beta1"
|
||||||
"knative.dev/pkg/apis"
|
|
||||||
|
|
||||||
"knative.dev/eventing/pkg/apis/messaging"
|
"knative.dev/eventing/pkg/apis/messaging"
|
||||||
v1 "knative.dev/eventing/pkg/apis/messaging/v1"
|
v1 "knative.dev/eventing/pkg/apis/messaging/v1"
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
"knative.dev/pkg/kmeta"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertTo implements apis.Convertible
|
// ConvertTo implements apis.Convertible
|
||||||
|
|
@ -34,10 +34,8 @@ func (source *InMemoryChannel) ConvertTo(ctx context.Context, obj apis.Convertib
|
||||||
switch sink := obj.(type) {
|
switch sink := obj.(type) {
|
||||||
case *v1.InMemoryChannel:
|
case *v1.InMemoryChannel:
|
||||||
sink.ObjectMeta = source.ObjectMeta
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
if sink.Annotations == nil {
|
// Does a deep copy, adds our duck version.
|
||||||
sink.Annotations = make(map[string]string)
|
sink.Annotations = kmeta.UnionMaps(source.Annotations, map[string]string{messaging.SubscribableDuckVersionAnnotation: "v1"})
|
||||||
}
|
|
||||||
sink.Annotations[messaging.SubscribableDuckVersionAnnotation] = "v1"
|
|
||||||
source.Status.ConvertTo(ctx, &sink.Status)
|
source.Status.ConvertTo(ctx, &sink.Status)
|
||||||
return source.Spec.ConvertTo(ctx, &sink.Spec)
|
return source.Spec.ConvertTo(ctx, &sink.Spec)
|
||||||
default:
|
default:
|
||||||
|
|
@ -58,10 +56,11 @@ func (source *InMemoryChannelSpec) ConvertTo(ctx context.Context, sink *v1.InMem
|
||||||
|
|
||||||
// ConvertTo helps implement apis.Convertible
|
// ConvertTo helps implement apis.Convertible
|
||||||
func (source *InMemoryChannelStatus) ConvertTo(ctx context.Context, sink *v1.InMemoryChannelStatus) {
|
func (source *InMemoryChannelStatus) ConvertTo(ctx context.Context, sink *v1.InMemoryChannelStatus) {
|
||||||
source.Status.ConvertTo(ctx, &sink.Status)
|
sink.Status = source.Status
|
||||||
sink.AddressStatus = source.AddressStatus
|
sink.AddressStatus = source.AddressStatus
|
||||||
sink.SubscribableStatus = eventingduckv1.SubscribableStatus{}
|
sink.SubscribableStatus = eventingduckv1.SubscribableStatus{}
|
||||||
source.SubscribableStatus.ConvertTo(ctx, &sink.SubscribableStatus)
|
source.SubscribableStatus.ConvertTo(ctx, &sink.SubscribableStatus)
|
||||||
|
sink.DeadLetterChannel = source.DeadLetterChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertFrom implements apis.Convertible.
|
// ConvertFrom implements apis.Convertible.
|
||||||
|
|
@ -72,10 +71,8 @@ func (sink *InMemoryChannel) ConvertFrom(ctx context.Context, obj apis.Convertib
|
||||||
sink.ObjectMeta = source.ObjectMeta
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
sink.Status.ConvertFrom(ctx, source.Status)
|
sink.Status.ConvertFrom(ctx, source.Status)
|
||||||
sink.Spec.ConvertFrom(ctx, source.Spec)
|
sink.Spec.ConvertFrom(ctx, source.Spec)
|
||||||
if sink.Annotations == nil {
|
// Does a deep copy, adds our duck version.
|
||||||
sink.Annotations = make(map[string]string)
|
sink.Annotations = kmeta.UnionMaps(source.Annotations, map[string]string{messaging.SubscribableDuckVersionAnnotation: "v1beta1"})
|
||||||
}
|
|
||||||
sink.Annotations[messaging.SubscribableDuckVersionAnnotation] = "v1beta1"
|
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown version, got: %T", source)
|
return fmt.Errorf("unknown version, got: %T", source)
|
||||||
|
|
@ -97,8 +94,9 @@ func (sink *InMemoryChannelSpec) ConvertFrom(ctx context.Context, source v1.InMe
|
||||||
|
|
||||||
// ConvertFrom helps implement apis.Convertible
|
// ConvertFrom helps implement apis.Convertible
|
||||||
func (sink *InMemoryChannelStatus) ConvertFrom(ctx context.Context, source v1.InMemoryChannelStatus) {
|
func (sink *InMemoryChannelStatus) ConvertFrom(ctx context.Context, source v1.InMemoryChannelStatus) {
|
||||||
source.Status.ConvertTo(ctx, &sink.Status)
|
sink.Status = source.Status
|
||||||
sink.AddressStatus = source.AddressStatus
|
sink.AddressStatus = source.AddressStatus
|
||||||
sink.SubscribableStatus = eventingduckv1beta1.SubscribableStatus{}
|
sink.SubscribableStatus = eventingduckv1beta1.SubscribableStatus{}
|
||||||
sink.SubscribableStatus.ConvertFrom(ctx, &source.SubscribableStatus)
|
sink.SubscribableStatus.ConvertFrom(ctx, &source.SubscribableStatus)
|
||||||
|
sink.DeadLetterChannel = source.DeadLetterChannel
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
@ -32,7 +31,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertTo implements apis.Convertible.
|
// ConvertTo implements apis.Convertible.
|
||||||
// Converts source (from v1alpha1.ApiServerSource) into v1alpha2.ApiServerSource
|
// Converts source (from v1alpha1.ApiServerSource) into into a higher version.
|
||||||
func (source *ApiServerSource) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
func (source *ApiServerSource) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
||||||
switch sink := obj.(type) {
|
switch sink := obj.(type) {
|
||||||
case *v1alpha2.ApiServerSource:
|
case *v1alpha2.ApiServerSource:
|
||||||
|
|
@ -95,12 +94,12 @@ func (source *ApiServerSource) ConvertTo(ctx context.Context, obj apis.Convertib
|
||||||
source.Status.SourceStatus.DeepCopyInto(&sink.Status.SourceStatus)
|
source.Status.SourceStatus.DeepCopyInto(&sink.Status.SourceStatus)
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown conversion, got: %T", sink)
|
return apis.ConvertToViaProxy(ctx, source, &v1alpha2.ApiServerSource{}, sink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertFrom implements apis.Convertible.
|
// ConvertFrom implements apis.Convertible.
|
||||||
// Converts obj from v1alpha2.ApiServerSource into v1alpha1.ApiServerSource
|
// Converts obj from a higher version into v1alpha1.ApiServerSource.
|
||||||
func (sink *ApiServerSource) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
func (sink *ApiServerSource) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
||||||
switch source := obj.(type) {
|
switch source := obj.(type) {
|
||||||
case *v1alpha2.ApiServerSource:
|
case *v1alpha2.ApiServerSource:
|
||||||
|
|
@ -158,6 +157,6 @@ func (sink *ApiServerSource) ConvertFrom(ctx context.Context, obj apis.Convertib
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown conversion, got: %T", source)
|
return apis.ConvertFromViaProxy(ctx, source, &v1alpha2.ApiServerSource{}, sink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func (s *ApiServerSourceStatus) PropagateDeploymentAvailability(d *appsv1.Deploy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !deploymentAvailableFound {
|
if !deploymentAvailableFound {
|
||||||
PingSourceCondSet.Manage(s).MarkUnknown(PingSourceConditionDeployed, "DeploymentUnavailable", "The Deployment '%s' is unavailable.", d.Name)
|
apiserverCondSet.Manage(s).MarkUnknown(ApiServerConditionDeployed, "DeploymentUnavailable", "The Deployment '%s' is unavailable.", d.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,13 @@ package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"knative.dev/eventing/pkg/apis/sources/v1alpha2"
|
"knative.dev/eventing/pkg/apis/sources/v1alpha2"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertTo implements apis.Convertible.
|
// ConvertTo implements apis.Convertible.
|
||||||
// Converts source (from v1alpha1.SinkBinding) into v1alpha2.SinkBinding
|
// Converts source from v1alpha1.SinkBinding into a higher version.
|
||||||
func (source *SinkBinding) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
func (source *SinkBinding) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
||||||
switch sink := obj.(type) {
|
switch sink := obj.(type) {
|
||||||
case *v1alpha2.SinkBinding:
|
case *v1alpha2.SinkBinding:
|
||||||
|
|
@ -35,21 +34,22 @@ func (source *SinkBinding) ConvertTo(ctx context.Context, obj apis.Convertible)
|
||||||
sink.Status.SourceStatus = source.Status.SourceStatus
|
sink.Status.SourceStatus = source.Status.SourceStatus
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown conversion, got: %T", sink)
|
return apis.ConvertToViaProxy(ctx, source, &v1alpha2.SinkBinding{}, sink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertFrom implements apis.Convertible.
|
// ConvertFrom implements apis.Convertible.
|
||||||
// Converts obj from v1alpha2.SinkBinding into v1alpha1.SinkBinding
|
// Converts obj from a higher version into v1alpha1.SinkBinding.
|
||||||
func (sink *SinkBinding) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
func (sink *SinkBinding) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
||||||
switch source := obj.(type) {
|
switch source := obj.(type) {
|
||||||
case *v1alpha2.SinkBinding:
|
case *v1alpha2.SinkBinding:
|
||||||
sink.ObjectMeta = source.ObjectMeta
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
sink.Spec.Subject = source.Spec.Subject
|
||||||
sink.Spec.SourceSpec = source.Spec.SourceSpec
|
sink.Spec.SourceSpec = source.Spec.SourceSpec
|
||||||
sink.Spec.BindingSpec = source.Spec.BindingSpec
|
sink.Spec.BindingSpec = source.Spec.BindingSpec
|
||||||
sink.Status.SourceStatus = source.Status.SourceStatus
|
sink.Status.SourceStatus = source.Status.SourceStatus
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown conversion, got: %T", source)
|
return apis.ConvertFromViaProxy(ctx, source, &v1alpha2.SinkBinding{}, sink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,120 @@ package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"knative.dev/eventing/pkg/apis/sources/v1beta1"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
|
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertTo implements apis.Convertible
|
// ConvertTo implements apis.Convertible
|
||||||
func (source *ApiServerSource) ConvertTo(ctx context.Context, sink apis.Convertible) error {
|
// Converts source (from v1alpha2.ApiServerSource) into into a higher version.
|
||||||
return fmt.Errorf("v1alpha2 is the highest known version, got: %T", sink)
|
func (source *ApiServerSource) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
||||||
|
switch sink := obj.(type) {
|
||||||
|
case *v1beta1.ApiServerSource:
|
||||||
|
// Meta
|
||||||
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
|
||||||
|
// Spec
|
||||||
|
|
||||||
|
if len(source.Spec.Resources) > 0 {
|
||||||
|
sink.Spec.Resources = make([]v1beta1.APIVersionKindSelector, len(source.Spec.Resources))
|
||||||
|
}
|
||||||
|
for i, v := range source.Spec.Resources {
|
||||||
|
sink.Spec.Resources[i] = v1beta1.APIVersionKindSelector{
|
||||||
|
APIVersion: v.APIVersion,
|
||||||
|
Kind: v.Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.LabelSelector != nil {
|
||||||
|
sink.Spec.Resources[i].LabelSelector = &metav1.LabelSelector{}
|
||||||
|
v.LabelSelector.DeepCopyInto(sink.Spec.Resources[i].LabelSelector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sink.Spec.EventMode = source.Spec.EventMode
|
||||||
|
|
||||||
|
// Optional Spec
|
||||||
|
|
||||||
|
if source.Spec.ResourceOwner != nil {
|
||||||
|
sink.Spec.ResourceOwner = &v1beta1.APIVersionKind{
|
||||||
|
Kind: source.Spec.ResourceOwner.Kind,
|
||||||
|
APIVersion: source.Spec.ResourceOwner.APIVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ref *duckv1.KReference
|
||||||
|
if source.Spec.Sink.Ref != nil {
|
||||||
|
ref = &duckv1.KReference{
|
||||||
|
Kind: source.Spec.Sink.Ref.Kind,
|
||||||
|
Namespace: source.Spec.Sink.Ref.Namespace,
|
||||||
|
Name: source.Spec.Sink.Ref.Name,
|
||||||
|
APIVersion: source.Spec.Sink.Ref.APIVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sink.Spec.Sink = duckv1.Destination{
|
||||||
|
Ref: ref,
|
||||||
|
URI: source.Spec.Sink.URI,
|
||||||
|
}
|
||||||
|
|
||||||
|
if source.Spec.CloudEventOverrides != nil {
|
||||||
|
sink.Spec.CloudEventOverrides = source.Spec.CloudEventOverrides.DeepCopy()
|
||||||
|
}
|
||||||
|
|
||||||
|
sink.Spec.ServiceAccountName = source.Spec.ServiceAccountName
|
||||||
|
|
||||||
|
// Status
|
||||||
|
source.Status.SourceStatus.DeepCopyInto(&sink.Status.SourceStatus)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return apis.ConvertToViaProxy(ctx, source, &v1beta1.ApiServerSource{}, sink)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertFrom implements apis.Convertible
|
// ConvertFrom implements apis.Convertible
|
||||||
func (sink *ApiServerSource) ConvertFrom(ctx context.Context, source apis.Convertible) error {
|
// Converts obj from a higher version into v1alpha2.ApiServerSource.
|
||||||
return fmt.Errorf("v1alpha2 is the highest known version, got: %T", source)
|
func (sink *ApiServerSource) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
||||||
|
switch source := obj.(type) {
|
||||||
|
case *v1beta1.ApiServerSource:
|
||||||
|
// Meta
|
||||||
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
|
||||||
|
// Spec
|
||||||
|
sink.Spec.EventMode = source.Spec.EventMode
|
||||||
|
|
||||||
|
sink.Spec.CloudEventOverrides = source.Spec.CloudEventOverrides
|
||||||
|
|
||||||
|
sink.Spec.Sink = source.Spec.Sink
|
||||||
|
|
||||||
|
if len(source.Spec.Resources) > 0 {
|
||||||
|
sink.Spec.Resources = make([]APIVersionKindSelector, len(source.Spec.Resources))
|
||||||
|
}
|
||||||
|
for i, v := range source.Spec.Resources {
|
||||||
|
sink.Spec.Resources[i] = APIVersionKindSelector{}
|
||||||
|
sink.Spec.Resources[i].APIVersion = v.APIVersion
|
||||||
|
sink.Spec.Resources[i].Kind = v.Kind
|
||||||
|
if v.LabelSelector != nil {
|
||||||
|
sink.Spec.Resources[i].LabelSelector = v.LabelSelector.DeepCopy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spec Optionals
|
||||||
|
|
||||||
|
if source.Spec.ResourceOwner != nil {
|
||||||
|
sink.Spec.ResourceOwner = &APIVersionKind{
|
||||||
|
Kind: source.Spec.ResourceOwner.Kind,
|
||||||
|
APIVersion: source.Spec.ResourceOwner.APIVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sink.Spec.ServiceAccountName = source.Spec.ServiceAccountName
|
||||||
|
|
||||||
|
// Status
|
||||||
|
source.Status.SourceStatus.DeepCopyInto(&sink.Status.SourceStatus)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return apis.ConvertFromViaProxy(ctx, source, &v1beta1.ApiServerSource{}, sink)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,6 @@ const (
|
||||||
|
|
||||||
// ApiServerConditionSufficientPermissions has status True when the ApiServerSource has sufficient permissions to access resources.
|
// ApiServerConditionSufficientPermissions has status True when the ApiServerSource has sufficient permissions to access resources.
|
||||||
ApiServerConditionSufficientPermissions apis.ConditionType = "SufficientPermissions"
|
ApiServerConditionSufficientPermissions apis.ConditionType = "SufficientPermissions"
|
||||||
|
|
||||||
// ApiServerConditionEventTypeProvided has status True when the ApiServerSource has been configured with its event types.
|
|
||||||
ApiServerConditionEventTypeProvided apis.ConditionType = "EventTypesProvided"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var apiserverCondSet = apis.NewLivingConditionSet(
|
var apiserverCondSet = apis.NewLivingConditionSet(
|
||||||
|
|
@ -109,20 +106,10 @@ func (s *ApiServerSourceStatus) PropagateDeploymentAvailability(d *appsv1.Deploy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !deploymentAvailableFound {
|
if !deploymentAvailableFound {
|
||||||
PingSourceCondSet.Manage(s).MarkUnknown(PingSourceConditionDeployed, "DeploymentUnavailable", "The Deployment '%s' is unavailable.", d.Name)
|
apiserverCondSet.Manage(s).MarkUnknown(ApiServerConditionDeployed, "DeploymentUnavailable", "The Deployment '%s' is unavailable.", d.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkEventTypes sets the condition that the source has set its event type.
|
|
||||||
func (s *ApiServerSourceStatus) MarkEventTypes() {
|
|
||||||
apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionEventTypeProvided)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarkNoEventTypes sets the condition that the source does not its event type configured.
|
|
||||||
func (s *ApiServerSourceStatus) MarkNoEventTypes(reason, messageFormat string, messageA ...interface{}) {
|
|
||||||
apiserverCondSet.Manage(s).MarkFalse(ApiServerConditionEventTypeProvided, reason, messageFormat, messageA...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarkSufficientPermissions sets the condition that the source has enough permissions to access the resources.
|
// MarkSufficientPermissions sets the condition that the source has enough permissions to access the resources.
|
||||||
func (s *ApiServerSourceStatus) MarkSufficientPermissions() {
|
func (s *ApiServerSourceStatus) MarkSufficientPermissions() {
|
||||||
apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionSufficientPermissions)
|
apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionSufficientPermissions)
|
||||||
|
|
|
||||||
55
vendor/knative.dev/eventing/pkg/apis/sources/v1alpha2/container_conversion.go
vendored
Normal file
55
vendor/knative.dev/eventing/pkg/apis/sources/v1alpha2/container_conversion.go
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"knative.dev/eventing/pkg/apis/sources/v1beta1"
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConvertTo implements apis.Convertible.
|
||||||
|
// Converts source from v1alpha2.ContainerSource into a higher version.
|
||||||
|
func (source *ContainerSource) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
||||||
|
switch sink := obj.(type) {
|
||||||
|
case *v1beta1.ContainerSource:
|
||||||
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
sink.Spec.SourceSpec = source.Spec.SourceSpec
|
||||||
|
sink.Spec.Template = source.Spec.Template
|
||||||
|
sink.Status.SourceStatus = source.Status.SourceStatus
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown conversion, got: %T", sink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertFrom implements apis.Convertible.
|
||||||
|
// Converts obj from a higher version into v1alpha2.ContainerSource.
|
||||||
|
func (sink *ContainerSource) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
||||||
|
switch source := obj.(type) {
|
||||||
|
case *v1beta1.ContainerSource:
|
||||||
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
sink.Spec.SourceSpec = source.Spec.SourceSpec
|
||||||
|
sink.Spec.Template = source.Spec.Template
|
||||||
|
sink.Status.SourceStatus = source.Status.SourceStatus
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown conversion, got: %T", source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,17 +18,43 @@ package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
|
"knative.dev/eventing/pkg/apis/sources/v1beta1"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
|
duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1"
|
||||||
|
duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertTo implements apis.Convertible
|
// ConvertTo implements apis.Convertible.
|
||||||
func (source *SinkBinding) ConvertTo(ctx context.Context, sink apis.Convertible) error {
|
// Converts source from v1alpha2.SinkBinding into a higher version.
|
||||||
return fmt.Errorf("v1alpha2 is the highest known version, got: %T", sink)
|
func (source *SinkBinding) ConvertTo(ctx context.Context, obj apis.Convertible) error {
|
||||||
|
switch sink := obj.(type) {
|
||||||
|
case *v1beta1.SinkBinding:
|
||||||
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
sink.Spec.SourceSpec = source.Spec.SourceSpec
|
||||||
|
sink.Spec.BindingSpec = duckv1beta1.BindingSpec{
|
||||||
|
Subject: source.Spec.BindingSpec.Subject,
|
||||||
|
}
|
||||||
|
sink.Status.SourceStatus = source.Status.SourceStatus
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return apis.ConvertToViaProxy(ctx, source, &v1beta1.SinkBinding{}, sink)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertFrom implements apis.Convertible
|
// ConvertFrom implements apis.Convertible.
|
||||||
func (sink *SinkBinding) ConvertFrom(ctx context.Context, source apis.Convertible) error {
|
// Converts obj from a higher version into v1alpha2.SinkBinding.
|
||||||
return fmt.Errorf("v1alpha2 is the highest known version, got: %T", source)
|
func (sink *SinkBinding) ConvertFrom(ctx context.Context, obj apis.Convertible) error {
|
||||||
|
switch source := obj.(type) {
|
||||||
|
case *v1beta1.SinkBinding:
|
||||||
|
sink.ObjectMeta = source.ObjectMeta
|
||||||
|
sink.Spec.SourceSpec = source.Spec.SourceSpec
|
||||||
|
sink.Spec.BindingSpec = duckv1alpha1.BindingSpec{
|
||||||
|
Subject: source.Spec.BindingSpec.Subject,
|
||||||
|
}
|
||||||
|
sink.Status.SourceStatus = source.Status.SourceStatus
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return apis.ConvertToViaProxy(ctx, source, &v1beta1.SinkBinding{}, sink)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/apiserver_conversion.go
vendored
Normal file
34
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/apiserver_conversion.go
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConvertTo implements apis.Convertible
|
||||||
|
func (source *ApiServerSource) ConvertTo(ctx context.Context, sink apis.Convertible) error {
|
||||||
|
return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertFrom implements apis.Convertible
|
||||||
|
func (sink *ApiServerSource) ConvertFrom(ctx context.Context, source apis.Convertible) error {
|
||||||
|
return fmt.Errorf("v1beta1 is the highest known version, got: %T", source)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *ApiServerSource) SetDefaults(ctx context.Context) {
|
||||||
|
s.Spec.SetDefaults(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *ApiServerSourceSpec) SetDefaults(ctx context.Context) {
|
||||||
|
|
||||||
|
if ss.EventMode == "" {
|
||||||
|
ss.EventMode = ReferenceMode
|
||||||
|
}
|
||||||
|
|
||||||
|
if ss.ServiceAccountName == "" {
|
||||||
|
ss.ServiceAccountName = "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
126
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/apiserver_lifecycle.go
vendored
Normal file
126
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/apiserver_lifecycle.go
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ApiServerConditionReady has status True when the ApiServerSource is ready to send events.
|
||||||
|
ApiServerConditionReady = apis.ConditionReady
|
||||||
|
|
||||||
|
// ApiServerConditionSinkProvided has status True when the ApiServerSource has been configured with a sink target.
|
||||||
|
ApiServerConditionSinkProvided apis.ConditionType = "SinkProvided"
|
||||||
|
|
||||||
|
// ApiServerConditionDeployed has status True when the ApiServerSource has had it's deployment created.
|
||||||
|
ApiServerConditionDeployed apis.ConditionType = "Deployed"
|
||||||
|
|
||||||
|
// ApiServerConditionSufficientPermissions has status True when the ApiServerSource has sufficient permissions to access resources.
|
||||||
|
ApiServerConditionSufficientPermissions apis.ConditionType = "SufficientPermissions"
|
||||||
|
)
|
||||||
|
|
||||||
|
var apiserverCondSet = apis.NewLivingConditionSet(
|
||||||
|
ApiServerConditionSinkProvided,
|
||||||
|
ApiServerConditionDeployed,
|
||||||
|
ApiServerConditionSufficientPermissions,
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface.
|
||||||
|
func (*ApiServerSource) GetConditionSet() apis.ConditionSet {
|
||||||
|
return apiserverCondSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGroupVersionKind returns the GroupVersionKind.
|
||||||
|
func (*ApiServerSource) GetGroupVersionKind() schema.GroupVersionKind {
|
||||||
|
return SchemeGroupVersion.WithKind("ApiServerSource")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUntypedSpec returns the spec of the ApiServerSource.
|
||||||
|
func (s *ApiServerSource) GetUntypedSpec() interface{} {
|
||||||
|
return s.Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCondition returns the condition currently associated with the given type, or nil.
|
||||||
|
func (s *ApiServerSourceStatus) GetCondition(t apis.ConditionType) *apis.Condition {
|
||||||
|
return apiserverCondSet.Manage(s).GetCondition(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTopLevelCondition returns the top level condition.
|
||||||
|
func (s *ApiServerSourceStatus) GetTopLevelCondition() *apis.Condition {
|
||||||
|
return apiserverCondSet.Manage(s).GetTopLevelCondition()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitializeConditions sets relevant unset conditions to Unknown state.
|
||||||
|
func (s *ApiServerSourceStatus) InitializeConditions() {
|
||||||
|
apiserverCondSet.Manage(s).InitializeConditions()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkSink sets the condition that the source has a sink configured.
|
||||||
|
func (s *ApiServerSourceStatus) MarkSink(uri *apis.URL) {
|
||||||
|
s.SinkURI = uri
|
||||||
|
if uri != nil {
|
||||||
|
apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionSinkProvided)
|
||||||
|
} else {
|
||||||
|
apiserverCondSet.Manage(s).MarkFalse(ApiServerConditionSinkProvided, "SinkEmpty", "Sink has resolved to empty.%s", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkNoSink sets the condition that the source does not have a sink configured.
|
||||||
|
func (s *ApiServerSourceStatus) MarkNoSink(reason, messageFormat string, messageA ...interface{}) {
|
||||||
|
apiserverCondSet.Manage(s).MarkFalse(ApiServerConditionSinkProvided, reason, messageFormat, messageA...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PropagateDeploymentAvailability uses the availability of the provided Deployment to determine if
|
||||||
|
// ApiServerConditionDeployed should be marked as true or false.
|
||||||
|
func (s *ApiServerSourceStatus) PropagateDeploymentAvailability(d *appsv1.Deployment) {
|
||||||
|
deploymentAvailableFound := false
|
||||||
|
for _, cond := range d.Status.Conditions {
|
||||||
|
if cond.Type == appsv1.DeploymentAvailable {
|
||||||
|
deploymentAvailableFound = true
|
||||||
|
if cond.Status == corev1.ConditionTrue {
|
||||||
|
apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionDeployed)
|
||||||
|
} else if cond.Status == corev1.ConditionFalse {
|
||||||
|
apiserverCondSet.Manage(s).MarkFalse(ApiServerConditionDeployed, cond.Reason, cond.Message)
|
||||||
|
} else if cond.Status == corev1.ConditionUnknown {
|
||||||
|
apiserverCondSet.Manage(s).MarkUnknown(ApiServerConditionDeployed, cond.Reason, cond.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !deploymentAvailableFound {
|
||||||
|
apiserverCondSet.Manage(s).MarkUnknown(ApiServerConditionDeployed, "DeploymentUnavailable", "The Deployment '%s' is unavailable.", d.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkSufficientPermissions sets the condition that the source has enough permissions to access the resources.
|
||||||
|
func (s *ApiServerSourceStatus) MarkSufficientPermissions() {
|
||||||
|
apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionSufficientPermissions)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkNoSufficientPermissions sets the condition that the source does not have enough permissions to access the resources
|
||||||
|
func (s *ApiServerSourceStatus) MarkNoSufficientPermissions(reason, messageFormat string, messageA ...interface{}) {
|
||||||
|
apiserverCondSet.Manage(s).MarkFalse(ApiServerConditionSufficientPermissions, reason, messageFormat, messageA...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsReady returns true if the resource is ready overall.
|
||||||
|
func (s *ApiServerSourceStatus) IsReady() bool {
|
||||||
|
return apiserverCondSet.Manage(s).IsHappy()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
duckv1 "knative.dev/pkg/apis/duck/v1"
|
||||||
|
"knative.dev/pkg/kmeta"
|
||||||
|
)
|
||||||
|
|
||||||
|
// +genclient
|
||||||
|
// +genreconciler
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
// +k8s:defaulter-gen=true
|
||||||
|
|
||||||
|
// ApiServerSource is the Schema for the apiserversources API
|
||||||
|
type ApiServerSource struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ApiServerSourceSpec `json:"spec,omitempty"`
|
||||||
|
Status ApiServerSourceStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the interfaces that ApiServerSource should be implementing.
|
||||||
|
var (
|
||||||
|
_ runtime.Object = (*ApiServerSource)(nil)
|
||||||
|
_ kmeta.OwnerRefable = (*ApiServerSource)(nil)
|
||||||
|
_ apis.Validatable = (*ApiServerSource)(nil)
|
||||||
|
_ apis.Defaultable = (*ApiServerSource)(nil)
|
||||||
|
_ apis.HasSpec = (*ApiServerSource)(nil)
|
||||||
|
_ duckv1.KRShaped = (*ApiServerSource)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ApiServerSourceAddEventType is the ApiServerSource CloudEvent type for adds.
|
||||||
|
ApiServerSourceAddEventType = "dev.knative.apiserver.resource.add"
|
||||||
|
// ApiServerSourceUpdateEventType is the ApiServerSource CloudEvent type for updates.
|
||||||
|
ApiServerSourceUpdateEventType = "dev.knative.apiserver.resource.update"
|
||||||
|
// ApiServerSourceDeleteEventType is the ApiServerSource CloudEvent type for deletions.
|
||||||
|
ApiServerSourceDeleteEventType = "dev.knative.apiserver.resource.delete"
|
||||||
|
|
||||||
|
// ApiServerSourceAddRefEventType is the ApiServerSource CloudEvent type for ref adds.
|
||||||
|
ApiServerSourceAddRefEventType = "dev.knative.apiserver.ref.add"
|
||||||
|
// ApiServerSourceUpdateRefEventType is the ApiServerSource CloudEvent type for ref updates.
|
||||||
|
ApiServerSourceUpdateRefEventType = "dev.knative.apiserver.ref.update"
|
||||||
|
// ApiServerSourceDeleteRefEventType is the ApiServerSource CloudEvent type for ref deletions.
|
||||||
|
ApiServerSourceDeleteRefEventType = "dev.knative.apiserver.ref.delete"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApiServerSourceEventTypes is the list of CloudEvent types the ApiServerSource emits.
|
||||||
|
var ApiServerSourceEventTypes = []string{
|
||||||
|
ApiServerSourceAddEventType,
|
||||||
|
ApiServerSourceDeleteEventType,
|
||||||
|
ApiServerSourceUpdateEventType,
|
||||||
|
ApiServerSourceAddRefEventType,
|
||||||
|
ApiServerSourceDeleteRefEventType,
|
||||||
|
ApiServerSourceUpdateRefEventType,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApiServerSourceSpec defines the desired state of ApiServerSource
|
||||||
|
type ApiServerSourceSpec struct {
|
||||||
|
// inherits duck/v1 SourceSpec, which currently provides:
|
||||||
|
// * Sink - a reference to an object that will resolve to a domain name or
|
||||||
|
// a URI directly to use as the sink.
|
||||||
|
// * CloudEventOverrides - defines overrides to control the output format
|
||||||
|
// and modifications of the event sent to the sink.
|
||||||
|
duckv1.SourceSpec `json:",inline"`
|
||||||
|
|
||||||
|
// Resource are the resources this source will track and send related
|
||||||
|
// lifecycle events from the Kubernetes ApiServer, with an optional label
|
||||||
|
// selector to help filter.
|
||||||
|
// +required
|
||||||
|
Resources []APIVersionKindSelector `json:"resources,omitempty"`
|
||||||
|
|
||||||
|
// ResourceOwner is an additional filter to only track resources that are
|
||||||
|
// owned by a specific resource type. If ResourceOwner matches Resources[n]
|
||||||
|
// then Resources[n] is allowed to pass the ResourceOwner filter.
|
||||||
|
// +optional
|
||||||
|
ResourceOwner *APIVersionKind `json:"owner,omitempty"`
|
||||||
|
|
||||||
|
// EventMode controls the format of the event.
|
||||||
|
// `Reference` sends a dataref event type for the resource under watch.
|
||||||
|
// `Resource` send the full resource lifecycle event.
|
||||||
|
// Defaults to `Reference`
|
||||||
|
// +optional
|
||||||
|
EventMode string `json:"mode,omitempty"`
|
||||||
|
|
||||||
|
// ServiceAccountName is the name of the ServiceAccount to use to run this
|
||||||
|
// source. Defaults to default if not set.
|
||||||
|
// +optional
|
||||||
|
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApiServerSourceStatus defines the observed state of ApiServerSource
|
||||||
|
type ApiServerSourceStatus struct {
|
||||||
|
// inherits duck/v1 SourceStatus, which currently provides:
|
||||||
|
// * ObservedGeneration - the 'Generation' of the Service that was last
|
||||||
|
// processed by the controller.
|
||||||
|
// * Conditions - the latest available observations of a resource's current
|
||||||
|
// state.
|
||||||
|
// * SinkURI - the current active sink URI that has been configured for the
|
||||||
|
// Source.
|
||||||
|
duckv1.SourceStatus `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIVersionKind is an APIVersion and Kind tuple.
|
||||||
|
type APIVersionKind struct {
|
||||||
|
// APIVersion - the API version of the resource to watch.
|
||||||
|
APIVersion string `json:"apiVersion"`
|
||||||
|
|
||||||
|
// Kind of the resource to watch.
|
||||||
|
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIVersionKindSelector is an APIVersion Kind tuple with a LabelSelector.
|
||||||
|
type APIVersionKindSelector struct {
|
||||||
|
// APIVersion - the API version of the resource to watch.
|
||||||
|
APIVersion string `json:"apiVersion"`
|
||||||
|
|
||||||
|
// Kind of the resource to watch.
|
||||||
|
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
|
||||||
|
// LabelSelector filters this source to objects to those resources pass the
|
||||||
|
// label selector.
|
||||||
|
// More info: http://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
|
||||||
|
// +optional
|
||||||
|
LabelSelector *metav1.LabelSelector `json:"selector,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
// ApiServerSourceList contains a list of ApiServerSource
|
||||||
|
type ApiServerSourceList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ApiServerSource `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStatus retrieves the status of the ApiServerSource . Implements the KRShaped interface.
|
||||||
|
func (a *ApiServerSource) GetStatus() *duckv1.Status {
|
||||||
|
return &a.Status.Status
|
||||||
|
}
|
||||||
77
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/apiserver_validation.go
vendored
Normal file
77
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/apiserver_validation.go
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ReferenceMode produces payloads of ObjectReference
|
||||||
|
ReferenceMode = "Reference"
|
||||||
|
// ResourceMode produces payloads of ResourceEvent
|
||||||
|
ResourceMode = "Resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *ApiServerSource) Validate(ctx context.Context) *apis.FieldError {
|
||||||
|
return c.Spec.Validate(ctx).ViaField("spec")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ApiServerSourceSpec) Validate(ctx context.Context) *apis.FieldError {
|
||||||
|
var errs *apis.FieldError
|
||||||
|
|
||||||
|
// Validate mode, if can be empty or set as certain value
|
||||||
|
switch cs.EventMode {
|
||||||
|
case ReferenceMode, ResourceMode:
|
||||||
|
// EventMode is valid.
|
||||||
|
default:
|
||||||
|
errs = errs.Also(apis.ErrInvalidValue(cs.EventMode, "mode"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate sink
|
||||||
|
errs = errs.Also(cs.Sink.Validate(ctx).ViaField("sink"))
|
||||||
|
|
||||||
|
if len(cs.Resources) == 0 {
|
||||||
|
errs = errs.Also(apis.ErrMissingField("resources"))
|
||||||
|
}
|
||||||
|
for i, res := range cs.Resources {
|
||||||
|
_, err := schema.ParseGroupVersion(res.APIVersion)
|
||||||
|
if err != nil {
|
||||||
|
errs = errs.Also(apis.ErrInvalidValue(res.APIVersion, "apiVersion").ViaFieldIndex("resources", i))
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(res.Kind) == "" {
|
||||||
|
errs = errs.Also(apis.ErrMissingField("kind").ViaFieldIndex("resources", i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cs.ResourceOwner != nil {
|
||||||
|
_, err := schema.ParseGroupVersion(cs.ResourceOwner.APIVersion)
|
||||||
|
if err != nil {
|
||||||
|
errs = errs.Also(apis.ErrInvalidValue(cs.ResourceOwner.APIVersion, "apiVersion").ViaField("owner"))
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(cs.ResourceOwner.Kind) == "" {
|
||||||
|
errs = errs.Also(apis.ErrMissingField("kind").ViaField("owner"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
||||||
34
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/container_conversion.go
vendored
Normal file
34
vendor/knative.dev/eventing/pkg/apis/sources/v1beta1/container_conversion.go
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"knative.dev/pkg/apis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConvertTo implements apis.Convertible
|
||||||
|
func (source *ContainerSource) ConvertTo(ctx context.Context, sink apis.Convertible) error {
|
||||||
|
return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertFrom implements apis.Convertible
|
||||||
|
func (sink *ContainerSource) ConvertFrom(ctx context.Context, source apis.Convertible) error {
|
||||||
|
return fmt.Errorf("v1beta1 is the highest known version, got: %T", source)
|
||||||
|
}
|
||||||
|
|
@ -45,6 +45,8 @@ var (
|
||||||
// Adds the list of known types to Scheme.
|
// Adds the list of known types to Scheme.
|
||||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
|
&ApiServerSource{},
|
||||||
|
&ApiServerSourceList{},
|
||||||
&SinkBinding{},
|
&SinkBinding{},
|
||||||
&SinkBindingList{},
|
&SinkBindingList{},
|
||||||
&ContainerSource{},
|
&ContainerSource{},
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,154 @@ limitations under the License.
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *APIVersionKind) DeepCopyInto(out *APIVersionKind) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIVersionKind.
|
||||||
|
func (in *APIVersionKind) DeepCopy() *APIVersionKind {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(APIVersionKind)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *APIVersionKindSelector) DeepCopyInto(out *APIVersionKindSelector) {
|
||||||
|
*out = *in
|
||||||
|
if in.LabelSelector != nil {
|
||||||
|
in, out := &in.LabelSelector, &out.LabelSelector
|
||||||
|
*out = new(v1.LabelSelector)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIVersionKindSelector.
|
||||||
|
func (in *APIVersionKindSelector) DeepCopy() *APIVersionKindSelector {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(APIVersionKindSelector)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ApiServerSource) DeepCopyInto(out *ApiServerSource) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
|
in.Status.DeepCopyInto(&out.Status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiServerSource.
|
||||||
|
func (in *ApiServerSource) DeepCopy() *ApiServerSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ApiServerSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ApiServerSource) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ApiServerSourceList) DeepCopyInto(out *ApiServerSourceList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ApiServerSource, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiServerSourceList.
|
||||||
|
func (in *ApiServerSourceList) DeepCopy() *ApiServerSourceList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ApiServerSourceList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ApiServerSourceList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ApiServerSourceSpec) DeepCopyInto(out *ApiServerSourceSpec) {
|
||||||
|
*out = *in
|
||||||
|
in.SourceSpec.DeepCopyInto(&out.SourceSpec)
|
||||||
|
if in.Resources != nil {
|
||||||
|
in, out := &in.Resources, &out.Resources
|
||||||
|
*out = make([]APIVersionKindSelector, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if in.ResourceOwner != nil {
|
||||||
|
in, out := &in.ResourceOwner, &out.ResourceOwner
|
||||||
|
*out = new(APIVersionKind)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiServerSourceSpec.
|
||||||
|
func (in *ApiServerSourceSpec) DeepCopy() *ApiServerSourceSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ApiServerSourceSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ApiServerSourceStatus) DeepCopyInto(out *ApiServerSourceStatus) {
|
||||||
|
*out = *in
|
||||||
|
in.SourceStatus.DeepCopyInto(&out.SourceStatus)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiServerSourceStatus.
|
||||||
|
func (in *ApiServerSourceStatus) DeepCopy() *ApiServerSourceStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ApiServerSourceStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ContainerSource) DeepCopyInto(out *ContainerSource) {
|
func (in *ContainerSource) DeepCopyInto(out *ContainerSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
|
||||||
|
cm "knative.dev/pkg/configmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultsConfigName is the name of config map for the defaults.
|
||||||
|
DefaultsConfigName = "config-defaults"
|
||||||
|
|
||||||
|
// DefaultRevisionTimeoutSeconds will be set if timeoutSeconds not specified.
|
||||||
|
DefaultRevisionTimeoutSeconds = 5 * 60
|
||||||
|
|
||||||
|
// DefaultMaxRevisionTimeoutSeconds will be set if MaxRevisionTimeoutSeconds is not specified.
|
||||||
|
DefaultMaxRevisionTimeoutSeconds = 10 * 60
|
||||||
|
)
|
||||||
|
|
||||||
|
func defaultConfig() *Defaults {
|
||||||
|
return &Defaults{
|
||||||
|
RevisionTimeoutSeconds: DefaultRevisionTimeoutSeconds,
|
||||||
|
MaxRevisionTimeoutSeconds: DefaultMaxRevisionTimeoutSeconds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultsConfigFromMap creates a Defaults from the supplied Map.
|
||||||
|
func NewDefaultsConfigFromMap(data map[string]string) (*Defaults, error) {
|
||||||
|
nc := defaultConfig()
|
||||||
|
|
||||||
|
if err := cm.Parse(data,
|
||||||
|
cm.AsInt64("revision-timeout-seconds", &nc.RevisionTimeoutSeconds),
|
||||||
|
cm.AsInt64("max-revision-timeout-seconds", &nc.MaxRevisionTimeoutSeconds),
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if nc.RevisionTimeoutSeconds > nc.MaxRevisionTimeoutSeconds {
|
||||||
|
return nil, fmt.Errorf("revision-timeout-seconds (%d) cannot be greater than max-revision-timeout-seconds (%d)", nc.RevisionTimeoutSeconds, nc.MaxRevisionTimeoutSeconds)
|
||||||
|
}
|
||||||
|
return nc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultsConfigFromConfigMap creates a Defaults from the supplied configMap.
|
||||||
|
func NewDefaultsConfigFromConfigMap(config *corev1.ConfigMap) (*Defaults, error) {
|
||||||
|
return NewDefaultsConfigFromMap(config.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defaults includes the default values to be populated by the webhook.
|
||||||
|
type Defaults struct {
|
||||||
|
RevisionTimeoutSeconds int64
|
||||||
|
// This is the timeout set for ingress.
|
||||||
|
// RevisionTimeoutSeconds must be less than this value.
|
||||||
|
MaxRevisionTimeoutSeconds int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// asQuantity parses the value at key as a *resource.Quantity into the target, if it exists.
|
||||||
|
func asQuantity(key string, target **resource.Quantity) cm.ParseFunc {
|
||||||
|
return func(data map[string]string) error {
|
||||||
|
if raw, ok := data[key]; !ok {
|
||||||
|
*target = nil
|
||||||
|
} else if val, err := resource.ParseQuantity(raw); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
*target = &val
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=package
|
||||||
|
|
||||||
|
// Package config holds the typed objects that define the schemas for
|
||||||
|
// ConfigMap objects that pertain to our API objects.
|
||||||
|
package config
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"knative.dev/pkg/configmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cfgKey struct{}
|
||||||
|
|
||||||
|
// Config holds the collection of configurations that we attach to contexts.
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type Config struct {
|
||||||
|
Defaults *Defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext extracts a Config from the provided context.
|
||||||
|
func FromContext(ctx context.Context) *Config {
|
||||||
|
x, ok := ctx.Value(cfgKey{}).(*Config)
|
||||||
|
if ok {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContextOrDefaults is like FromContext, but when no Config is attached it
|
||||||
|
// returns a Config populated with the defaults for each of the Config fields.
|
||||||
|
func FromContextOrDefaults(ctx context.Context) *Config {
|
||||||
|
if cfg := FromContext(ctx); cfg != nil {
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
defaults, _ := NewDefaultsConfigFromMap(map[string]string{})
|
||||||
|
return &Config{
|
||||||
|
Defaults: defaults,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContext attaches the provided Config to the provided context, returning the
|
||||||
|
// new context with the Config attached.
|
||||||
|
func ToContext(ctx context.Context, c *Config) context.Context {
|
||||||
|
return context.WithValue(ctx, cfgKey{}, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store is a typed wrapper around configmap.Untyped store to handle our configmaps.
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type Store struct {
|
||||||
|
*configmap.UntypedStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStore creates a new store of Configs and optionally calls functions when ConfigMaps are updated.
|
||||||
|
func NewStore(logger configmap.Logger, onAfterStore ...func(name string, value interface{})) *Store {
|
||||||
|
store := &Store{
|
||||||
|
UntypedStore: configmap.NewUntypedStore(
|
||||||
|
"defaults",
|
||||||
|
logger,
|
||||||
|
configmap.Constructors{
|
||||||
|
DefaultsConfigName: NewDefaultsConfigFromConfigMap,
|
||||||
|
},
|
||||||
|
onAfterStore...,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContext attaches the current Config state to the provided context.
|
||||||
|
func (s *Store) ToContext(ctx context.Context) context.Context {
|
||||||
|
return ToContext(ctx, s.Load())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load creates a Config from the current config state of the Store.
|
||||||
|
func (s *Store) Load() *Config {
|
||||||
|
return &Config{
|
||||||
|
Defaults: s.UntypedLoad(DefaultsConfigName).(*Defaults).DeepCopy(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Knative Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Defaults) DeepCopyInto(out *Defaults) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Defaults.
|
||||||
|
func (in *Defaults) DeepCopy() *Defaults {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Defaults)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
@ -18,8 +18,12 @@ package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
|
|
||||||
|
"knative.dev/networking/pkg/apis/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetDefaults populates default values in Ingress
|
// SetDefaults populates default values in Ingress
|
||||||
|
|
@ -65,4 +69,11 @@ func (p *HTTPIngressPath) SetDefaults(ctx context.Context) {
|
||||||
if len(p.Splits) == 1 && p.Splits[0].Percent == 0 {
|
if len(p.Splits) == 1 && p.Splits[0].Percent == 0 {
|
||||||
p.Splits[0].Percent = 100
|
p.Splits[0].Percent = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg := config.FromContextOrDefaults(ctx)
|
||||||
|
maxTimeout := time.Duration(cfg.Defaults.MaxRevisionTimeoutSeconds) * time.Second
|
||||||
|
|
||||||
|
if p.Timeout == nil {
|
||||||
|
p.Timeout = &metav1.Duration{Duration: maxTimeout}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// +genclient
|
// +genclient
|
||||||
// +genreconciler:krshapedlogic=true
|
// +genreconciler:class=networking.knative.dev/ingress.class,krshapedlogic=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
// Ingress is a collection of rules that allow inbound connections to reach the endpoints defined
|
// Ingress is a collection of rules that allow inbound connections to reach the endpoints defined
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,11 @@ const (
|
||||||
func defaultFeaturesConfig() *Features {
|
func defaultFeaturesConfig() *Features {
|
||||||
return &Features{
|
return &Features{
|
||||||
MultiContainer: Disabled,
|
MultiContainer: Disabled,
|
||||||
|
PodSpecAffinity: Disabled,
|
||||||
PodSpecFieldRef: Disabled,
|
PodSpecFieldRef: Disabled,
|
||||||
PodSpecDryRun: Allowed,
|
PodSpecDryRun: Enabled,
|
||||||
|
PodSpecNodeSelector: Disabled,
|
||||||
|
PodSpecTolerations: Disabled,
|
||||||
ResponsiveRevisionGC: Disabled,
|
ResponsiveRevisionGC: Disabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,8 +56,11 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) {
|
||||||
|
|
||||||
if err := cm.Parse(data,
|
if err := cm.Parse(data,
|
||||||
asFlag("multi-container", &nc.MultiContainer),
|
asFlag("multi-container", &nc.MultiContainer),
|
||||||
|
asFlag("kubernetes.podspec-affinity", &nc.PodSpecAffinity),
|
||||||
asFlag("kubernetes.podspec-fieldref", &nc.PodSpecFieldRef),
|
asFlag("kubernetes.podspec-fieldref", &nc.PodSpecFieldRef),
|
||||||
asFlag("kubernetes.podspec-dryrun", &nc.PodSpecDryRun),
|
asFlag("kubernetes.podspec-dryrun", &nc.PodSpecDryRun),
|
||||||
|
asFlag("kubernetes.podspec-nodeselector", &nc.PodSpecNodeSelector),
|
||||||
|
asFlag("kubernetes.podspec-tolerations", &nc.PodSpecTolerations),
|
||||||
asFlag("responsive-revision-gc", &nc.ResponsiveRevisionGC)); err != nil {
|
asFlag("responsive-revision-gc", &nc.ResponsiveRevisionGC)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -69,8 +75,11 @@ func NewFeaturesConfigFromConfigMap(config *corev1.ConfigMap) (*Features, error)
|
||||||
// Features specifies which features are allowed by the webhook.
|
// Features specifies which features are allowed by the webhook.
|
||||||
type Features struct {
|
type Features struct {
|
||||||
MultiContainer Flag
|
MultiContainer Flag
|
||||||
|
PodSpecAffinity Flag
|
||||||
PodSpecFieldRef Flag
|
PodSpecFieldRef Flag
|
||||||
PodSpecDryRun Flag
|
PodSpecDryRun Flag
|
||||||
|
PodSpecNodeSelector Flag
|
||||||
|
PodSpecTolerations Flag
|
||||||
ResponsiveRevisionGC Flag
|
ResponsiveRevisionGC Flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,17 +45,23 @@ func FromContext(ctx context.Context) *Config {
|
||||||
// FromContextOrDefaults is like FromContext, but when no Config is attached it
|
// FromContextOrDefaults is like FromContext, but when no Config is attached it
|
||||||
// returns a Config populated with the defaults for each of the Config fields.
|
// returns a Config populated with the defaults for each of the Config fields.
|
||||||
func FromContextOrDefaults(ctx context.Context) *Config {
|
func FromContextOrDefaults(ctx context.Context) *Config {
|
||||||
if cfg := FromContext(ctx); cfg != nil {
|
cfg := FromContext(ctx)
|
||||||
|
if cfg == nil {
|
||||||
|
cfg = &Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Defaults == nil {
|
||||||
|
cfg.Defaults, _ = NewDefaultsConfigFromMap(map[string]string{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Features == nil {
|
||||||
|
cfg.Features, _ = NewFeaturesConfigFromMap(map[string]string{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Autoscaler == nil {
|
||||||
|
cfg.Autoscaler, _ = autoscalerconfig.NewConfigFromMap(map[string]string{})
|
||||||
|
}
|
||||||
return cfg
|
return cfg
|
||||||
}
|
|
||||||
defaults, _ := NewDefaultsConfigFromMap(map[string]string{})
|
|
||||||
features, _ := NewFeaturesConfigFromMap(map[string]string{})
|
|
||||||
autoscaler, _ := autoscalerconfig.NewConfigFromMap(map[string]string{})
|
|
||||||
return &Config{
|
|
||||||
Defaults: defaults,
|
|
||||||
Features: features,
|
|
||||||
Autoscaler: autoscaler,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContext attaches the provided Config to the provided context, returning the
|
// ToContext attaches the provided Config to the provided context, returning the
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,10 @@ limitations under the License.
|
||||||
package serving
|
package serving
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"knative.dev/serving/pkg/apis/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VolumeMask performs a _shallow_ copy of the Kubernetes Volume object to a new
|
// VolumeMask performs a _shallow_ copy of the Kubernetes Volume object to a new
|
||||||
|
|
@ -136,11 +139,12 @@ func KeyToPathMask(in *corev1.KeyToPath) *corev1.KeyToPath {
|
||||||
// PodSpecMask performs a _shallow_ copy of the Kubernetes PodSpec object to a new
|
// PodSpecMask performs a _shallow_ copy of the Kubernetes PodSpec object to a new
|
||||||
// Kubernetes PodSpec object bringing over only the fields allowed in the Knative API. This
|
// Kubernetes PodSpec object bringing over only the fields allowed in the Knative API. This
|
||||||
// does not validate the contents or the bounds of the provided fields.
|
// does not validate the contents or the bounds of the provided fields.
|
||||||
func PodSpecMask(in *corev1.PodSpec) *corev1.PodSpec {
|
func PodSpecMask(ctx context.Context, in *corev1.PodSpec) *corev1.PodSpec {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg := config.FromContextOrDefaults(ctx)
|
||||||
out := new(corev1.PodSpec)
|
out := new(corev1.PodSpec)
|
||||||
|
|
||||||
// Allowed fields
|
// Allowed fields
|
||||||
|
|
@ -150,6 +154,17 @@ func PodSpecMask(in *corev1.PodSpec) *corev1.PodSpec {
|
||||||
out.ImagePullSecrets = in.ImagePullSecrets
|
out.ImagePullSecrets = in.ImagePullSecrets
|
||||||
out.EnableServiceLinks = in.EnableServiceLinks
|
out.EnableServiceLinks = in.EnableServiceLinks
|
||||||
|
|
||||||
|
// Feature fields
|
||||||
|
if cfg.Features.PodSpecAffinity != config.Disabled {
|
||||||
|
out.Affinity = in.Affinity
|
||||||
|
}
|
||||||
|
if cfg.Features.PodSpecNodeSelector != config.Disabled {
|
||||||
|
out.NodeSelector = in.NodeSelector
|
||||||
|
}
|
||||||
|
if cfg.Features.PodSpecTolerations != config.Disabled {
|
||||||
|
out.Tolerations = in.Tolerations
|
||||||
|
}
|
||||||
|
|
||||||
// Disallowed fields
|
// Disallowed fields
|
||||||
// This list is unnecessary, but added here for clarity
|
// This list is unnecessary, but added here for clarity
|
||||||
out.InitContainers = nil
|
out.InitContainers = nil
|
||||||
|
|
@ -157,7 +172,6 @@ func PodSpecMask(in *corev1.PodSpec) *corev1.PodSpec {
|
||||||
out.TerminationGracePeriodSeconds = nil
|
out.TerminationGracePeriodSeconds = nil
|
||||||
out.ActiveDeadlineSeconds = nil
|
out.ActiveDeadlineSeconds = nil
|
||||||
out.DNSPolicy = ""
|
out.DNSPolicy = ""
|
||||||
out.NodeSelector = nil
|
|
||||||
out.AutomountServiceAccountToken = nil
|
out.AutomountServiceAccountToken = nil
|
||||||
out.NodeName = ""
|
out.NodeName = ""
|
||||||
out.HostNetwork = false
|
out.HostNetwork = false
|
||||||
|
|
@ -167,9 +181,7 @@ func PodSpecMask(in *corev1.PodSpec) *corev1.PodSpec {
|
||||||
out.SecurityContext = nil
|
out.SecurityContext = nil
|
||||||
out.Hostname = ""
|
out.Hostname = ""
|
||||||
out.Subdomain = ""
|
out.Subdomain = ""
|
||||||
out.Affinity = nil
|
|
||||||
out.SchedulerName = ""
|
out.SchedulerName = ""
|
||||||
out.Tolerations = nil
|
|
||||||
out.HostAliases = nil
|
out.HostAliases = nil
|
||||||
out.PriorityClassName = ""
|
out.PriorityClassName = ""
|
||||||
out.Priority = nil
|
out.Priority = nil
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,14 @@ var (
|
||||||
"K_REVISION",
|
"K_REVISION",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
reservedPorts = sets.NewInt32(
|
||||||
|
networking.BackendHTTPPort,
|
||||||
|
networking.BackendHTTP2Port,
|
||||||
|
networking.QueueAdminPort,
|
||||||
|
networking.AutoscalingQueueMetricsPort,
|
||||||
|
networking.UserQueueMetricsPort,
|
||||||
|
profiling.ProfilingPort)
|
||||||
|
|
||||||
reservedSidecarEnvVars = reservedEnvVars.Difference(sets.NewString("PORT"))
|
reservedSidecarEnvVars = reservedEnvVars.Difference(sets.NewString("PORT"))
|
||||||
|
|
||||||
// The port is named "user-port" on the deployment, but a user cannot set an arbitrary name on the port
|
// The port is named "user-port" on the deployment, but a user cannot set an arbitrary name on the port
|
||||||
|
|
@ -263,7 +271,7 @@ func ValidatePodSpec(ctx context.Context, ps corev1.PodSpec) *apis.FieldError {
|
||||||
// return apis.ErrMissingField(apis.CurrentField)
|
// return apis.ErrMissingField(apis.CurrentField)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
errs := apis.CheckDisallowedFields(ps, *PodSpecMask(&ps))
|
errs := apis.CheckDisallowedFields(ps, *PodSpecMask(ctx, &ps))
|
||||||
|
|
||||||
volumes, err := ValidateVolumes(ps.Volumes, AllMountedVolumes(ps.Containers))
|
volumes, err := ValidateVolumes(ps.Volumes, AllMountedVolumes(ps.Containers))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -501,13 +509,8 @@ func validateContainerPorts(ports []corev1.ContainerPort) *apis.FieldError {
|
||||||
errs = errs.Also(apis.ErrInvalidValue(userPort.Protocol, "protocol"))
|
errs = errs.Also(apis.ErrInvalidValue(userPort.Protocol, "protocol"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow userPort to conflict with QueueProxy sidecar
|
// Don't allow userPort to conflict with knative system reserved ports
|
||||||
if userPort.ContainerPort == networking.BackendHTTPPort ||
|
if reservedPorts.Has(userPort.ContainerPort) {
|
||||||
userPort.ContainerPort == networking.BackendHTTP2Port ||
|
|
||||||
userPort.ContainerPort == networking.QueueAdminPort ||
|
|
||||||
userPort.ContainerPort == networking.AutoscalingQueueMetricsPort ||
|
|
||||||
userPort.ContainerPort == networking.UserQueueMetricsPort ||
|
|
||||||
userPort.ContainerPort == profiling.ProfilingPort {
|
|
||||||
errs = errs.Also(apis.ErrInvalidValue(userPort.ContainerPort, "containerPort"))
|
errs = errs.Also(apis.ErrInvalidValue(userPort.ContainerPort, "containerPort"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ var (
|
||||||
RevisionLastPinnedAnnotationKey,
|
RevisionLastPinnedAnnotationKey,
|
||||||
RoutingStateModifiedAnnotationKey,
|
RoutingStateModifiedAnnotationKey,
|
||||||
GroupNamePrefix+"forceUpgrade",
|
GroupNamePrefix+"forceUpgrade",
|
||||||
|
RevisionPreservedAnnotationKey,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ const (
|
||||||
// pinned a revision
|
// pinned a revision
|
||||||
RevisionLastPinnedAnnotationKey = GroupName + "/lastPinned"
|
RevisionLastPinnedAnnotationKey = GroupName + "/lastPinned"
|
||||||
|
|
||||||
|
// RevisionPreservedAnnotationKey is the annotation key used for preventing garbage collector
|
||||||
|
// from automatically deleting the revision.
|
||||||
|
RevisionPreservedAnnotationKey = GroupName + "/no-gc"
|
||||||
|
|
||||||
// RouteLabelKey is the label key attached to a Configuration indicating by
|
// RouteLabelKey is the label key attached to a Configuration indicating by
|
||||||
// which Route it is configured as traffic target.
|
// which Route it is configured as traffic target.
|
||||||
// The key is also attached to Revision resources to indicate they are directly
|
// The key is also attached to Revision resources to indicate they are directly
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"knative.dev/pkg/apis"
|
"knative.dev/pkg/apis"
|
||||||
"knative.dev/pkg/kmeta"
|
"knative.dev/pkg/kmeta"
|
||||||
"knative.dev/pkg/ptr"
|
"knative.dev/pkg/ptr"
|
||||||
|
|
@ -43,24 +43,44 @@ func (rts *RevisionTemplateSpec) SetDefaults(ctx context.Context) {
|
||||||
func (rs *RevisionSpec) SetDefaults(ctx context.Context) {
|
func (rs *RevisionSpec) SetDefaults(ctx context.Context) {
|
||||||
cfg := config.FromContextOrDefaults(ctx)
|
cfg := config.FromContextOrDefaults(ctx)
|
||||||
|
|
||||||
// Default TimeoutSeconds based on our configmap
|
// Default TimeoutSeconds based on our configmap.
|
||||||
if rs.TimeoutSeconds == nil || *rs.TimeoutSeconds == 0 {
|
if rs.TimeoutSeconds == nil || *rs.TimeoutSeconds == 0 {
|
||||||
rs.TimeoutSeconds = ptr.Int64(cfg.Defaults.RevisionTimeoutSeconds)
|
rs.TimeoutSeconds = ptr.Int64(cfg.Defaults.RevisionTimeoutSeconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default ContainerConcurrency based on our configmap
|
// Default ContainerConcurrency based on our configmap.
|
||||||
if rs.ContainerConcurrency == nil {
|
if rs.ContainerConcurrency == nil {
|
||||||
rs.ContainerConcurrency = ptr.Int64(cfg.Defaults.ContainerConcurrency)
|
rs.ContainerConcurrency = ptr.Int64(cfg.Defaults.ContainerConcurrency)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Avoid clashes with user-supplied names when generating defaults.
|
||||||
|
userContainerNames := make(sets.String, len(rs.PodSpec.Containers))
|
||||||
|
for idx := range rs.PodSpec.Containers {
|
||||||
|
userContainerNames.Insert(rs.PodSpec.Containers[idx].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default container name based on UserContainerName value from configmap.
|
||||||
|
// In multi-container mode, add a numeric suffix, avoiding clashes with user-supplied names.
|
||||||
|
nextSuffix := 0
|
||||||
|
defaultContainerName := cfg.Defaults.UserContainerName(ctx)
|
||||||
for idx := range rs.PodSpec.Containers {
|
for idx := range rs.PodSpec.Containers {
|
||||||
if rs.PodSpec.Containers[idx].Name == "" {
|
if rs.PodSpec.Containers[idx].Name == "" {
|
||||||
|
name := defaultContainerName
|
||||||
|
|
||||||
if len(rs.PodSpec.Containers) > 1 {
|
if len(rs.PodSpec.Containers) > 1 {
|
||||||
rs.PodSpec.Containers[idx].Name = kmeta.ChildName(cfg.Defaults.UserContainerName(ctx), "-"+uuid.New().String())
|
for {
|
||||||
} else {
|
name = kmeta.ChildName(defaultContainerName, "-"+strconv.Itoa(nextSuffix))
|
||||||
rs.PodSpec.Containers[idx].Name = cfg.Defaults.UserContainerName(ctx)
|
nextSuffix++
|
||||||
|
|
||||||
|
// Continue until we get a name that doesn't clash with a user-supplied name.
|
||||||
|
if !userContainerNames.Has(name) {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.PodSpec.Containers[idx].Name = name
|
||||||
|
}
|
||||||
|
|
||||||
rs.applyDefault(&rs.PodSpec.Containers[idx], cfg)
|
rs.applyDefault(&rs.PodSpec.Containers[idx], cfg)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ func (rs *RevisionSpec) GetContainer() *corev1.Container {
|
||||||
|
|
||||||
// SetRoutingState sets the routingState label on this Revision and updates the
|
// SetRoutingState sets the routingState label on this Revision and updates the
|
||||||
// routingStateModified annotation.
|
// routingStateModified annotation.
|
||||||
func (r *Revision) SetRoutingState(state RoutingState) {
|
func (r *Revision) SetRoutingState(state RoutingState, clock clock.Clock) {
|
||||||
stateStr := string(state)
|
stateStr := string(state)
|
||||||
if t := r.ObjectMeta.Annotations[serving.RoutingStateModifiedAnnotationKey]; t != "" &&
|
if t := r.ObjectMeta.Annotations[serving.RoutingStateModifiedAnnotationKey]; t != "" &&
|
||||||
r.Labels[serving.RoutingStateLabelKey] == stateStr {
|
r.Labels[serving.RoutingStateLabelKey] == stateStr {
|
||||||
|
|
@ -123,7 +123,7 @@ func (r *Revision) SetRoutingState(state RoutingState) {
|
||||||
|
|
||||||
r.Annotations = kmeta.UnionMaps(r.Annotations,
|
r.Annotations = kmeta.UnionMaps(r.Annotations,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
serving.RoutingStateModifiedAnnotationKey: RoutingStateModifiedString(clock.RealClock{}),
|
serving.RoutingStateModifiedAnnotationKey: RoutingStateModifiedString(clock),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,13 +119,18 @@ func (rs *RevisionStatus) Validate(ctx context.Context) *apis.FieldError {
|
||||||
// ValidateLabels function validates service labels
|
// ValidateLabels function validates service labels
|
||||||
func (r *Revision) ValidateLabels() (errs *apis.FieldError) {
|
func (r *Revision) ValidateLabels() (errs *apis.FieldError) {
|
||||||
for key, val := range r.GetLabels() {
|
for key, val := range r.GetLabels() {
|
||||||
switch {
|
switch key {
|
||||||
case key == serving.RouteLabelKey || key == serving.ServiceLabelKey || key == serving.ConfigurationGenerationLabelKey:
|
case serving.RoutingStateLabelKey:
|
||||||
case key == serving.ConfigurationLabelKey:
|
case serving.RouteLabelKey:
|
||||||
|
case serving.ServiceLabelKey:
|
||||||
|
case serving.ConfigurationGenerationLabelKey:
|
||||||
|
case serving.ConfigurationLabelKey:
|
||||||
errs = errs.Also(verifyLabelOwnerRef(val, serving.ConfigurationLabelKey, "Configuration", r.GetOwnerReferences()))
|
errs = errs.Also(verifyLabelOwnerRef(val, serving.ConfigurationLabelKey, "Configuration", r.GetOwnerReferences()))
|
||||||
case strings.HasPrefix(key, serving.GroupNamePrefix):
|
default:
|
||||||
|
if strings.HasPrefix(key, serving.GroupNamePrefix) {
|
||||||
errs = errs.Also(apis.ErrInvalidKeyName(key, ""))
|
errs = errs.Also(apis.ErrInvalidKeyName(key, ""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# cloud.google.com/go v0.60.0
|
# cloud.google.com/go v0.61.0
|
||||||
cloud.google.com/go/compute/metadata
|
cloud.google.com/go/compute/metadata
|
||||||
# github.com/PuerkitoBio/purell v1.1.1
|
# github.com/PuerkitoBio/purell v1.1.1
|
||||||
github.com/PuerkitoBio/purell
|
github.com/PuerkitoBio/purell
|
||||||
|
|
@ -36,19 +36,17 @@ github.com/golang/protobuf/ptypes/duration
|
||||||
github.com/golang/protobuf/ptypes/timestamp
|
github.com/golang/protobuf/ptypes/timestamp
|
||||||
# github.com/google/btree v1.0.0
|
# github.com/google/btree v1.0.0
|
||||||
github.com/google/btree
|
github.com/google/btree
|
||||||
# github.com/google/go-cmp v0.5.0
|
# github.com/google/go-cmp v0.5.1
|
||||||
github.com/google/go-cmp/cmp
|
github.com/google/go-cmp/cmp
|
||||||
github.com/google/go-cmp/cmp/cmpopts
|
github.com/google/go-cmp/cmp/cmpopts
|
||||||
github.com/google/go-cmp/cmp/internal/diff
|
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.1.1
|
# github.com/google/go-containerregistry v0.1.2-0.20200717224239-a84993334b27
|
||||||
github.com/google/go-containerregistry/pkg/name
|
github.com/google/go-containerregistry/pkg/name
|
||||||
# github.com/google/gofuzz v1.1.0
|
# github.com/google/gofuzz v1.1.0
|
||||||
github.com/google/gofuzz
|
github.com/google/gofuzz
|
||||||
# github.com/google/uuid v1.1.1
|
|
||||||
github.com/google/uuid
|
|
||||||
# github.com/googleapis/gnostic v0.4.0
|
# github.com/googleapis/gnostic v0.4.0
|
||||||
github.com/googleapis/gnostic/OpenAPIv2
|
github.com/googleapis/gnostic/OpenAPIv2
|
||||||
github.com/googleapis/gnostic/compiler
|
github.com/googleapis/gnostic/compiler
|
||||||
|
|
@ -100,6 +98,10 @@ github.com/peterbourgon/diskv
|
||||||
# github.com/pkg/errors v0.9.1
|
# github.com/pkg/errors v0.9.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/pkg/errors
|
github.com/pkg/errors
|
||||||
|
# github.com/rickb777/date v1.13.0
|
||||||
|
github.com/rickb777/date/period
|
||||||
|
# github.com/rickb777/plural v1.2.1
|
||||||
|
github.com/rickb777/plural
|
||||||
# github.com/robfig/cron/v3 v3.0.1
|
# github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/robfig/cron/v3
|
github.com/robfig/cron/v3
|
||||||
# github.com/russross/blackfriday/v2 v2.0.1
|
# github.com/russross/blackfriday/v2 v2.0.1
|
||||||
|
|
@ -155,7 +157,7 @@ golang.org/x/oauth2/google
|
||||||
golang.org/x/oauth2/internal
|
golang.org/x/oauth2/internal
|
||||||
golang.org/x/oauth2/jws
|
golang.org/x/oauth2/jws
|
||||||
golang.org/x/oauth2/jwt
|
golang.org/x/oauth2/jwt
|
||||||
# golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae
|
# golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6
|
||||||
golang.org/x/sys/internal/unsafeheader
|
golang.org/x/sys/internal/unsafeheader
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
|
|
@ -171,9 +173,9 @@ golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/bidi
|
golang.org/x/text/unicode/bidi
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
golang.org/x/text/width
|
golang.org/x/text/width
|
||||||
# golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
|
# golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||||
golang.org/x/time/rate
|
golang.org/x/time/rate
|
||||||
# golang.org/x/tools v0.0.0-20200710042808-f1c4188a97a1
|
# golang.org/x/tools v0.0.0-20200723000907-a7c6fd066f6d
|
||||||
golang.org/x/tools/go/ast/astutil
|
golang.org/x/tools/go/ast/astutil
|
||||||
golang.org/x/tools/imports
|
golang.org/x/tools/imports
|
||||||
golang.org/x/tools/internal/event
|
golang.org/x/tools/internal/event
|
||||||
|
|
@ -310,7 +312,7 @@ k8s.io/api/settings/v1alpha1
|
||||||
k8s.io/api/storage/v1
|
k8s.io/api/storage/v1
|
||||||
k8s.io/api/storage/v1alpha1
|
k8s.io/api/storage/v1alpha1
|
||||||
k8s.io/api/storage/v1beta1
|
k8s.io/api/storage/v1beta1
|
||||||
# k8s.io/apimachinery v0.18.5 => k8s.io/apimachinery v0.17.6
|
# k8s.io/apimachinery v0.18.6 => k8s.io/apimachinery v0.17.6
|
||||||
## explicit
|
## explicit
|
||||||
k8s.io/apimachinery/pkg/api/apitesting/fuzzer
|
k8s.io/apimachinery/pkg/api/apitesting/fuzzer
|
||||||
k8s.io/apimachinery/pkg/api/equality
|
k8s.io/apimachinery/pkg/api/equality
|
||||||
|
|
@ -603,7 +605,7 @@ k8s.io/kube-openapi/pkg/util/sets
|
||||||
k8s.io/utils/buffer
|
k8s.io/utils/buffer
|
||||||
k8s.io/utils/integer
|
k8s.io/utils/integer
|
||||||
k8s.io/utils/trace
|
k8s.io/utils/trace
|
||||||
# knative.dev/eventing v0.16.1-0.20200715062032-28f9f61e6131
|
# knative.dev/eventing v0.16.1-0.20200724032657-8d83431c07bd
|
||||||
## explicit
|
## explicit
|
||||||
knative.dev/eventing/pkg/apis/config
|
knative.dev/eventing/pkg/apis/config
|
||||||
knative.dev/eventing/pkg/apis/configs
|
knative.dev/eventing/pkg/apis/configs
|
||||||
|
|
@ -631,10 +633,11 @@ knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1/fake
|
||||||
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha2
|
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha2
|
||||||
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha2/fake
|
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha2/fake
|
||||||
knative.dev/eventing/pkg/logging
|
knative.dev/eventing/pkg/logging
|
||||||
# knative.dev/networking v0.0.0-20200713162319-e2731eead7e8
|
# knative.dev/networking v0.0.0-20200723155758-cc457d7322d6
|
||||||
|
knative.dev/networking/pkg/apis/config
|
||||||
knative.dev/networking/pkg/apis/networking
|
knative.dev/networking/pkg/apis/networking
|
||||||
knative.dev/networking/pkg/apis/networking/v1alpha1
|
knative.dev/networking/pkg/apis/networking/v1alpha1
|
||||||
# knative.dev/pkg v0.0.0-20200714233132-cb1281d05cc8
|
# knative.dev/pkg v0.0.0-20200724211057-f21f66204a5c
|
||||||
## explicit
|
## explicit
|
||||||
knative.dev/pkg/apis
|
knative.dev/pkg/apis
|
||||||
knative.dev/pkg/apis/duck
|
knative.dev/pkg/apis/duck
|
||||||
|
|
@ -652,7 +655,7 @@ knative.dev/pkg/logging/logkey
|
||||||
knative.dev/pkg/profiling
|
knative.dev/pkg/profiling
|
||||||
knative.dev/pkg/ptr
|
knative.dev/pkg/ptr
|
||||||
knative.dev/pkg/tracker
|
knative.dev/pkg/tracker
|
||||||
# knative.dev/serving v0.16.1-0.20200715073232-81d40bfc82a6
|
# knative.dev/serving v0.16.1-0.20200724203457-1517b1735305
|
||||||
## explicit
|
## explicit
|
||||||
knative.dev/serving/pkg/apis/autoscaling
|
knative.dev/serving/pkg/apis/autoscaling
|
||||||
knative.dev/serving/pkg/apis/autoscaling/v1alpha1
|
knative.dev/serving/pkg/apis/autoscaling/v1alpha1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue