Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d573007747 | ||
|
|
f054b1c251 | ||
|
|
7a2358272a | ||
|
|
8a6a75b7a2 | ||
|
|
8cf678fb27 | ||
|
|
a20c6dc907 | ||
|
|
37ff8bb60d | ||
|
|
b6ac055857 | ||
|
|
12e53a1468 | ||
|
|
b21123e1cd | ||
|
|
f1db949abc | ||
|
|
761c6529a2 | ||
|
|
1f832fa294 | ||
|
|
be569aee4f | ||
|
|
419e94ccec | ||
|
|
12bc5265b8 | ||
|
|
32898f0c57 | ||
|
|
125c9abf56 | ||
|
|
bc27db4a69 | ||
|
|
dd8e2b13d3 | ||
|
|
005e3b941c | ||
|
|
efa614c773 |
@@ -11,40 +11,7 @@ $ docker run --rm -p 389:389 -p 636:636 --name my-openldap-container --detach os
|
||||
Run the `billy.ldif` file using `ldapadd` command to create a new user and assign it to a group.
|
||||
|
||||
```
|
||||
$ cat > billy.ldif << EOF
|
||||
# LDIF fragment to create group branch under root
|
||||
dn: uid=billy,dc=example,dc=org
|
||||
uid: billy
|
||||
cn: billy
|
||||
sn: 3
|
||||
objectClass: top
|
||||
objectClass: posixAccount
|
||||
objectClass: inetOrgPerson
|
||||
loginShell: /bin/bash
|
||||
homeDirectory: /home/billy
|
||||
uidNumber: 14583102
|
||||
gidNumber: 14564100
|
||||
userPassword: {SSHA}j3lBh1Seqe4rqF1+NuWmjhvtAni1JC5A
|
||||
mail: billy@example.org
|
||||
gecos: Billy User
|
||||
# Create base group
|
||||
dn: ou=groups,dc=example,dc=org
|
||||
objectclass:organizationalunit
|
||||
ou: groups
|
||||
description: generic groups branch
|
||||
# create consoleAdmin group (this already exists on minio and have a policy of s3::*)
|
||||
dn: cn=consoleAdmin,ou=groups,dc=example,dc=org
|
||||
objectClass: top
|
||||
objectClass: posixGroup
|
||||
gidNumber: 678
|
||||
# Assing group to new user
|
||||
dn: cn=consoleAdmin,ou=groups,dc=example,dc=org
|
||||
changetype: modify
|
||||
add: memberuid
|
||||
memberuid: billy
|
||||
EOF
|
||||
|
||||
$ docker cp billy.ldif my-openldap-container:/container/service/slapd/assets/test/billy.ldif
|
||||
$ docker cp console/docs/ldap/billy.ldif my-openldap-container:/container/service/slapd/assets/test/billy.ldif
|
||||
$ docker exec my-openldap-container ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin -f /container/service/slapd/assets/test/billy.ldif -H ldap://localhost -ZZ
|
||||
```
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ import (
|
||||
"github.com/minio/console/pkg/certs"
|
||||
"github.com/minio/console/restapi"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
certsx "github.com/minio/minio/pkg/certs"
|
||||
)
|
||||
|
||||
// starts the server
|
||||
@@ -107,19 +105,18 @@ func startServer(ctx *cli.Context) error {
|
||||
restapi.Hostname = ctx.String("host")
|
||||
restapi.Port = fmt.Sprintf("%v", ctx.Int("port"))
|
||||
|
||||
// Set all certs and CAs directories.
|
||||
// Set all certs and CAs directories path
|
||||
certs.GlobalCertsDir, _ = certs.NewConfigDirFromCtx(ctx, "certs-dir", certs.DefaultCertsDir.Get)
|
||||
certs.GlobalCertsCADir = &certs.ConfigDir{Path: filepath.Join(certs.GlobalCertsDir.Get(), certs.CertsCADir)}
|
||||
logger.FatalIf(certs.MkdirAllIgnorePerm(certs.GlobalCertsCADir.Get()), "Unable to create certs CA directory at %s", certs.GlobalCertsCADir.Get())
|
||||
|
||||
// load all CAs from ~/.console/certs/CAs
|
||||
restapi.GlobalRootCAs, err = certsx.GetRootCAs(certs.GlobalCertsCADir.Get())
|
||||
logger.FatalIf(err, "Failed to read root CAs (%v)", err)
|
||||
// load all certs from ~/.console/certs
|
||||
restapi.GlobalPublicCerts, restapi.GlobalTLSCertsManager, err = certs.GetTLSConfig()
|
||||
logger.FatalIf(err, "Unable to load the TLS configuration")
|
||||
// check if certs and CAs directories exists or can be created
|
||||
if err := certs.MkdirAllIgnorePerm(certs.GlobalCertsCADir.Get()); err != nil {
|
||||
log.Println(fmt.Sprintf("Unable to create certs CA directory at %s", certs.GlobalCertsCADir.Get()))
|
||||
}
|
||||
// load the certificates and the CAs
|
||||
restapi.GlobalRootCAs, restapi.GlobalPublicCerts, restapi.GlobalTLSCertsManager = certs.GetAllCertificatesAndCAs()
|
||||
|
||||
if len(restapi.GlobalPublicCerts) > 0 && restapi.GlobalRootCAs != nil {
|
||||
if len(restapi.GlobalPublicCerts) > 0 {
|
||||
// If TLS certificates are provided enforce the HTTPS schema, meaning console will redirect
|
||||
// plain HTTP connections to HTTPS server
|
||||
server.EnabledListeners = []string{"http", "https"}
|
||||
|
||||
35
docs/ldap/billy.ldif
Normal file
35
docs/ldap/billy.ldif
Normal file
@@ -0,0 +1,35 @@
|
||||
# LDIF fragment to create group branch under root
|
||||
dn: uid=billy,dc=example,dc=org
|
||||
uid: billy
|
||||
cn: billy
|
||||
sn: 3
|
||||
objectClass: top
|
||||
objectClass: posixAccount
|
||||
objectClass: inetOrgPerson
|
||||
loginShell: /bin/bash
|
||||
homeDirectory: /home/billy
|
||||
uidNumber: 14583102
|
||||
gidNumber: 14564100
|
||||
userPassword: {SSHA}j3lBh1Seqe4rqF1+NuWmjhvtAni1JC5A
|
||||
mail: billy@example.org
|
||||
gecos: Billy User
|
||||
|
||||
# Create base group
|
||||
dn: ou=groups,dc=example,dc=org
|
||||
objectclass:organizationalunit
|
||||
ou: groups
|
||||
description: generic groups branch
|
||||
|
||||
# create consoleAdmin group (this already exists on minio and have a policy of s3::*)
|
||||
dn: cn=consoleAdmin,ou=groups,dc=example,dc=org
|
||||
objectClass: top
|
||||
objectClass: posixGroup
|
||||
gidNumber: 678
|
||||
|
||||
# Assing group to new user
|
||||
dn: cn=consoleAdmin,ou=groups,dc=example,dc=org
|
||||
changetype: modify
|
||||
add: memberuid
|
||||
memberuid: billy
|
||||
|
||||
|
||||
10
go.mod
10
go.mod
@@ -16,17 +16,17 @@ require (
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/minio/cli v1.22.0
|
||||
github.com/minio/kes v0.11.0
|
||||
github.com/minio/mc v0.0.0-20201001165056-7f2df96e4821
|
||||
github.com/minio/minio v0.0.0-20200927172404-27d9bd04e544
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20200923173112-bc846cb9b089
|
||||
github.com/minio/mc v0.0.0-20201119214335-d4f9ea859d6c
|
||||
github.com/minio/minio v0.0.0-20201102034248-d8e07f2c41c8
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20201119032702-6914cb678dde
|
||||
github.com/minio/operator v0.0.0-20201022162018-527e5c32132b
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/secure-io/sio-go v0.3.1
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/unrolled/secure v1.0.7
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
k8s.io/api v0.18.6
|
||||
|
||||
188
go.sum
188
go.sum
@@ -2,7 +2,6 @@ bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.39.0 h1:UgQP9na6OTfp4dsAiz/eFpFA1C6tPdH5wiRdi19tuMw=
|
||||
cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
@@ -14,7 +13,6 @@ cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
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=
|
||||
@@ -31,7 +29,6 @@ cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjp
|
||||
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.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0 h1:86K1Gel7BQ9/WmNWn7dTKMvTLFzwtBe5FNqYbi9X35g=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
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=
|
||||
@@ -40,12 +37,9 @@ contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e
|
||||
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
|
||||
contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.apache.org/thrift.git v0.13.0 h1:/3bz5WZ+sqYArk7MBBBbDufMxKKOA56/6JO6psDpUDY=
|
||||
git.apache.org/thrift.git v0.13.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||
github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY=
|
||||
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
||||
github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
@@ -53,34 +47,26 @@ github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
|
||||
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
|
||||
github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o=
|
||||
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
|
||||
github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
|
||||
github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest v14.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
|
||||
github.com/Azure/go-autorest/autorest v0.10.2 h1:NuSF3gXetiHyUbVdneJMEVyPUYAe5wh+aN08JYAf1tI=
|
||||
github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.1 h1:xjPqigMQe2+0DAJ5A6MLUPp5D2r2Io8qHCuCMMI/yJU=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.1/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
@@ -90,10 +76,8 @@ github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocm
|
||||
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
|
||||
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
@@ -125,7 +109,6 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrU
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE=
|
||||
github.com/alecthomas/participle v0.2.1 h1:4AVLj1viSGa4LG5HDXKXrm5xRx19SB/rS/skPQB1Grw=
|
||||
github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@@ -144,7 +127,6 @@ github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQh
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
@@ -160,11 +142,9 @@ github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
||||
github.com/aws/aws-sdk-go v1.29.11/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
|
||||
github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2 h1:M+TYzBcNIRyzPRg66ndEqUMd7oWDmhvdQmaPC6EZNwM=
|
||||
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M=
|
||||
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
|
||||
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
@@ -182,12 +162,11 @@ github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMS
|
||||
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98=
|
||||
github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
|
||||
github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo=
|
||||
github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -199,10 +178,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=
|
||||
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
|
||||
github.com/colinmarc/hdfs/v2 v2.1.1 h1:x0hw/m+o3UE20Scso/KCkvYNc9Di39TBlCfGMkJ1/a0=
|
||||
github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c=
|
||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coredns/coredns v1.4.0 h1:RubBkYmkByUqZWWkjRHvNLnUHgkRVqAWgSMmRFvpE1A=
|
||||
github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
@@ -211,7 +188,6 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -231,29 +207,26 @@ github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4=
|
||||
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/djherbis/atime v1.0.0 h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=
|
||||
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xiSOIjXD4sLI55Y/gfpa8/558=
|
||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE=
|
||||
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/dswarbrick/smart v0.0.0-20190505152634-909a45200d6d h1:QK8IYltsNy+5QZcDFbVkyInrs98/wHy1tfUTGG91sps=
|
||||
github.com/dswarbrick/smart v0.0.0-20190505152634-909a45200d6d/go.mod h1:apXo4PA/BgBPrt66j0N45O2stlBTRowdip2igwcUWVc=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -278,7 +251,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
@@ -289,12 +261,10 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.4.1 h1:Wv2VwvNn73pAdFIVUQRXYDFp31lXKbqblIXo/Q5GPSg=
|
||||
github.com/frankban/quicktest v1.4.1/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
@@ -306,7 +276,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-ini/ini v1.57.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-ldap/ldap v3.0.2+incompatible h1:kD5HQcAzlQ7yrhfn+h+MSABeAy/jAJhvIJ/QDllP44g=
|
||||
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
|
||||
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
@@ -435,14 +404,11 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -459,7 +425,6 @@ github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
@@ -468,7 +433,6 @@ github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
@@ -496,19 +460,15 @@ github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunE
|
||||
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-containerregistry v0.1.2 h1:YjFNKqxzWUVZND8d4ItF9wuYlE75WQfECE7yKX/Nu3o=
|
||||
github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
@@ -534,33 +494,25 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
|
||||
github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
|
||||
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
|
||||
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.2.2 h1:DcFegQ7+ECdmkJMfVwWlC+89I4esJ7p8nkGt9ainGDk=
|
||||
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
|
||||
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/goreleaser/goreleaser v0.136.0/go.mod h1:wiKrPUeSNh6Wu8nUHxZydSOVQ/OZvOaO7DTtFqie904=
|
||||
github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w=
|
||||
github.com/goreleaser/nfpm v1.3.0/go.mod h1:w0p7Kc9TAUgWMyrub63ex3M2Mgw88M4GZXoTq5UCb40=
|
||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.5-0.20200711200521-98cb6bf42e08 h1:kPna6oIGlRXWmg/jkKfxbpvsl+0DHYnw1qQwN+6+gyA=
|
||||
github.com/gorilla/mux v1.7.5-0.20200711200521-98cb6bf42e08/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk=
|
||||
github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
@@ -584,11 +536,9 @@ github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.9.1 h1:9PZfAcVEvez4yhLH2TBU64/h/z4xlFI80cWXRrxuKuM=
|
||||
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
@@ -601,16 +551,12 @@ github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uP
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
@@ -621,11 +567,9 @@ github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
@@ -634,19 +578,15 @@ github.com/hashicorp/raft v1.1.2 h1:oxEL5DDeurYxLd3UbcY/hccgSPhLLpiBZ1YxtWEq59c=
|
||||
github.com/hashicorp/raft v1.1.2/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
|
||||
github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU=
|
||||
github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
|
||||
github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8=
|
||||
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
|
||||
@@ -673,7 +613,6 @@ github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBv
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@@ -696,40 +635,30 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.2 h1:1xAgYebNnsb9LKCdLOvFWtAxGU/33mjJtyOVbmUa0Us=
|
||||
github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4=
|
||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=
|
||||
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/klauspost/readahead v1.3.1 h1:QqXNYvm+VvqYcbrRT4LojUciM0XrznFRIDrbHiJtu/0=
|
||||
github.com/klauspost/readahead v1.3.1/go.mod h1:AH9juHzNH7xqdqFHrMRSHeH2Ps+vFf+kblDqzPFiLJg=
|
||||
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
|
||||
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
@@ -752,9 +681,7 @@ github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
@@ -765,13 +692,12 @@ github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
@@ -783,7 +709,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI=
|
||||
github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/cli v1.22.0 h1:VTQm7lmXm3quxO917X3p+el1l0Ca5X3S4PM2ruUYO68=
|
||||
github.com/minio/cli v1.22.0/go.mod h1:bYxnK0uS629N3Bq+AOZZ+6lwF77Sodk4+UL9vNuXhOY=
|
||||
@@ -791,32 +716,27 @@ github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2
|
||||
github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc=
|
||||
github.com/minio/kes v0.11.0 h1:8ma6OCVSxKT50b1uYXLJro3m7PmZtCLxBaTddQexI5k=
|
||||
github.com/minio/kes v0.11.0/go.mod h1:mTF1Bv8YVEtQqF/B7Felp4tLee44Pp+dgI0rhCvgNg8=
|
||||
github.com/minio/mc v0.0.0-20201001165056-7f2df96e4821 h1:+09Ta2rY29df6U4bfSC85t7jxlNuYpUfl7lIVgTiDEA=
|
||||
github.com/minio/mc v0.0.0-20201001165056-7f2df96e4821/go.mod h1:+OeGPfw7qpvO1x2Td65ejwAuFT0Cxzx0GFTJSDlPMZQ=
|
||||
github.com/minio/mc v0.0.0-20201119214335-d4f9ea859d6c h1:/wGiTfC8pFOC2JzwE+XrPeH31LqFR/Dam4Lx1zX3Wag=
|
||||
github.com/minio/mc v0.0.0-20201119214335-d4f9ea859d6c/go.mod h1:B738ZPTRQiyp3uJ3p2W2mqk8Yp1puYASKY7GIhYyHP8=
|
||||
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
github.com/minio/minio v0.0.0-20200723003940-b9be841fd222 h1:+XFGpEsqmA033nDX8LtjyPZy01Shivf6E2OL67WoGiE=
|
||||
github.com/minio/minio v0.0.0-20200723003940-b9be841fd222/go.mod h1:Eu2KC2p+vW03rnYY/6R/D+QduPB7/j4kBaVA/EDLjWM=
|
||||
github.com/minio/minio v0.0.0-20200927172404-27d9bd04e544 h1:G6M9uXdFShowoLG3rMkdCtHsx37ZYB1vc+7bu22r85I=
|
||||
github.com/minio/minio v0.0.0-20200927172404-27d9bd04e544/go.mod h1:5uolst3SWpgvDNF+KJwfViU+j9WH7dB5i2YCi0nMNVo=
|
||||
github.com/minio/minio v0.0.0-20201102034248-d8e07f2c41c8 h1:yCDFjUBUoE1uNr8dEqjHuwySdAtOyvVONchEVrPPOGQ=
|
||||
github.com/minio/minio v0.0.0-20201102034248-d8e07f2c41c8/go.mod h1:640kMkCwiyOX8dheptHYModdUw4HrnUFHKw3McqUXD8=
|
||||
github.com/minio/minio-go/v7 v7.0.1/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns=
|
||||
github.com/minio/minio-go/v7 v7.0.2 h1:P/7wFd4KrRBHVo7AKdcqO+9ReoS+XpMjfRFoE5quH0E=
|
||||
github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns=
|
||||
github.com/minio/minio-go/v7 v7.0.5-0.20200811211821-14ed05478889/go.mod h1:CSt2ETZNs+bIIhWTse0mcZKZWMGrFU7Er7RR0TmkDYk=
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20200923173112-bc846cb9b089 h1:9DDs/Gc3fNHOQxQmwIFWs7YDLMTBh59r2XQ6RqEUA1I=
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20200923173112-bc846cb9b089/go.mod h1:CSt2ETZNs+bIIhWTse0mcZKZWMGrFU7Er7RR0TmkDYk=
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20200929220449-755b5633803a/go.mod h1:CSt2ETZNs+bIIhWTse0mcZKZWMGrFU7Er7RR0TmkDYk=
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20201119032702-6914cb678dde h1:Ag2kFFpCxct9ayux92WQUlT938y7+IbibERYOraT8dM=
|
||||
github.com/minio/minio-go/v7 v7.0.6-0.20201119032702-6914cb678dde/go.mod h1:HcIuq+11d/3MfavIPZiswSzfQ1VJ2Lwxp/XLtW46IWQ=
|
||||
github.com/minio/operator v0.0.0-20201022162018-527e5c32132b h1:ggfD6V3nodTzhHJHCYIT1F897gscrz+hHsan0a2Wtqw=
|
||||
github.com/minio/operator v0.0.0-20201022162018-527e5c32132b/go.mod h1:At+++4/6W5BEXK11tN5DKIvkJKhYBZybbb5zmxb0LQI=
|
||||
github.com/minio/selfupdate v0.3.1 h1:BWEFSNnrZVMUWXbXIgLDNDjbejkmpAmZvy/nCz1HlEs=
|
||||
github.com/minio/selfupdate v0.3.1/go.mod h1:b8ThJzzH7u2MkF6PcIra7KaXO9Khf6alWPvMSyTDCFM=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/simdjson-go v0.1.5-0.20200303142138-b17fe061ea37 h1:pDeao6M5AEd8hwTtGmE0pVKomlL56JFRa5SiXDZAuJE=
|
||||
github.com/minio/simdjson-go v0.1.5-0.20200303142138-b17fe061ea37/go.mod h1:oKURrZZEBtqObgJrSjN1Ln2n9MJj2icuBTkeJzZnvSI=
|
||||
github.com/minio/simdjson-go v0.1.5 h1:6T5mHh7r3kUvgwhmFWQAjoPV5Yt5oD/VPjAI9ViH1kM=
|
||||
github.com/minio/simdjson-go v0.1.5/go.mod h1:oKURrZZEBtqObgJrSjN1Ln2n9MJj2icuBTkeJzZnvSI=
|
||||
github.com/minio/sio v0.2.0 h1:NCRCFLx0r5pRbXf65LVNjxbCGZgNQvNFQkgX3XF4BoA=
|
||||
github.com/minio/sio v0.2.0/go.mod h1:nKM5GIWSrqbOZp0uhyj6M1iA0X6xQzSGtYSaTKSCut0=
|
||||
github.com/minio/sio v0.2.1/go.mod h1:8b0yPp2avGThviy/+OCJBI6OMpvxoUuiLvE6F1lebhw=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@@ -829,13 +749,11 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mmcloughlin/avo v0.0.0-20200523190732-4439b6b2c061 h1:UCU8+cLbbvyxi0sQ9fSeoEhZgvrrD9HKMtX6Gmc1vk8=
|
||||
github.com/mmcloughlin/avo v0.0.0-20200523190732-4439b6b2c061/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
|
||||
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -864,7 +782,6 @@ github.com/nats-io/nats-streaming-server v0.18.0 h1:+RDozeN9scwCm0Wc2fYlvGcP144h
|
||||
github.com/nats-io/nats-streaming-server v0.18.0/go.mod h1:Y9Aiif2oANuoKazQrs4wXtF3jqt6p97ODQg68lR5TnY=
|
||||
github.com/nats-io/nats.go v1.10.0 h1:L8qnKaofSfNFbXg0C5F71LdjPRnmQwSsA4ukmkt1TvY=
|
||||
github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
|
||||
github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA=
|
||||
github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
|
||||
@@ -887,13 +804,11 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
@@ -913,14 +828,13 @@ github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUr
|
||||
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
|
||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/philhofer/fwd v1.1.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.4.0+incompatible h1:06usnXXDNcPvCHDkmPpkidf4jTc52UKld7UPfqKatY4=
|
||||
github.com/pierrec/lz4 v2.4.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -943,7 +857,6 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
|
||||
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@@ -972,7 +885,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
@@ -983,13 +895,11 @@ github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0f
|
||||
github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/secure-io/sio-go v0.3.0 h1:QKGb6rGJeiExac9wSWxnWPYo8O8OFN7lxXQvHshX6vo=
|
||||
github.com/secure-io/sio-go v0.3.0/go.mod h1:D3KmXgKETffyYxBdFRN+Hpd2WzhzqS0EQwT3XWsAcBU=
|
||||
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
|
||||
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
|
||||
@@ -1007,18 +917,15 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
|
||||
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
@@ -1029,7 +936,6 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
||||
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
|
||||
github.com/sourcegraph/go-diff v0.5.3/go.mod h1:v9JDtjCE4HHHCZGId75rg8gkKKa98RVjBcBGsVmMmak=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
@@ -1053,7 +959,6 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRN
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
@@ -1067,23 +972,19 @@ github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0
|
||||
github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM=
|
||||
github.com/tetafro/godot v0.3.7/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0=
|
||||
github.com/tetafro/godot v0.4.2/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0=
|
||||
github.com/tidwall/gjson v1.3.5 h1:2oW9FBNu8qt9jy5URgrzsVx/T/KSn3qn/smJQ0crlDQ=
|
||||
github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
||||
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
||||
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/sjson v1.0.4 h1:UcdIRXff12Lpnu3OLtZvnc03g4vH2suXDXhBwBqmzYg=
|
||||
github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y=
|
||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||
github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||
github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ=
|
||||
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.3/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
|
||||
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
|
||||
github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao=
|
||||
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
@@ -1108,11 +1009,8 @@ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6Jc
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c=
|
||||
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
|
||||
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
|
||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
|
||||
github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
|
||||
github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
|
||||
github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
|
||||
@@ -1139,16 +1037,13 @@ go.etcd.io/etcd/v3 v3.3.0-rc.0.0.20200707003333-58bb8ae09f8e h1:HZQLoe71Q24wVyDr
|
||||
go.etcd.io/etcd/v3 v3.3.0-rc.0.0.20200707003333-58bb8ae09f8e/go.mod h1:UENlOa05tkNvLx9VnNziSerG4Ro74upGK6Apd4v6M/Y=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.3.0 h1:ew6uUIeJOo+qdUUv7LxFCUhtWmVv7ZV/Xuy4FAUsw2E=
|
||||
go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
|
||||
go.mongodb.org/mongo-driver v1.3.4 h1:zs/dKNwX0gYUtzwrN9lLiR15hCO0nDwQj5xXx+vjCdE=
|
||||
go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
|
||||
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
|
||||
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
@@ -1186,15 +1081,14 @@ golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1215,7 +1109,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
@@ -1227,7 +1120,6 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -1270,19 +1162,17 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/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-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/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-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
@@ -1292,12 +1182,9 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1348,28 +1235,26 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200915084602-288bc346aa39 h1:356XA7ITklAU2//sYkjFeco+dH1bCRD8XCJ9FIEsvo4=
|
||||
golang.org/x/sys v0.0.0-20200915084602-288bc346aa39/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb h1:HS9IzC4UFbpMBLQUDSQcU+ViVT1vdFCQVjdPVpTlZrs=
|
||||
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/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-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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/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=
|
||||
@@ -1441,21 +1326,16 @@ golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWc
|
||||
golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
|
||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/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-20200502202811-ed308ab3e770/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-20200804011535-6c149bb5ef0d h1:szSOL78iTCl0LF1AMjhSWJj8tIM0KixlUUnBtYXsmd8=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200814172026-c4923e618c08 h1:sfBQLM20fzeXhOixVQirwEbuW4PGStP773EXQpsBB6E=
|
||||
golang.org/x/tools v0.0.0-20200814172026-c4923e618c08/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f h1:7+Nz9MyPqt2qMCTvNiRy1G0zYfkB7UCa+ayT6uVvbyI=
|
||||
golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
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-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1463,7 +1343,6 @@ gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.5.0 h1:lj9SyhMzyoa38fgFF0oO2T6pjs5IzkLPKfVtxpyCRMM=
|
||||
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
|
||||
google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
|
||||
@@ -1479,12 +1358,10 @@ google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
|
||||
google.golang.org/api v0.20.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.25.0 h1:LodzhlzZEUfhXzNUMIfVlf9Gr6Ua5MMtoFWh7+f47qA=
|
||||
google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
@@ -1500,7 +1377,6 @@ google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRn
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
@@ -1526,12 +1402,10 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw=
|
||||
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
@@ -1543,26 +1417,19 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
@@ -1581,16 +1448,13 @@ gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=
|
||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.2.3 h1:hHMV/yKPwMnJhPuPx7pH2Uw/3Qyf+thJYlisUc44010=
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.3.0 h1:0709Jtq/6QXEuWRfAm260XqlpcwL1vxtO1tUE2qK8Z4=
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
|
||||
gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
|
||||
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
|
||||
gopkg.in/ldap.v3 v3.0.3 h1:YKRHW/2sIl05JsCtx/5ZuUueFuJyoj/6+DGXe3wp6ro=
|
||||
gopkg.in/ldap.v3 v3.0.3/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/olivere/elastic.v5 v5.0.80 h1:AKjfcq3ZIAAqO4m8h/vJ3GP6nY8n9ft5mgf54fEqC60=
|
||||
gopkg.in/olivere/elastic.v5 v5.0.80/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0=
|
||||
gopkg.in/olivere/elastic.v5 v5.0.86 h1:xFy6qRCGAmo5Wjx96srho9BitLhZl2fcnpuidPwduXM=
|
||||
gopkg.in/olivere/elastic.v5 v5.0.86/go.mod h1:M3WNlsF+WhYn7api4D87NIflwTV/c0iVs8cqfWhK+68=
|
||||
@@ -1608,7 +1472,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -1621,7 +1484,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.4.4
|
||||
image: minio/console:v0.4.6
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
args:
|
||||
- server
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.4.4
|
||||
image: minio/console:v0.4.6
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -33,14 +33,8 @@ import (
|
||||
// swagger:model createTenantResponse
|
||||
type CreateTenantResponse struct {
|
||||
|
||||
// access key
|
||||
AccessKey string `json:"access_key,omitempty"`
|
||||
|
||||
// console
|
||||
Console *CreateTenantResponseConsole `json:"console,omitempty"`
|
||||
|
||||
// secret key
|
||||
SecretKey string `json:"secret_key,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this create tenant response
|
||||
|
||||
@@ -177,7 +177,7 @@ func TestGetActionsStringFromPolicy(t *testing.T) {
|
||||
args: args{
|
||||
policy: &iampolicy.AdminDiagnostics,
|
||||
},
|
||||
want: 6,
|
||||
want: 7,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -18,7 +18,7 @@ package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
)
|
||||
@@ -27,13 +27,14 @@ var (
|
||||
errInvalidCredentials = errors.New("invalid Login")
|
||||
)
|
||||
|
||||
// GetConsoleCredentialsFromLDAP authenticates the user against MinIO when the LDAP integration is enabled
|
||||
// GetCredentialsFromLDAP authenticates the user against MinIO when the LDAP integration is enabled
|
||||
// if the authentication succeed *credentials.Login object is returned and we continue with the normal STSAssumeRole flow
|
||||
func GetConsoleCredentialsFromLDAP(endpoint, ldapUser, ldapPassword string) (*credentials.Credentials, error) {
|
||||
creds, err := credentials.NewLDAPIdentity(endpoint, ldapUser, ldapPassword)
|
||||
if err != nil {
|
||||
log.Println("LDAP authentication error: ", err)
|
||||
return nil, errInvalidCredentials
|
||||
}
|
||||
func GetCredentialsFromLDAP(client *http.Client, endpoint, ldapUser, ldapPassword string) (*credentials.Credentials, error) {
|
||||
creds := credentials.New(&credentials.LDAPIdentity{
|
||||
Client: client,
|
||||
STSEndpoint: endpoint,
|
||||
LDAPUsername: ldapUser,
|
||||
LDAPPassword: ldapPassword,
|
||||
})
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
certsx "github.com/minio/minio/pkg/certs"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
@@ -220,3 +221,13 @@ func GetTLSConfig() (x509Certs []*x509.Certificate, manager *certs.Manager, err
|
||||
}
|
||||
return x509Certs, manager, nil
|
||||
}
|
||||
|
||||
func GetAllCertificatesAndCAs() (*x509.CertPool, []*x509.Certificate, *certs.Manager) {
|
||||
// load all CAs from ~/.console/certs/CAs
|
||||
GlobalRootCAs, err := certsx.GetRootCAs(GlobalCertsCADir.Get())
|
||||
logger.FatalIf(err, "Failed to read root CAs (%v)", err)
|
||||
// load all certs from ~/.console/certs
|
||||
globalPublicCerts, globalTLSCertsManager, err := GetTLSConfig()
|
||||
logger.FatalIf(err, "Unable to load the TLS configuration")
|
||||
return GlobalRootCAs, globalPublicCerts, globalTLSCertsManager
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
30
portal-ui/package-lock.json
generated
30
portal-ui/package-lock.json
generated
@@ -1827,6 +1827,14 @@
|
||||
"csstype": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@types/react-copy-to-clipboard": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.3.0.tgz",
|
||||
"integrity": "sha512-iideNPRyroENqsOFh1i2Dv3zkviYS9r/9qD9Uh3Z9NNoAAqqa2x53i7iGndGNnJFIo20wIu7Hgh77tx1io8bgw==",
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "16.9.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.4.tgz",
|
||||
@@ -3943,6 +3951,14 @@
|
||||
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
|
||||
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
|
||||
},
|
||||
"copy-to-clipboard": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz",
|
||||
"integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==",
|
||||
"requires": {
|
||||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.6.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
|
||||
@@ -13932,6 +13948,15 @@
|
||||
"resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.1.0.tgz",
|
||||
"integrity": "sha512-Rel0QbPnCTjHxgZYt6TkGw4icSZXNyONHb72a+1wWA+PlYJIvzFAv4pZlDPG0rpKpKmy4kSUlkoWgneH7w3A0g=="
|
||||
},
|
||||
"react-copy-to-clipboard": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz",
|
||||
"integrity": "sha512-/2t5mLMMPuN5GmdXo6TebFa8IoFxZ+KTDDqYhcDm0PhkgEzSxVvIX26G20s1EB02A4h2UZgwtfymZ3lGJm0OLg==",
|
||||
"requires": {
|
||||
"copy-to-clipboard": "^3",
|
||||
"prop-types": "^15.5.8"
|
||||
}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "10.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz",
|
||||
@@ -16325,6 +16350,11 @@
|
||||
"repeat-string": "^1.6.1"
|
||||
}
|
||||
},
|
||||
"toggle-selection": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
|
||||
"integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI="
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/node": "12.12.8",
|
||||
"@types/react": "16.9.11",
|
||||
"@types/react-copy-to-clipboard": "^4.3.0",
|
||||
"@types/react-dom": "16.9.4",
|
||||
"@types/react-redux": "^7.1.5",
|
||||
"@types/react-router": "^5.1.3",
|
||||
"@types/react-router-dom": "^5.1.2",
|
||||
"@types/react-virtualized": "^9.21.10",
|
||||
"@types/recharts": "^1.8.9",
|
||||
"@types/superagent": "^4.1.4",
|
||||
"@types/webpack-env": "^1.14.1",
|
||||
@@ -34,12 +36,15 @@
|
||||
"react-async-hook": "^3.6.1",
|
||||
"react-chartjs-2": "^2.9.0",
|
||||
"react-codemirror2": "^7.1.0",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-hot-loader": "^4.13.0",
|
||||
"react-moment": "^0.9.7",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "3.4.4",
|
||||
"react-virtualized": "^9.22.2",
|
||||
"react-window-infinite-loader": "^1.0.5",
|
||||
"recharts": "^1.8.5",
|
||||
"redux": "^4.0.4",
|
||||
"redux-thunk": "^2.3.0",
|
||||
|
||||
68
portal-ui/src/ProtectedRoutes.tsx
Normal file
68
portal-ui/src/ProtectedRoutes.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { AppState } from "./store";
|
||||
import { userLoggedIn } from "./actions";
|
||||
import api from "./common/api";
|
||||
import { clearSession } from "./common/utils";
|
||||
import { saveSessionResponse } from "./screens/Console/actions";
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
loggedIn: state.system.loggedIn,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
userLoggedIn,
|
||||
saveSessionResponse,
|
||||
});
|
||||
|
||||
interface ProtectedRouteProps {
|
||||
loggedIn: boolean;
|
||||
Component: any;
|
||||
userLoggedIn: typeof userLoggedIn;
|
||||
saveSessionResponse: typeof saveSessionResponse;
|
||||
}
|
||||
|
||||
const ProtectedRoute = ({
|
||||
Component,
|
||||
loggedIn,
|
||||
userLoggedIn,
|
||||
saveSessionResponse,
|
||||
}: ProtectedRouteProps) => {
|
||||
const [sessionLoading, setSessionLoading] = useState<boolean>(true);
|
||||
useEffect(() => {
|
||||
api
|
||||
.invoke("GET", `/api/v1/session`)
|
||||
.then((res) => {
|
||||
saveSessionResponse(res);
|
||||
userLoggedIn(true);
|
||||
setSessionLoading(false);
|
||||
})
|
||||
.catch(() => setSessionLoading(false));
|
||||
}, [saveSessionResponse]);
|
||||
|
||||
// if we still trying to retrieve user session render nothing
|
||||
if (sessionLoading) {
|
||||
return null;
|
||||
}
|
||||
// redirect user to the right page based on session status
|
||||
return loggedIn ? <Component /> : <Redirect to={{ pathname: "/login" }} />;
|
||||
};
|
||||
|
||||
export default connector(ProtectedRoute);
|
||||
@@ -15,65 +15,24 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import { Redirect, Route, Router, Switch } from "react-router-dom";
|
||||
import { Route, Router, Switch } from "react-router-dom";
|
||||
import history from "./history";
|
||||
import Login from "./screens/LoginPage/LoginPage";
|
||||
import Console from "./screens/Console/Console";
|
||||
import storage from "local-storage-fallback";
|
||||
import { connect } from "react-redux";
|
||||
import { AppState } from "./store";
|
||||
import { userLoggedIn } from "./actions";
|
||||
import LoginCallback from "./screens/LoginPage/LoginCallback";
|
||||
import { hot } from "react-hot-loader/root";
|
||||
import ProtectedRoute from "./ProtectedRoutes";
|
||||
|
||||
interface ProtectedRouteProps {
|
||||
loggedIn: boolean;
|
||||
component: any;
|
||||
}
|
||||
|
||||
export class ProtectedRoute extends React.Component<ProtectedRouteProps> {
|
||||
render() {
|
||||
const Component = this.props.component;
|
||||
return this.props.loggedIn ? (
|
||||
<Component />
|
||||
) : (
|
||||
<Redirect to={{ pathname: "/login" }} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const isLoggedIn = () => {
|
||||
const Routes = () => {
|
||||
return (
|
||||
storage.getItem("token") !== undefined &&
|
||||
storage.getItem("token") !== null &&
|
||||
storage.getItem("token") !== ""
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<Route exact path="/oauth_callback" component={LoginCallback} />
|
||||
<Route exact path="/login" component={Login} />
|
||||
<ProtectedRoute Component={Console} />
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
loggedIn: state.system.loggedIn,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, { userLoggedIn });
|
||||
|
||||
interface RoutesProps {
|
||||
loggedIn: boolean;
|
||||
userLoggedIn: typeof userLoggedIn;
|
||||
}
|
||||
|
||||
class Routes extends React.Component<RoutesProps> {
|
||||
render() {
|
||||
const loggedIn = isLoggedIn();
|
||||
return (
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<Route exact path="/oauth_callback" component={LoginCallback} />
|
||||
<Route exact path="/login" component={Login} />
|
||||
<ProtectedRoute component={Console} loggedIn={loggedIn} />
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default hot(connector(Routes));
|
||||
export default hot(Routes);
|
||||
|
||||
@@ -14,16 +14,13 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import storage from "local-storage-fallback";
|
||||
import request from "superagent";
|
||||
import get from "lodash/get";
|
||||
import { clearSession } from "../utils";
|
||||
|
||||
export class API {
|
||||
invoke(method: string, url: string, data?: object) {
|
||||
const token: string = storage.getItem("token")!;
|
||||
return request(method, url)
|
||||
.set("Authorization", `Bearer ${token}`)
|
||||
.send(data)
|
||||
.then((res) => res.body)
|
||||
.catch((err) => {
|
||||
|
||||
@@ -62,17 +62,12 @@ export const deleteCookie = (name: string) => {
|
||||
document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
|
||||
};
|
||||
|
||||
export const setSession = (token: string) => {
|
||||
setCookie("token", token);
|
||||
storage.setItem("token", token);
|
||||
};
|
||||
|
||||
export const clearSession = () => {
|
||||
storage.removeItem("token");
|
||||
deleteCookie("token");
|
||||
};
|
||||
|
||||
// timeFromdate gets time string from date input
|
||||
// timeFromDate gets time string from date input
|
||||
export const timeFromDate = (d: Date) => {
|
||||
let h = d.getHours() < 10 ? `0${d.getHours()}` : `${d.getHours()}`;
|
||||
let m = d.getMinutes() < 10 ? `0${d.getMinutes()}` : `${d.getMinutes()}`;
|
||||
|
||||
39
portal-ui/src/icons/CopyIcon.tsx
Normal file
39
portal-ui/src/icons/CopyIcon.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import { SvgIcon } from "@material-ui/core";
|
||||
class CopyIcon extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<SvgIcon>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>ic_h_copy-new_sl</title>
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path
|
||||
className="cls-1"
|
||||
d="M0,0V16H16V0ZM11.886,9.048H9.048v2.838h-2.1V9.048H4.114v-2.1H6.952V4.114h2.1V6.952h2.838Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CopyIcon;
|
||||
@@ -15,21 +15,20 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import {SvgIcon} from "@material-ui/core";
|
||||
import { SvgIcon } from "@material-ui/core";
|
||||
class DeleteIcon extends React.Component {
|
||||
render() {
|
||||
return (<SvgIcon>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>ic_h_delete</title>
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path className="cls-1"
|
||||
d="M0,8H0a8,8,0,0,0,8,8H8a8,8,0,0,0,8-8h0A8,8,0,0,0,8,0H8A8,8,0,0,0,0,8Zm10.007,3.489L8,9.482,5.993,11.489,4.511,10.007,6.518,8,4.511,5.993,5.993,4.511,8,6.518l2.007-2.007,1.482,1.482L9.482,8l2.007,2.007Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</SvgIcon>)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<SvgIcon>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10.402 13">
|
||||
<path
|
||||
d="M6.761 1V0H3.64v1H.004v1h10.4V1zM.004 2.998l1.672 10h7.052l1.673-10zm3.412 8.243l-.552-6.478h.653l.553 6.472zm3.569 0h-.653l.551-6.472h.654z"
|
||||
className="a"
|
||||
></path>
|
||||
</svg>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DeleteIcon;
|
||||
|
||||
33
portal-ui/src/icons/DownloadIcon.tsx
Normal file
33
portal-ui/src/icons/DownloadIcon.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import SvgIcon from "@material-ui/core/SvgIcon";
|
||||
|
||||
class DownloadIcon extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<SvgIcon>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 12.996">
|
||||
<path d="M11.05 9.096v1.95h-9.1v-1.95H0v3.9h13v-3.9z"></path>
|
||||
<path d="M6.5 9.75L9 6.672H7.475V0h-1.95v6.672H4z"></path>
|
||||
</svg>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DownloadIcon;
|
||||
39
portal-ui/src/icons/ShareIcon.tsx
Normal file
39
portal-ui/src/icons/ShareIcon.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from "react";
|
||||
import SvgIcon from "@material-ui/core/SvgIcon";
|
||||
|
||||
class ShareIcon extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<SvgIcon>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 13">
|
||||
<path
|
||||
d="M11.05 8.617v2.429h-9.1v-9.1h2.429v-1.95H0v13h13V8.617z"
|
||||
className="a"
|
||||
></path>
|
||||
<path
|
||||
d="M3.854 9.256h1.95a4.945 4.945 0 013.6-4.74v1.3l.6-.487 2.474-2.012L9.4.817v1.7a6.9 6.9 0 00-5.546 6.739z"
|
||||
className="a"
|
||||
></path>
|
||||
</svg>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ShareIcon;
|
||||
@@ -15,6 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export { default as PermissionIcon } from "./PermissionIcon";
|
||||
export { default as CopyIcon } from "./CopyIcon";
|
||||
export { default as CreateIcon } from "./CreateIcon";
|
||||
export { default as DeleteIcon } from "./DeleteIcon";
|
||||
export { default as ServiceAccountIcon } from "./ServiceAccountIcon";
|
||||
|
||||
@@ -21,6 +21,7 @@ import Routes from "./Routes";
|
||||
import configureStore from "./store";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
import { ThemeProvider, withStyles } from "@material-ui/core/styles";
|
||||
import "react-virtualized/styles.css";
|
||||
|
||||
import "./index.css";
|
||||
import theme from "./theme/main";
|
||||
|
||||
@@ -221,7 +221,7 @@ const AddBucket = ({
|
||||
addBucketVersioned(event.target.checked);
|
||||
}}
|
||||
label={"Versioning"}
|
||||
indicatorLabel={"On"}
|
||||
indicatorLabels={["On", "Off"]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
@@ -234,7 +234,7 @@ const AddBucket = ({
|
||||
addBucketQuota(event.target.checked);
|
||||
}}
|
||||
label={"Enable Bucket Quota"}
|
||||
indicatorLabel={"On"}
|
||||
indicatorLabels={["On", "Off"]}
|
||||
/>
|
||||
</Grid>
|
||||
{enableQuota && (
|
||||
|
||||
@@ -197,7 +197,7 @@ const ListBuckets = ({
|
||||
}
|
||||
});
|
||||
|
||||
const showInPage = filteredRecords.slice(offset, offset + rowsPerPage);
|
||||
const showInPage = filteredRecords;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
@@ -266,26 +266,14 @@ const ListBuckets = ({
|
||||
label: "Size",
|
||||
elementKey: "size",
|
||||
renderFunction: niceBytes,
|
||||
width: 60,
|
||||
contentTextAlign: "right",
|
||||
},
|
||||
]}
|
||||
isLoading={loading}
|
||||
records={showInPage}
|
||||
entityName="Buckets"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: filteredRecords.length,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import React, { useState } from "react";
|
||||
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
|
||||
import { Button, Grid, LinearProgress } from "@material-ui/core";
|
||||
import { Button, Grid } from "@material-ui/core";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
@@ -42,17 +42,22 @@ import Snackbar from "@material-ui/core/Snackbar";
|
||||
import BrowserBreadcrumbs from "../../../../ObjectBrowser/BrowserBreadcrumbs";
|
||||
import get from "lodash/get";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { addRoute, setAllRoutes } from "../../../../ObjectBrowser/actions";
|
||||
import {
|
||||
addRoute,
|
||||
setAllRoutes,
|
||||
setLastAsFile,
|
||||
} from "../../../../ObjectBrowser/actions";
|
||||
import { connect } from "react-redux";
|
||||
import { ObjectBrowserState, Route } from "../../../../ObjectBrowser/reducers";
|
||||
import CreateFolderModal from "./CreateFolderModal";
|
||||
import { create } from "domain";
|
||||
import UploadFile from "../../../../../../icons/UploadFile";
|
||||
import { download } from "../utils";
|
||||
|
||||
const commonIcon = {
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPosition: "center center",
|
||||
width: 16,
|
||||
minWidth: 16,
|
||||
height: 40,
|
||||
marginRight: 10,
|
||||
};
|
||||
@@ -91,6 +96,11 @@ const styles = (theme: Theme) =>
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
},
|
||||
fileNameText: {
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
},
|
||||
iconFolder: {
|
||||
backgroundImage: "url(/images/ob_folder_clear.svg)",
|
||||
...commonIcon,
|
||||
@@ -104,11 +114,14 @@ const styles = (theme: Theme) =>
|
||||
marginLeft: 10,
|
||||
},
|
||||
},
|
||||
browsePaper: {
|
||||
height: "calc(100vh - 280px)",
|
||||
},
|
||||
"@global": {
|
||||
".rowElementRaw:hover .iconFileElm": {
|
||||
".rowLine:hover .iconFileElm": {
|
||||
backgroundImage: "url(/images/ob_file_filled.svg)",
|
||||
},
|
||||
".rowElementRaw:hover .iconFolderElm": {
|
||||
".rowLine:hover .iconFolderElm": {
|
||||
backgroundImage: "url(/images/ob_folder_filled.svg)",
|
||||
},
|
||||
},
|
||||
@@ -121,9 +134,10 @@ const styles = (theme: Theme) =>
|
||||
interface IListObjectsProps {
|
||||
classes: any;
|
||||
match: any;
|
||||
addRoute: (param1: string, param2: string) => any;
|
||||
addRoute: (param1: string, param2: string, param3: string) => any;
|
||||
setAllRoutes: (path: string) => any;
|
||||
routesList: Route[];
|
||||
setLastAsFile: () => any;
|
||||
}
|
||||
|
||||
interface ObjectBrowserReducer {
|
||||
@@ -136,6 +150,7 @@ const ListObjects = ({
|
||||
addRoute,
|
||||
setAllRoutes,
|
||||
routesList,
|
||||
setLastAsFile,
|
||||
}: IListObjectsProps) => {
|
||||
const [records, setRecords] = useState<BucketObject[]>([]);
|
||||
const [totalRecords, setTotalRecords] = useState<number>(0);
|
||||
@@ -162,13 +177,16 @@ const ListObjects = ({
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets/${bucketName}/objects${extraPath}`)
|
||||
.then((res: BucketObjectsList) => {
|
||||
setLoading(false);
|
||||
setSelectedBucket(bucketName);
|
||||
setRecords(res.objects || []);
|
||||
setTotalRecords(!res.objects ? 0 : res.total);
|
||||
setError("");
|
||||
// TODO:
|
||||
// if we get 0 results, and page > 0 , go down 1 page
|
||||
// In case no objects were retrieved, We check if item is a file
|
||||
if (!res.objects && extraPath !== "") {
|
||||
verifyIfIsFile();
|
||||
return;
|
||||
}
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
setLoading(false);
|
||||
@@ -183,6 +201,30 @@ const ListObjects = ({
|
||||
}
|
||||
}, [match, routesList, setAllRoutes]);
|
||||
|
||||
const verifyIfIsFile = () => {
|
||||
const bucketName = match.params["bucket"];
|
||||
const internalPaths = match.params[0];
|
||||
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/buckets/${bucketName}/objects?prefix=${internalPaths}`
|
||||
)
|
||||
.then((res: BucketObjectsList) => {
|
||||
//It is a file since it has elements in the object, setting file flag and waiting for component mount
|
||||
if (res.objects !== null) {
|
||||
setLastAsFile();
|
||||
} else {
|
||||
// It is a folder, we remove loader
|
||||
setLoading(false);
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
setLoading(false);
|
||||
setError(err);
|
||||
});
|
||||
};
|
||||
|
||||
const closeDeleteModalAndRefresh = (refresh: boolean) => {
|
||||
setDeleteOpen(false);
|
||||
|
||||
@@ -219,7 +261,6 @@ const ListObjects = ({
|
||||
let xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open("POST", uploadUrl, true);
|
||||
xhr.setRequestHeader("Authorization", `Bearer ${token}`);
|
||||
|
||||
xhr.withCredentials = false;
|
||||
xhr.onload = function (event) {
|
||||
@@ -257,38 +298,6 @@ const ListObjects = ({
|
||||
e.target.value = null;
|
||||
};
|
||||
|
||||
const download = (bucketName: string, objectName: string) => {
|
||||
const anchor = document.createElement("a");
|
||||
document.body.appendChild(anchor);
|
||||
const token: string = storage.getItem("token")!;
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open(
|
||||
"GET",
|
||||
`/api/v1/buckets/${bucketName}/objects/download?prefix=${objectName}`,
|
||||
true
|
||||
);
|
||||
xhr.setRequestHeader("Authorization", `Bearer ${token}`);
|
||||
xhr.responseType = "blob";
|
||||
|
||||
xhr.onload = function (e) {
|
||||
if (this.status === 200) {
|
||||
const blob = new Blob([this.response], {
|
||||
type: "octet/stream",
|
||||
});
|
||||
const blobUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
anchor.href = blobUrl;
|
||||
anchor.download = objectName;
|
||||
|
||||
anchor.click();
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
anchor.remove();
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
const displayParsedDate = (date: string) => {
|
||||
return <reactMoment.default>{date}</reactMoment.default>;
|
||||
};
|
||||
@@ -313,13 +322,16 @@ const ListObjects = ({
|
||||
const lastIndex = idElementClean.length - 1;
|
||||
const newPath = `${currentPath}/${idElementClean[lastIndex]}`;
|
||||
|
||||
addRoute(newPath, idElementClean[lastIndex]);
|
||||
addRoute(newPath, idElementClean[lastIndex], "path");
|
||||
return;
|
||||
}
|
||||
|
||||
// Element is a file. we open details here
|
||||
// TODO: Add details open function here.
|
||||
//console.log("object", idElementClean);
|
||||
const pathInArray = idElement.split("/");
|
||||
const fileName = pathInArray[pathInArray.length - 1];
|
||||
const newPath = `${currentPath}/${fileName}`;
|
||||
|
||||
addRoute(newPath, fileName, "file");
|
||||
return;
|
||||
};
|
||||
|
||||
const uploadObject = (e: any): void => {
|
||||
@@ -372,7 +384,9 @@ const ListObjects = ({
|
||||
return (
|
||||
<div className={classes.fileName}>
|
||||
<div className={icon} />
|
||||
<span>{splitItem[splitItem.length - 1]}</span>
|
||||
<span className={classes.fileNameText}>
|
||||
{splitItem[splitItem.length - 1]}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -486,12 +500,15 @@ const ListObjects = ({
|
||||
label: "Size",
|
||||
elementKey: "size",
|
||||
renderFunction: niceBytes,
|
||||
width: 60,
|
||||
contentTextAlign: "right",
|
||||
},
|
||||
]}
|
||||
isLoading={loading}
|
||||
entityName="Objects"
|
||||
idField="name"
|
||||
records={filteredRecords}
|
||||
customPaperHeight={classes.browsePaper}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -507,6 +524,7 @@ const mapStateToProps = ({ objectBrowser }: ObjectBrowserReducer) => ({
|
||||
const mapDispatchToProps = {
|
||||
addRoute,
|
||||
setAllRoutes,
|
||||
setLastAsFile,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import ListObjects from "./ListObjects";
|
||||
import ObjectDetails from "../ObjectDetails/ObjectDetails";
|
||||
import get from "lodash/get";
|
||||
import { setAllRoutes } from "../../../../ObjectBrowser/actions";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { ObjectBrowserState, Route } from "../../../../ObjectBrowser/reducers";
|
||||
|
||||
interface ObjectBrowserReducer {
|
||||
objectBrowser: ObjectBrowserState;
|
||||
}
|
||||
|
||||
interface ObjectRoutingProps {
|
||||
routesList: Route[];
|
||||
setAllRoutes: (path: string) => any;
|
||||
match: any;
|
||||
}
|
||||
|
||||
const ObjectRouting = ({
|
||||
routesList,
|
||||
match,
|
||||
setAllRoutes,
|
||||
}: ObjectRoutingProps) => {
|
||||
const currentItem = routesList[routesList.length - 1];
|
||||
|
||||
useEffect(() => {
|
||||
const url = get(match, "url", "/object-browser");
|
||||
|
||||
if (url !== routesList[routesList.length - 1].route) {
|
||||
setAllRoutes(url);
|
||||
}
|
||||
}, [match, routesList, setAllRoutes]);
|
||||
|
||||
return currentItem.type === "path" ? (
|
||||
<ListObjects />
|
||||
) : (
|
||||
<ObjectDetails routesList={routesList} />
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ objectBrowser }: ObjectBrowserReducer) => ({
|
||||
routesList: get(objectBrowser, "routesList", []),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setAllRoutes,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
export default withRouter(connector(ObjectRouting));
|
||||
@@ -0,0 +1,138 @@
|
||||
import React, { useState } from "react";
|
||||
import { Button, Grid } from "@material-ui/core";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import api from "../../../../../../common/api";
|
||||
|
||||
interface ITagModal {
|
||||
modalOpen: boolean;
|
||||
currentTags: any;
|
||||
bucketName: string;
|
||||
versionId: string;
|
||||
onCloseAndUpdate: (refresh: boolean) => void;
|
||||
selectedObject: string;
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
},
|
||||
pathLabel: {
|
||||
marginTop: 0,
|
||||
marginBottom: 32,
|
||||
},
|
||||
...modalBasic,
|
||||
});
|
||||
|
||||
const AddTagModal = ({
|
||||
modalOpen,
|
||||
currentTags,
|
||||
selectedObject,
|
||||
onCloseAndUpdate,
|
||||
bucketName,
|
||||
versionId,
|
||||
classes,
|
||||
}: ITagModal) => {
|
||||
const [newKey, setNewKey] = useState<string>("");
|
||||
const [newLabel, setNewLabel] = useState<string>("");
|
||||
const [error, setError] = useState<string>("");
|
||||
const [isSending, setIsSending] = useState<boolean>(false);
|
||||
|
||||
const resetForm = () => {
|
||||
setNewLabel("");
|
||||
setNewKey("");
|
||||
};
|
||||
|
||||
const addTagProcess = () => {
|
||||
setIsSending(true);
|
||||
const newTag: any = {};
|
||||
|
||||
newTag[newKey] = newLabel;
|
||||
const newTagList = { ...currentTags, ...newTag };
|
||||
|
||||
api
|
||||
.invoke(
|
||||
"PUT",
|
||||
`/api/v1/buckets/${bucketName}/objects/tags?prefix=${selectedObject}&version_id=${versionId}`,
|
||||
{ tags: newTagList }
|
||||
)
|
||||
.then((res: any) => {
|
||||
setIsSending(false);
|
||||
onCloseAndUpdate(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
setError(error);
|
||||
setIsSending(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ModalWrapper
|
||||
modalOpen={modalOpen}
|
||||
title="Add New Tag"
|
||||
onClose={() => {
|
||||
onCloseAndUpdate(false);
|
||||
}}
|
||||
>
|
||||
<Grid container>
|
||||
<h3 className={classes.pathLabel}>
|
||||
Selected Object: {selectedObject}
|
||||
</h3>
|
||||
{error !== "" && <span>{error}</span>}
|
||||
<Grid item xs={12}>
|
||||
<InputBoxWrapper
|
||||
value={newKey}
|
||||
label={"New Tag Key"}
|
||||
id={"newTagKey"}
|
||||
name={"newTagKey"}
|
||||
placeholder={"Enter New Tag Key"}
|
||||
onChange={(e) => {
|
||||
setNewKey(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<InputBoxWrapper
|
||||
value={newLabel}
|
||||
label={"New Tag Label"}
|
||||
id={"newTagLabel"}
|
||||
name={"newTagLabel"}
|
||||
placeholder={"Enter New Tag Label"}
|
||||
onChange={(e) => {
|
||||
setNewLabel(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.buttonContainer}>
|
||||
<button
|
||||
type="button"
|
||||
color="primary"
|
||||
className={classes.clearButton}
|
||||
onClick={resetForm}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={
|
||||
newLabel.trim() === "" || newKey.trim() === "" || isSending
|
||||
}
|
||||
onClick={addTagProcess}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ModalWrapper>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(AddTagModal);
|
||||
@@ -0,0 +1,125 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Grid,
|
||||
LinearProgress,
|
||||
} from "@material-ui/core";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import api from "../../../../../../common/api";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
|
||||
interface IDeleteTagModal {
|
||||
deleteOpen: boolean;
|
||||
currentTags: any;
|
||||
bucketName: string;
|
||||
versionId: string;
|
||||
selectedTag: [string, string];
|
||||
onCloseAndUpdate: (refresh: boolean) => void;
|
||||
selectedObject: string;
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
},
|
||||
pathLabel: {
|
||||
marginTop: 0,
|
||||
marginBottom: 32,
|
||||
},
|
||||
...modalBasic,
|
||||
});
|
||||
|
||||
const DeleteTagModal = ({
|
||||
deleteOpen,
|
||||
currentTags,
|
||||
selectedObject,
|
||||
selectedTag,
|
||||
onCloseAndUpdate,
|
||||
bucketName,
|
||||
versionId,
|
||||
classes,
|
||||
}: IDeleteTagModal) => {
|
||||
const [deleteError, setDeleteError] = useState<string>("");
|
||||
const [deleteLoading, setDeleteSending] = useState<boolean>(false);
|
||||
const [tagKey, tagLabel] = selectedTag;
|
||||
|
||||
const removeTagProcess = () => {
|
||||
setDeleteSending(true);
|
||||
const cleanObject = { ...currentTags };
|
||||
delete cleanObject[tagKey];
|
||||
|
||||
api
|
||||
.invoke(
|
||||
"PUT",
|
||||
`/api/v1/buckets/${bucketName}/objects/tags?prefix=${selectedObject}&version_id=${versionId}`,
|
||||
{ tags: cleanObject }
|
||||
)
|
||||
.then((res: any) => {
|
||||
setDeleteSending(false);
|
||||
onCloseAndUpdate(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
setDeleteError(error);
|
||||
setDeleteSending(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={deleteOpen}
|
||||
onClose={() => {
|
||||
onCloseAndUpdate(false);
|
||||
}}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">Delete Tag</DialogTitle>
|
||||
<DialogContent>
|
||||
{deleteLoading && <LinearProgress />}
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Are you sure you want to delete the tag{" "}
|
||||
<b className={classes.wrapText}>
|
||||
{tagKey} : {tagLabel}
|
||||
</b>{" "}
|
||||
from {selectedObject}?
|
||||
{deleteError !== "" && (
|
||||
<React.Fragment>
|
||||
<br />
|
||||
<Typography
|
||||
component="p"
|
||||
variant="body1"
|
||||
className={classes.errorBlock}
|
||||
>
|
||||
{deleteError}
|
||||
</Typography>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onCloseAndUpdate(false);
|
||||
}}
|
||||
color="primary"
|
||||
disabled={deleteLoading}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={removeTagProcess} color="secondary" autoFocus>
|
||||
Delete
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(DeleteTagModal);
|
||||
@@ -0,0 +1,508 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import get from "lodash/get";
|
||||
import * as reactMoment from "react-moment";
|
||||
import clsx from "clsx";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Chip from "@material-ui/core/Chip";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||
import SearchIcon from "@material-ui/icons/Search";
|
||||
import AddIcon from "@material-ui/icons/Add";
|
||||
import CloseIcon from "@material-ui/icons/Close";
|
||||
import ShareFile from "./ShareFile";
|
||||
import {
|
||||
actionsTray,
|
||||
containerForHeader,
|
||||
searchField,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import history from "../../../../../../history";
|
||||
import { Route } from "../../../../ObjectBrowser/reducers";
|
||||
import { download } from "../utils";
|
||||
import api from "../../../../../../common/api";
|
||||
import PageHeader from "../../../../Common/PageHeader/PageHeader";
|
||||
import ShareIcon from "../../../../../../icons/ShareIcon";
|
||||
import DownloadIcon from "../../../../../../icons/DownloadIcon";
|
||||
import DeleteIcon from "../../../../../../icons/DeleteIcon";
|
||||
import TableWrapper from "../../../../Common/TableWrapper/TableWrapper";
|
||||
import PencilIcon from "../../../../Common/TableWrapper/TableActionIcons/PencilIcon";
|
||||
import SetRetention from "./SetRetention";
|
||||
import BrowserBreadcrumbs from "../../../../ObjectBrowser/BrowserBreadcrumbs";
|
||||
import DeleteObject from "../ListObjects/DeleteObject";
|
||||
import { removeRouteLevel } from "../../../../ObjectBrowser/actions";
|
||||
import { connect } from "react-redux";
|
||||
import AddTagModal from "./AddTagModal";
|
||||
import DeleteTagModal from "./DeleteTagModal";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
objectNameContainer: {
|
||||
marginBottom: 8,
|
||||
},
|
||||
objectPathContainer: {
|
||||
marginBottom: 26,
|
||||
fontSize: 10,
|
||||
},
|
||||
objectPathLink: {
|
||||
"&:visited": {
|
||||
color: "#000",
|
||||
},
|
||||
},
|
||||
objectName: {
|
||||
fontSize: 24,
|
||||
},
|
||||
propertiesContainer: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
marginBottom: 15,
|
||||
},
|
||||
propertiesItem: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
marginRight: 21,
|
||||
},
|
||||
propertiesItemBold: {
|
||||
fontWeight: 700,
|
||||
},
|
||||
propertiesValue: {
|
||||
marginLeft: 8,
|
||||
textTransform: "capitalize",
|
||||
},
|
||||
propertiesIcon: {
|
||||
marginLeft: 5,
|
||||
},
|
||||
actionsIconContainer: {
|
||||
marginLeft: 12,
|
||||
},
|
||||
actionsIcon: {
|
||||
height: 16,
|
||||
width: 16,
|
||||
"& .MuiSvgIcon-root": {
|
||||
height: 16,
|
||||
},
|
||||
},
|
||||
tagsContainer: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginBottom: 15,
|
||||
},
|
||||
tagText: {
|
||||
marginRight: 13,
|
||||
},
|
||||
tag: {
|
||||
marginRight: 6,
|
||||
fontSize: 10,
|
||||
fontWeight: 700,
|
||||
"&.MuiChip-sizeSmall": {
|
||||
height: 18,
|
||||
},
|
||||
"& .MuiSvgIcon-root": {
|
||||
height: 10,
|
||||
width: 10,
|
||||
},
|
||||
},
|
||||
search: {
|
||||
marginBottom: 8,
|
||||
"&.MuiFormControl-root": {
|
||||
marginRight: 0,
|
||||
},
|
||||
},
|
||||
...actionsTray,
|
||||
...searchField,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
interface IObjectDetailsProps {
|
||||
classes: any;
|
||||
routesList: Route[];
|
||||
removeRouteLevel: (newRoute: string) => any;
|
||||
}
|
||||
|
||||
interface IFileInfo {
|
||||
is_latest?: boolean;
|
||||
last_modified: string;
|
||||
legal_hold_status?: string;
|
||||
name: string;
|
||||
retention_mode?: string;
|
||||
retention_until_date?: string;
|
||||
size?: string;
|
||||
tags?: object;
|
||||
version_id: string;
|
||||
}
|
||||
|
||||
const emptyFile: IFileInfo = {
|
||||
is_latest: true,
|
||||
last_modified: "",
|
||||
legal_hold_status: "",
|
||||
name: "",
|
||||
retention_mode: "",
|
||||
retention_until_date: "",
|
||||
size: "0",
|
||||
tags: {},
|
||||
version_id: "",
|
||||
};
|
||||
|
||||
const ObjectDetails = ({
|
||||
classes,
|
||||
routesList,
|
||||
removeRouteLevel,
|
||||
}: IObjectDetailsProps) => {
|
||||
const [loadObjectData, setLoadObjectData] = useState<boolean>(true);
|
||||
const [shareFileModalOpen, setShareFileModalOpen] = useState<boolean>(false);
|
||||
const [retentionModalOpen, setRetentionModalOpen] = useState<boolean>(false);
|
||||
const [tagModalOpen, setTagModalOpen] = useState<boolean>(false);
|
||||
const [deleteTagModalOpen, setDeleteTagModalOpen] = useState<boolean>(false);
|
||||
const [selectedTag, setSelectedTag] = useState<[string, string]>(["", ""]);
|
||||
const [actualInfo, setActualInfo] = useState<IFileInfo>(emptyFile);
|
||||
const [versions, setVersions] = useState<IFileInfo[]>([]);
|
||||
const [filterVersion, setFilterVersion] = useState<string>("");
|
||||
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
const currentItem = routesList[routesList.length - 1];
|
||||
const allPathData = currentItem.route.split("/");
|
||||
const objectName = allPathData[allPathData.length - 1];
|
||||
const bucketName = allPathData[2];
|
||||
const pathInBucket = allPathData.slice(3).join("/");
|
||||
|
||||
useEffect(() => {
|
||||
if (loadObjectData) {
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/buckets/${bucketName}/objects?prefix=${pathInBucket}&with_versions=true`
|
||||
)
|
||||
.then((res: IFileInfo[]) => {
|
||||
const result = get(res, "objects", []);
|
||||
setActualInfo(
|
||||
result.find((el: IFileInfo) => el.is_latest) || emptyFile
|
||||
);
|
||||
setVersions(result.filter((el: IFileInfo) => !el.is_latest));
|
||||
setLoadObjectData(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
setError(error);
|
||||
setLoadObjectData(false);
|
||||
});
|
||||
}
|
||||
}, [loadObjectData]);
|
||||
|
||||
let tagKeys: string[] = [];
|
||||
|
||||
if (actualInfo.tags) {
|
||||
tagKeys = Object.keys(actualInfo.tags);
|
||||
}
|
||||
|
||||
const openRetentionModal = () => {
|
||||
setRetentionModalOpen(true);
|
||||
console.log("open retention modal");
|
||||
};
|
||||
|
||||
const closeRetentionModal = () => {
|
||||
setRetentionModalOpen(false);
|
||||
console.log("close retention modal");
|
||||
};
|
||||
|
||||
const shareObject = () => {
|
||||
setShareFileModalOpen(true);
|
||||
console.log("share object");
|
||||
};
|
||||
|
||||
const closeShareModal = () => {
|
||||
setShareFileModalOpen(false);
|
||||
console.log("close share modal");
|
||||
};
|
||||
|
||||
const deleteTag = (tagKey: string, tagLabel: string) => {
|
||||
setSelectedTag([tagKey, tagLabel]);
|
||||
setDeleteTagModalOpen(true);
|
||||
};
|
||||
|
||||
const downloadObject = (path: string) => {
|
||||
download(bucketName, path);
|
||||
};
|
||||
|
||||
const tableActions = [
|
||||
{ type: "share", onClick: shareObject, sendOnlyId: true },
|
||||
{ type: "download", onClick: downloadObject, sendOnlyId: true },
|
||||
];
|
||||
|
||||
const filteredRecords = versions.filter((version) =>
|
||||
version.version_id.includes(filterVersion)
|
||||
);
|
||||
|
||||
const displayParsedDate = (date: string) => {
|
||||
return <reactMoment.default>{date}</reactMoment.default>;
|
||||
};
|
||||
|
||||
const closeDeleteModal = (redirectBack: boolean) => {
|
||||
setDeleteOpen(false);
|
||||
|
||||
if (redirectBack) {
|
||||
const newPath = allPathData.slice(0, -1).join("/");
|
||||
|
||||
removeRouteLevel(newPath);
|
||||
history.push(newPath);
|
||||
}
|
||||
};
|
||||
|
||||
const closeAddTagModal = (reloadObjectData: boolean) => {
|
||||
setTagModalOpen(false);
|
||||
|
||||
if (reloadObjectData) {
|
||||
setLoadObjectData(true);
|
||||
}
|
||||
};
|
||||
|
||||
const closeDeleteTagModal = (reloadObjectData: boolean) => {
|
||||
setDeleteTagModalOpen(false);
|
||||
|
||||
if (reloadObjectData) {
|
||||
setLoadObjectData(true);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<PageHeader label={"Object Browser"} />
|
||||
{shareFileModalOpen && (
|
||||
<ShareFile
|
||||
open={shareFileModalOpen}
|
||||
closeModalAndRefresh={closeShareModal}
|
||||
/>
|
||||
)}
|
||||
{retentionModalOpen && (
|
||||
<SetRetention
|
||||
open={retentionModalOpen}
|
||||
closeModalAndRefresh={closeRetentionModal}
|
||||
objectName={objectName}
|
||||
/>
|
||||
)}
|
||||
{deleteOpen && (
|
||||
<DeleteObject
|
||||
deleteOpen={deleteOpen}
|
||||
selectedBucket={bucketName}
|
||||
selectedObject={pathInBucket}
|
||||
closeDeleteModalAndRefresh={closeDeleteModal}
|
||||
/>
|
||||
)}
|
||||
{tagModalOpen && (
|
||||
<AddTagModal
|
||||
modalOpen={tagModalOpen}
|
||||
currentTags={actualInfo.tags}
|
||||
selectedObject={pathInBucket}
|
||||
versionId={actualInfo.version_id}
|
||||
bucketName={bucketName}
|
||||
onCloseAndUpdate={closeAddTagModal}
|
||||
/>
|
||||
)}
|
||||
{deleteTagModalOpen && (
|
||||
<DeleteTagModal
|
||||
deleteOpen={deleteTagModalOpen}
|
||||
currentTags={actualInfo.tags}
|
||||
selectedObject={pathInBucket}
|
||||
versionId={actualInfo.version_id}
|
||||
bucketName={bucketName}
|
||||
onCloseAndUpdate={closeDeleteTagModal}
|
||||
selectedTag={selectedTag}
|
||||
/>
|
||||
)}
|
||||
<Grid container>
|
||||
<Grid item xs={12} className={classes.container}>
|
||||
<Grid item xs={12} className={classes.obTitleSection}>
|
||||
<div>
|
||||
<BrowserBreadcrumbs />
|
||||
</div>
|
||||
</Grid>
|
||||
<br />
|
||||
<Grid item xs={12} className={classes.propertiesContainer}>
|
||||
<div className={classes.propertiesItem}>
|
||||
<div>
|
||||
<span className={classes.propertiesItemBold}>Legal Hold:</span>
|
||||
<span className={classes.propertiesValue}>
|
||||
{actualInfo.legal_hold_status
|
||||
? actualInfo.legal_hold_status.toLowerCase()
|
||||
: "Off"}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<IconButton
|
||||
color="primary"
|
||||
aria-label="legal-hold"
|
||||
size="small"
|
||||
className={classes.propertiesIcon}
|
||||
onClick={() => {
|
||||
console.log("open legal hold modal");
|
||||
}}
|
||||
>
|
||||
<PencilIcon active={true} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.propertiesItem}>
|
||||
<div>
|
||||
<span className={classes.propertiesItemBold}>Retention:</span>
|
||||
<span className={classes.propertiesValue}>
|
||||
{actualInfo.retention_mode
|
||||
? actualInfo.retention_mode.toLowerCase()
|
||||
: "Undefined"}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<IconButton
|
||||
color="primary"
|
||||
aria-label="retention"
|
||||
size="small"
|
||||
className={classes.propertiesIcon}
|
||||
onClick={() => {
|
||||
openRetentionModal();
|
||||
}}
|
||||
>
|
||||
<PencilIcon active={true} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.propertiesItem}>
|
||||
<div className={classes.propertiesItemBold}>File Actions:</div>
|
||||
<div className={classes.actionsIconContainer}>
|
||||
<IconButton
|
||||
color="primary"
|
||||
aria-label="share"
|
||||
size="small"
|
||||
className={classes.actionsIcon}
|
||||
onClick={() => {
|
||||
shareObject();
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className={classes.actionsIconContainer}>
|
||||
<IconButton
|
||||
color="primary"
|
||||
aria-label="download"
|
||||
size="small"
|
||||
className={classes.actionsIcon}
|
||||
onClick={() => {
|
||||
downloadObject(pathInBucket);
|
||||
}}
|
||||
>
|
||||
<DownloadIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className={classes.actionsIconContainer}>
|
||||
<IconButton
|
||||
color="primary"
|
||||
aria-label="delete"
|
||||
size="small"
|
||||
className={classes.actionsIcon}
|
||||
onClick={() => {
|
||||
setDeleteOpen(true);
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.tagsContainer}>
|
||||
<div className={classes.tagText}>Tags:</div>
|
||||
{tagKeys.map((tagKey, index) => {
|
||||
const tag = get(actualInfo, `tags.${tagKey}`, "");
|
||||
if (tag !== "") {
|
||||
return (
|
||||
<Chip
|
||||
key={`chip-${index}`}
|
||||
className={classes.tag}
|
||||
size="small"
|
||||
label={`${tagKey} : ${tag}`}
|
||||
color="primary"
|
||||
deleteIcon={<CloseIcon />}
|
||||
onDelete={() => {
|
||||
deleteTag(tagKey, tag);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
<Chip
|
||||
className={classes.tag}
|
||||
icon={<AddIcon />}
|
||||
clickable
|
||||
size="small"
|
||||
label="Add tag"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setTagModalOpen(true);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.actionsTray}>
|
||||
<TextField
|
||||
placeholder={`Search ${objectName}`}
|
||||
className={clsx(classes.search, classes.searchField)}
|
||||
id="search-resource"
|
||||
label=""
|
||||
onChange={(val) => {
|
||||
setFilterVersion(val.target.value);
|
||||
}}
|
||||
InputProps={{
|
||||
disableUnderline: true,
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TableWrapper
|
||||
itemActions={tableActions}
|
||||
columns={[
|
||||
{ label: "Version ID", elementKey: "version_id" },
|
||||
{
|
||||
label: "Last Modified",
|
||||
elementKey: "last_modified",
|
||||
renderFunction: displayParsedDate,
|
||||
},
|
||||
]}
|
||||
isLoading={false}
|
||||
entityName="Versions"
|
||||
idField="version_id"
|
||||
records={filteredRecords}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const mapDispatchToProps = {
|
||||
removeRouteLevel,
|
||||
};
|
||||
|
||||
const connector = connect(null, mapDispatchToProps);
|
||||
|
||||
export default connector(withStyles(styles)(ObjectDetails));
|
||||
@@ -0,0 +1,138 @@
|
||||
import React, { useState, useRef } from "react";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
|
||||
import FormSwitchWrapper from "../../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import RadioGroupSelector from "../../../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
|
||||
import DateSelector from "../../../../Common/FormComponents/DateSelector/DateSelector";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
objectName: {
|
||||
fontSize: 18,
|
||||
fontWeight: 700,
|
||||
marginBottom: 40,
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right",
|
||||
},
|
||||
...modalBasic,
|
||||
});
|
||||
|
||||
interface ISetRetentionProps {
|
||||
classes: any;
|
||||
open: boolean;
|
||||
closeModalAndRefresh: () => void;
|
||||
objectName: string;
|
||||
}
|
||||
|
||||
interface IRefObject {
|
||||
resetDate: () => void;
|
||||
}
|
||||
|
||||
const SetRetention = ({
|
||||
classes,
|
||||
open,
|
||||
closeModalAndRefresh,
|
||||
objectName,
|
||||
}: ISetRetentionProps) => {
|
||||
const [statusEnabled, setStatusEnabled] = useState<boolean>(false);
|
||||
const [type, setType] = useState<string>("");
|
||||
|
||||
const dateElement = useRef<IRefObject>(null);
|
||||
|
||||
const dateFieldDisabled = () => {
|
||||
return !(statusEnabled && (type === "governance" || type === "compliance"));
|
||||
};
|
||||
|
||||
const onSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
setStatusEnabled(false);
|
||||
setType("");
|
||||
if (dateElement.current) {
|
||||
dateElement.current.resetDate();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalWrapper
|
||||
title="Set Retention Policy"
|
||||
modalOpen={open}
|
||||
onClose={() => {
|
||||
resetForm();
|
||||
closeModalAndRefresh();
|
||||
}}
|
||||
>
|
||||
<Grid item xs={12} className={classes.objectName}>
|
||||
{objectName}
|
||||
</Grid>
|
||||
<form
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
|
||||
onSubmit(e);
|
||||
}}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
<FormSwitchWrapper
|
||||
value="status"
|
||||
id="status"
|
||||
name="status"
|
||||
checked={statusEnabled}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setStatusEnabled(!statusEnabled);
|
||||
setType("");
|
||||
}}
|
||||
label={"Status"}
|
||||
indicatorLabels={["Enabled", "Disabled"]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<RadioGroupSelector
|
||||
currentSelection={type}
|
||||
id="type"
|
||||
name="type"
|
||||
label="Type"
|
||||
disableOptions={!statusEnabled}
|
||||
onChange={(e) => {
|
||||
setType(e.target.value);
|
||||
}}
|
||||
selectorOptions={[
|
||||
{ label: "Governance", value: "governance" },
|
||||
{ label: "Compliance", value: "compliance" },
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<DateSelector
|
||||
id="date"
|
||||
label="Date"
|
||||
disableOptions={dateFieldDisabled()}
|
||||
ref={dateElement}
|
||||
borderBottom={true}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.buttonContainer}>
|
||||
<button
|
||||
type="button"
|
||||
color="primary"
|
||||
className={classes.clearButton}
|
||||
onClick={resetForm}
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
<Button type="submit" variant="contained" color="primary">
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
</form>
|
||||
</ModalWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(SetRetention);
|
||||
@@ -0,0 +1,78 @@
|
||||
import React, { useState } from "react";
|
||||
import CopyToClipboard from "react-copy-to-clipboard";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import {
|
||||
modalBasic,
|
||||
predefinedList,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
|
||||
import DateSelector from "../../../../Common/FormComponents/DateSelector/DateSelector";
|
||||
import { CopyIcon } from "../../../../../../icons";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
copyButtonContainer: {
|
||||
paddingLeft: 16,
|
||||
},
|
||||
modalContent: {
|
||||
paddingBottom: 53,
|
||||
},
|
||||
...modalBasic,
|
||||
...predefinedList,
|
||||
});
|
||||
|
||||
interface IShareFileProps {
|
||||
classes: any;
|
||||
open: boolean;
|
||||
closeModalAndRefresh: () => void;
|
||||
}
|
||||
|
||||
const ShareFile = ({
|
||||
classes,
|
||||
open,
|
||||
closeModalAndRefresh,
|
||||
}: IShareFileProps) => {
|
||||
return (
|
||||
<ModalWrapper
|
||||
title="Share File"
|
||||
modalOpen={open}
|
||||
onClose={() => {
|
||||
closeModalAndRefresh();
|
||||
}}
|
||||
>
|
||||
<Grid container className={classes.modalContent}>
|
||||
<Grid item xs={12} className={classes.dateContainer}>
|
||||
<DateSelector
|
||||
id="date"
|
||||
label="Active until"
|
||||
borderBottom={false}
|
||||
addSwitch={true}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid container item xs={12}>
|
||||
<Grid item xs={10} className={classes.predefinedList}>
|
||||
{"https://somelink.will/go/here"}
|
||||
</Grid>
|
||||
<Grid item xs={2} className={classes.copyButtonContainer}>
|
||||
<CopyToClipboard text={"https://somelink.will/go/here"}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<CopyIcon />}
|
||||
onClick={() => {
|
||||
console.log("copied!");
|
||||
}}
|
||||
>
|
||||
Copy
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ModalWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(ShareFile);
|
||||
@@ -0,0 +1,48 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import storage from "local-storage-fallback";
|
||||
|
||||
export const download = (bucketName: string, objectName: string) => {
|
||||
const anchor = document.createElement("a");
|
||||
document.body.appendChild(anchor);
|
||||
const token: string = storage.getItem("token")!;
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open(
|
||||
"GET",
|
||||
`/api/v1/buckets/${bucketName}/objects/download?prefix=${objectName}`,
|
||||
true
|
||||
);
|
||||
xhr.responseType = "blob";
|
||||
|
||||
xhr.onload = function (e) {
|
||||
if (this.status === 200) {
|
||||
const blob = new Blob([this.response], {
|
||||
type: "octet/stream",
|
||||
});
|
||||
const blobUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
anchor.href = blobUrl;
|
||||
anchor.download = objectName;
|
||||
|
||||
anchor.click();
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
anchor.remove();
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
@@ -642,20 +642,6 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
|
||||
records={filteredRecords}
|
||||
entityName="Events"
|
||||
idField="id"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: totalRecords,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel index={1} value={curTab}>
|
||||
@@ -683,20 +669,6 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
|
||||
records={filteredRules}
|
||||
entityName="Replication Rules"
|
||||
idField="id"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: totalRecords,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</TabPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -82,14 +82,6 @@ const CredentialsPrompt = ({
|
||||
<Grid container>
|
||||
<Grid item xs={12} className={classes.formScrollable}>
|
||||
A new {entity} has been created with the following details:
|
||||
<ul>
|
||||
<li>
|
||||
<b>Access Key:</b> {newServiceAccount.accessKey}
|
||||
</li>
|
||||
<li>
|
||||
<b>Secret Key:</b> {newServiceAccount.secretKey}
|
||||
</li>
|
||||
</ul>
|
||||
{consoleCreds && (
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
@@ -131,8 +123,6 @@ const CredentialsPrompt = ({
|
||||
download(
|
||||
"credentials.json",
|
||||
JSON.stringify({
|
||||
access_key: newServiceAccount.accessKey,
|
||||
secret_key: newServiceAccount.secretKey,
|
||||
...consoleExtras,
|
||||
})
|
||||
);
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export interface NewServiceAccount {
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
console?: ConsoleSA;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
import React, { useState, forwardRef, useImperativeHandle } from "react";
|
||||
import clsx from "clsx";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import InputLabel from "@material-ui/core/InputLabel";
|
||||
import Tooltip from "@material-ui/core/Tooltip";
|
||||
import HelpIcon from "@material-ui/icons/Help";
|
||||
import FormControl from "@material-ui/core/FormControl";
|
||||
import Select from "@material-ui/core/Select";
|
||||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
import InputBase from "@material-ui/core/InputBase";
|
||||
import { fieldBasic, tooltipHelper } from "../common/styleLibrary";
|
||||
import FormSwitchWrapper from "../FormSwitchWrapper/FormSwitchWrapper";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
dateInput: {
|
||||
"&:not(:last-child)": {
|
||||
marginRight: 22,
|
||||
},
|
||||
},
|
||||
...fieldBasic,
|
||||
...tooltipHelper,
|
||||
labelContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
fieldContainer: {
|
||||
...fieldBasic.fieldContainer,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
paddingBottom: 10,
|
||||
marginTop: 11,
|
||||
marginBottom: 6,
|
||||
},
|
||||
fieldContainerBorder: {
|
||||
borderBottom: "#9c9c9c 1px solid",
|
||||
marginBottom: 20,
|
||||
},
|
||||
});
|
||||
|
||||
const SelectStyled = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
"& .MuiSelect-icon": {
|
||||
color: "#000",
|
||||
"&.Mui-disabled": {
|
||||
color: "#9c9c9c",
|
||||
},
|
||||
},
|
||||
},
|
||||
input: {
|
||||
borderBottom: 0,
|
||||
fontSize: 12,
|
||||
},
|
||||
})
|
||||
)(InputBase);
|
||||
|
||||
interface IDateSelectorProps {
|
||||
classes: any;
|
||||
id: string;
|
||||
label: string;
|
||||
disableOptions?: boolean;
|
||||
addSwitch?: boolean;
|
||||
tooltip?: string;
|
||||
borderBottom?: boolean;
|
||||
}
|
||||
|
||||
const DateSelector = forwardRef(
|
||||
(
|
||||
{
|
||||
classes,
|
||||
id,
|
||||
label,
|
||||
disableOptions = false,
|
||||
addSwitch = false,
|
||||
tooltip = "",
|
||||
borderBottom = false,
|
||||
}: IDateSelectorProps,
|
||||
ref: any
|
||||
) => {
|
||||
useImperativeHandle(ref, () => ({ resetDate }));
|
||||
|
||||
const [dateEnabled, setDateEnabled] = useState<boolean>(false);
|
||||
const [month, setMonth] = useState<string>("");
|
||||
const [day, setDay] = useState<string>("");
|
||||
const [year, setYear] = useState<string>("");
|
||||
|
||||
const resetDate = () => {
|
||||
setMonth("");
|
||||
setDay("");
|
||||
setYear("");
|
||||
};
|
||||
|
||||
const isDateDisabled = () => {
|
||||
if (disableOptions) {
|
||||
return disableOptions;
|
||||
} else if (addSwitch) {
|
||||
return !dateEnabled;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const onMonthChange = (
|
||||
e: React.ChangeEvent<{ name?: string | undefined; value: unknown }>
|
||||
) => {
|
||||
setMonth(e.target.value as string);
|
||||
};
|
||||
|
||||
const onDayChange = (
|
||||
e: React.ChangeEvent<{ name?: string | undefined; value: unknown }>
|
||||
) => {
|
||||
setDay(e.target.value as string);
|
||||
};
|
||||
|
||||
const onYearChange = (
|
||||
e: React.ChangeEvent<{ name?: string | undefined; value: unknown }>
|
||||
) => {
|
||||
setYear(e.target.value as string);
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
className={clsx(classes.fieldContainer, {
|
||||
[classes.fieldContainerBorder]: borderBottom,
|
||||
})}
|
||||
>
|
||||
<div className={classes.labelContainer}>
|
||||
<Grid container>
|
||||
<InputLabel htmlFor={id} className={classes.inputLabel}>
|
||||
<span>{label}</span>
|
||||
{tooltip !== "" && (
|
||||
<div className={classes.tooltipContainer}>
|
||||
<Tooltip title={tooltip} placement="top-start">
|
||||
<HelpIcon className={classes.tooltip} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</InputLabel>
|
||||
{addSwitch && (
|
||||
<FormSwitchWrapper
|
||||
indicatorLabels={["Specific Date", "Always active"]}
|
||||
checked={dateEnabled}
|
||||
value={"date_enabled"}
|
||||
id="date-status"
|
||||
name="date-status"
|
||||
onChange={(e) => {
|
||||
setDateEnabled(e.target.checked);
|
||||
}}
|
||||
switchOnly
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</div>
|
||||
<div>
|
||||
<FormControl
|
||||
disabled={isDateDisabled()}
|
||||
className={classes.dateInput}
|
||||
>
|
||||
<Select
|
||||
id={`${id}-month`}
|
||||
name={`${id}-month`}
|
||||
value={month}
|
||||
displayEmpty
|
||||
onChange={onMonthChange}
|
||||
input={<SelectStyled />}
|
||||
>
|
||||
<MenuItem value="" disabled>
|
||||
{"<Month>"}
|
||||
</MenuItem>
|
||||
<MenuItem value={"1"}>January</MenuItem>
|
||||
{/* {options.map((option) => (
|
||||
<MenuItem
|
||||
value={option.value}
|
||||
key={`select-${name}-${option.label}`}
|
||||
>
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
))} */}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
disabled={isDateDisabled()}
|
||||
className={classes.dateInput}
|
||||
>
|
||||
<Select
|
||||
id={`${id}-day`}
|
||||
name={`${id}-day`}
|
||||
value={day}
|
||||
displayEmpty
|
||||
onChange={onDayChange}
|
||||
input={<SelectStyled />}
|
||||
>
|
||||
<MenuItem value="" disabled>
|
||||
{"<Day>"}
|
||||
</MenuItem>
|
||||
<MenuItem value={"1"}>1</MenuItem>
|
||||
<MenuItem value={"2"}>2</MenuItem>
|
||||
{/* {options.map((option) => (
|
||||
<MenuItem
|
||||
value={option.value}
|
||||
key={`select-${name}-${option.label}`}
|
||||
>
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
))} */}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
disabled={isDateDisabled()}
|
||||
className={classes.dateInput}
|
||||
>
|
||||
<Select
|
||||
id={`${id}-year`}
|
||||
name={`${id}-year`}
|
||||
value={year}
|
||||
displayEmpty
|
||||
onChange={onYearChange}
|
||||
input={<SelectStyled />}
|
||||
>
|
||||
<MenuItem value="" disabled>
|
||||
{"<Year>"}
|
||||
</MenuItem>
|
||||
<MenuItem value={"2020"}>2020</MenuItem>
|
||||
<MenuItem value={"2021"}>2021</MenuItem>
|
||||
{/* {options.map((option) => (
|
||||
<MenuItem
|
||||
value={option.value}
|
||||
key={`select-${name}-${option.label}`}
|
||||
>
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
))} */}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default withStyles(styles)(DateSelector);
|
||||
@@ -31,7 +31,7 @@ interface IFormSwitch {
|
||||
disabled?: boolean;
|
||||
tooltip?: string;
|
||||
index?: number;
|
||||
indicatorLabel?: string;
|
||||
indicatorLabels?: string[];
|
||||
checked: boolean;
|
||||
switchOnly?: boolean;
|
||||
}
|
||||
@@ -142,14 +142,21 @@ const StyledSwitch = withStyles({
|
||||
opacity: 1,
|
||||
height: 15,
|
||||
},
|
||||
"&:hover": {
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
},
|
||||
checked: {},
|
||||
track: {
|
||||
height: 15,
|
||||
backgroundColor: "#081C42",
|
||||
backgroundColor: "#9C9C9C",
|
||||
border: "#081C42 1px solid",
|
||||
opacity: 1,
|
||||
padding: 0,
|
||||
marginTop: 1.5,
|
||||
"&$checked": {
|
||||
backgroundColor: "#081C42",
|
||||
},
|
||||
},
|
||||
thumb: {
|
||||
backgroundColor: "#fff",
|
||||
@@ -172,7 +179,7 @@ const FormSwitchWrapper = ({
|
||||
disabled = false,
|
||||
switchOnly = false,
|
||||
tooltip = "",
|
||||
indicatorLabel = "",
|
||||
indicatorLabels = [],
|
||||
classes,
|
||||
}: IFormSwitch) => {
|
||||
const switchComponent = (
|
||||
@@ -190,8 +197,10 @@ const FormSwitchWrapper = ({
|
||||
disableTouchRipple
|
||||
value={value}
|
||||
/>
|
||||
{indicatorLabel !== "" && (
|
||||
<span className={classes.indicatorLabel}>{indicatorLabel}</span>
|
||||
{indicatorLabels.length === 2 && (
|
||||
<span className={classes.indicatorLabel}>
|
||||
{checked ? indicatorLabels[0] : indicatorLabels[1]}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import React from "react";
|
||||
import clsx from "clsx";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import RadioGroup from "@material-ui/core/RadioGroup";
|
||||
import FormControlLabel from "@material-ui/core/FormControlLabel";
|
||||
@@ -40,6 +41,7 @@ interface RadioGroupProps {
|
||||
id: string;
|
||||
name: string;
|
||||
tooltip?: string;
|
||||
disableOptions?: boolean;
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
classes: any;
|
||||
displayInColumn?: boolean;
|
||||
@@ -58,8 +60,23 @@ const styles = (theme: Theme) =>
|
||||
paddingBottom: 10,
|
||||
marginTop: 11,
|
||||
},
|
||||
optionLabel: {
|
||||
"&.Mui-disabled": {
|
||||
"& .MuiFormControlLabel-label": {
|
||||
color: "#9c9c9c",
|
||||
},
|
||||
},
|
||||
"&:last-child": {
|
||||
marginRight: 0,
|
||||
},
|
||||
"& .MuiFormControlLabel-label": {
|
||||
fontSize: 12,
|
||||
color: "#000",
|
||||
},
|
||||
},
|
||||
checkedOption: {
|
||||
"& .MuiFormControlLabel-label": {
|
||||
fontSize: 12,
|
||||
color: "#000",
|
||||
fontWeight: 700,
|
||||
},
|
||||
@@ -98,6 +115,7 @@ export const RadioGroupSelector = ({
|
||||
name,
|
||||
onChange,
|
||||
tooltip = "",
|
||||
disableOptions = false,
|
||||
classes,
|
||||
displayInColumn = false,
|
||||
}: RadioGroupProps) => {
|
||||
@@ -128,14 +146,14 @@ export const RadioGroupSelector = ({
|
||||
return (
|
||||
<FormControlLabel
|
||||
key={`rd-${name}-${selectorOption.value}`}
|
||||
value={selectorOption.value}
|
||||
value={disableOptions ? "disabled" : selectorOption.value}
|
||||
control={<RadioButton />}
|
||||
label={selectorOption.label}
|
||||
className={
|
||||
selectorOption.value === currentSelection
|
||||
? classes.checkedOption
|
||||
: ""
|
||||
}
|
||||
disabled={disableOptions}
|
||||
className={clsx(classes.optionLabel, {
|
||||
[classes.checkedOption]:
|
||||
selectorOption.value === currentSelection,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -54,6 +54,7 @@ export const modalBasic = {
|
||||
marginLeft: 0,
|
||||
},
|
||||
clearButton: {
|
||||
fontFamily: "Lato, sans-serif",
|
||||
border: "0",
|
||||
backgroundColor: "transparent",
|
||||
color: "#393939",
|
||||
@@ -104,6 +105,9 @@ const radioBasic = {
|
||||
width: 12,
|
||||
height: 12,
|
||||
borderRadius: "100%",
|
||||
"input:disabled ~ &": {
|
||||
border: "1px solid #9C9C9C",
|
||||
},
|
||||
};
|
||||
|
||||
export const radioIcons = {
|
||||
@@ -117,8 +121,7 @@ export const radioIcons = {
|
||||
|
||||
export const containerForHeader = (bottomSpacing: any) => ({
|
||||
container: {
|
||||
padding: "110px 33px 30px",
|
||||
paddingBottom: bottomSpacing,
|
||||
padding: "110px 33px 0",
|
||||
"& h6": {
|
||||
color: "#777777",
|
||||
fontSize: 14,
|
||||
@@ -153,13 +156,17 @@ export const searchField = {
|
||||
justifyContent: "center",
|
||||
padding: "0 16px",
|
||||
"& input": {
|
||||
fontSize: 14,
|
||||
fontSize: 12,
|
||||
fontWeight: 700,
|
||||
color: "#000",
|
||||
"&::placeholder": {
|
||||
color: "#393939",
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
"&:hover": {
|
||||
borderColor: "#000",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -207,3 +214,9 @@ export const objectBrowserCommon = {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const selectorsCommon = {
|
||||
multiSelectTable: {
|
||||
height: 200,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -18,13 +18,21 @@ import isString from "lodash/isString";
|
||||
import { IconButton } from "@material-ui/core";
|
||||
import ViewIcon from "./TableActionIcons/ViewIcon";
|
||||
import PencilIcon from "./TableActionIcons/PencilIcon";
|
||||
import ShareIcon from "./TableActionIcons/ShareIcon";
|
||||
import DeleteIcon from "./TableActionIcons/DeleteIcon";
|
||||
import DescriptionIcon from "./TableActionIcons/DescriptionIcon";
|
||||
import CloudIcon from "./TableActionIcons/CloudIcon";
|
||||
import ConsoleIcon from "./TableActionIcons/ConsoleIcon";
|
||||
import GetAppIcon from "@material-ui/icons/GetApp";
|
||||
import SvgIcon from "@material-ui/core/SvgIcon";
|
||||
import DownloadIcon from "./TableActionIcons/DownloadIcon";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStyles, withStyles } from "@material-ui/core/styles";
|
||||
|
||||
const styles = () =>
|
||||
createStyles({
|
||||
spacing: {
|
||||
margin: "0 8px",
|
||||
},
|
||||
});
|
||||
|
||||
interface IActionButton {
|
||||
type: string;
|
||||
@@ -34,6 +42,7 @@ interface IActionButton {
|
||||
selected: boolean;
|
||||
sendOnlyId?: boolean;
|
||||
idField: string;
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const defineIcon = (type: string, selected: boolean) => {
|
||||
@@ -46,14 +55,14 @@ const defineIcon = (type: string, selected: boolean) => {
|
||||
return <DeleteIcon active={selected} />;
|
||||
case "description":
|
||||
return <DescriptionIcon active={selected} />;
|
||||
case "share":
|
||||
return <ShareIcon active={selected} />;
|
||||
case "cloud":
|
||||
return <CloudIcon active={selected} />;
|
||||
case "console":
|
||||
return <ConsoleIcon active={selected} />;
|
||||
case "download":
|
||||
return (
|
||||
<SvgIcon component={GetAppIcon} fontSize="small" color="primary" />
|
||||
);
|
||||
return <DownloadIcon active={selected} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -67,6 +76,7 @@ const TableActionButton = ({
|
||||
selected,
|
||||
to,
|
||||
sendOnlyId = false,
|
||||
classes,
|
||||
}: IActionButton) => {
|
||||
const valueClick = sendOnlyId ? valueToSend[idField] : valueToSend;
|
||||
|
||||
@@ -82,6 +92,7 @@ const TableActionButton = ({
|
||||
}
|
||||
: () => null
|
||||
}
|
||||
className={classes.spacing}
|
||||
>
|
||||
{defineIcon(type, selected)}
|
||||
</IconButton>
|
||||
@@ -107,4 +118,4 @@ const TableActionButton = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
export default TableActionButton;
|
||||
export default withStyles(styles)(TableActionButton);
|
||||
|
||||
@@ -9,17 +9,10 @@ const DeleteIcon = ({ active = false }: IIcon) => {
|
||||
height="16"
|
||||
viewBox="0 0 10.402 13"
|
||||
>
|
||||
<g transform="translate(0.004 -28.959)">
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M6.757,29.959v-1H3.636v1H0v1H10.4v-1Z"
|
||||
/>
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M0,31.957l1.672,10H8.724l1.673-10ZM3.412,40.2,2.86,33.722h.653l.553,6.472Zm3.569,0H6.328l.551-6.472h.654Z"
|
||||
transform="translate(0 0)"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M6.761 1V0H3.64v1H.004v1h10.4V1zM.004 2.998l1.672 10h7.052l1.673-10zm3.412 8.243l-.552-6.478h.653l.553 6.472zm3.569 0h-.653l.551-6.472h.654z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import { IIcon, selected, unSelected } from "./common";
|
||||
|
||||
const DeleteIcon = ({ active = false }: IIcon) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 13 12.996"
|
||||
>
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M11.05 9.096v1.95h-9.1v-1.95H0v3.9h13v-3.9z"
|
||||
></path>
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M6.5 9.75L9 6.672H7.475V0h-1.95v6.672H4z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteIcon;
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from "react";
|
||||
import { IIcon, selected, unSelected } from "./common";
|
||||
|
||||
const ShareIcon = ({ active = false }: IIcon) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 13 13"
|
||||
>
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M11.05 8.617v2.429h-9.1v-9.1h2.429v-1.95H0v13h13V8.617z"
|
||||
className="a"
|
||||
></path>
|
||||
<path
|
||||
fill={active ? selected : unSelected}
|
||||
d="M3.854 9.256h1.95a4.945 4.945 0 013.6-4.74v1.3l.6-.487 2.474-2.012L9.4.817v1.7a6.9 6.9 0 00-5.546 6.739z"
|
||||
className="a"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShareIcon;
|
||||
@@ -18,19 +18,13 @@ import get from "lodash/get";
|
||||
import isString from "lodash/isString";
|
||||
import {
|
||||
LinearProgress,
|
||||
TablePagination,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Paper,
|
||||
Grid,
|
||||
Checkbox,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { TablePaginationActionsProps } from "@material-ui/core/TablePagination/TablePaginationActions";
|
||||
import { Table, Column, AutoSizer } from "react-virtualized";
|
||||
import { createStyles, withStyles } from "@material-ui/core/styles";
|
||||
import TableActionButton from "./TableActionButton";
|
||||
import history from "../../../../history";
|
||||
import {
|
||||
@@ -50,28 +44,13 @@ interface ItemActions {
|
||||
interface IColumns {
|
||||
label: string;
|
||||
elementKey: string;
|
||||
sortable?: boolean;
|
||||
renderFunction?: (input: any) => any;
|
||||
renderFullObject?: boolean;
|
||||
globalClass?: any;
|
||||
rowClass?: any;
|
||||
}
|
||||
|
||||
interface IPaginatorConfig {
|
||||
rowsPerPageOptions: number[];
|
||||
colSpan: number;
|
||||
count: number;
|
||||
rowsPerPage: number;
|
||||
page: number;
|
||||
SelectProps: any;
|
||||
onChangePage: (
|
||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||
page: number
|
||||
) => void;
|
||||
onChangeRowsPerPage?: React.ChangeEventHandler<
|
||||
HTMLTextAreaElement | HTMLInputElement
|
||||
>;
|
||||
ActionsComponent?: React.ElementType<TablePaginationActionsProps>;
|
||||
width?: number;
|
||||
headerTextAlign?: string;
|
||||
contentTextAlign?: string;
|
||||
}
|
||||
|
||||
interface TableWrapperProps {
|
||||
@@ -84,10 +63,9 @@ interface TableWrapperProps {
|
||||
classes: any;
|
||||
entityName: string;
|
||||
selectedItems?: string[];
|
||||
stickyHeader?: boolean;
|
||||
radioSelection?: boolean;
|
||||
customEmptyMessage?: string;
|
||||
paginatorConfig?: IPaginatorConfig;
|
||||
customPaperHeight?: string;
|
||||
}
|
||||
|
||||
const borderColor = "#9c9c9c80";
|
||||
@@ -104,7 +82,7 @@ const rowText = {
|
||||
paddingLeft: 6,
|
||||
};
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const styles = () =>
|
||||
createStyles({
|
||||
dialogContainer: {
|
||||
padding: "12px 26px 22px",
|
||||
@@ -117,7 +95,16 @@ const styles = (theme: Theme) =>
|
||||
boxShadow: "none",
|
||||
border: "#EAEDEE 1px solid",
|
||||
borderRadius: 3,
|
||||
minHeight: "calc(100vh - 340px)",
|
||||
minHeight: 200,
|
||||
overflowY: "scroll",
|
||||
|
||||
"&::-webkit-scrollbar": {
|
||||
width: 3,
|
||||
height: 3,
|
||||
},
|
||||
},
|
||||
defaultPaperHeight: {
|
||||
height: "calc(100vh - 205px)",
|
||||
},
|
||||
allTableSettings: {
|
||||
"& .MuiTableCell-sizeSmall:last-child": {
|
||||
@@ -177,63 +164,143 @@ const styles = (theme: Theme) =>
|
||||
paddingTop: "100px",
|
||||
paddingBottom: "100px",
|
||||
},
|
||||
rowElement: {
|
||||
userSelect: "none",
|
||||
|
||||
"&:hover": {
|
||||
backgroundColor: "#ececec",
|
||||
|
||||
"& td": {
|
||||
"@global": {
|
||||
".rowLine": {
|
||||
borderBottom: `1px solid ${borderColor}`,
|
||||
height: 40,
|
||||
color: "#393939",
|
||||
fontSize: 14,
|
||||
transitionDuration: 0.3,
|
||||
"&:focus": {
|
||||
outline: "initial",
|
||||
},
|
||||
"&:hover:not(.ReactVirtualized__Table__headerRow)": {
|
||||
userSelect: "none",
|
||||
backgroundColor: "#ececec",
|
||||
fontWeight: 600,
|
||||
"&.canClick": {
|
||||
cursor: "pointer",
|
||||
},
|
||||
},
|
||||
"& .selected": {
|
||||
color: "#081C42",
|
||||
fontWeight: 600,
|
||||
},
|
||||
},
|
||||
},
|
||||
rowClickable: {
|
||||
cursor: "pointer",
|
||||
".headerItem": {
|
||||
userSelect: "none",
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
fontStyle: "initial",
|
||||
},
|
||||
".ReactVirtualized__Table__headerRow": {
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
borderColor: "#39393980",
|
||||
textTransform: "initial",
|
||||
},
|
||||
".optionsAlignment": {
|
||||
textAlign: "center",
|
||||
},
|
||||
".text-center": {
|
||||
textAlign: "center",
|
||||
},
|
||||
".text-right": {
|
||||
textAlign: "right",
|
||||
},
|
||||
},
|
||||
...checkboxIcons,
|
||||
...radioIcons,
|
||||
});
|
||||
|
||||
// Function that renders Title Columns
|
||||
const titleColumnsMap = (columns: IColumns[]) => {
|
||||
return columns.map((column: IColumns, index: number) => {
|
||||
return (
|
||||
<TableCell
|
||||
key={`tbCT-${column.elementKey}-${index}`}
|
||||
className={column.globalClass}
|
||||
>
|
||||
{column.label}
|
||||
</TableCell>
|
||||
);
|
||||
});
|
||||
};
|
||||
const selectWidth = 45;
|
||||
|
||||
// Function that renders Rows
|
||||
const rowColumnsMap = (
|
||||
columns: IColumns[],
|
||||
itemData: any,
|
||||
classes: any,
|
||||
// Function to render elements in table
|
||||
const subRenderFunction = (
|
||||
rowData: any,
|
||||
column: IColumns,
|
||||
isSelected: boolean
|
||||
) => {
|
||||
return columns.map((column: IColumns, index: number) => {
|
||||
const itemElement = isString(itemData)
|
||||
? itemData
|
||||
: get(itemData, column.elementKey, null); // If the element is just a string, we render it as it is
|
||||
const renderConst = column.renderFullObject ? itemData : itemElement;
|
||||
const itemElement = isString(rowData)
|
||||
? rowData
|
||||
: get(rowData, column.elementKey, null); // If the element is just a string, we render it as it is
|
||||
const renderConst = column.renderFullObject ? rowData : itemElement;
|
||||
|
||||
const renderElement = column.renderFunction
|
||||
? column.renderFunction(renderConst)
|
||||
: renderConst; // If render function is set, we send the value to the function.
|
||||
const renderElement = column.renderFunction
|
||||
? column.renderFunction(renderConst)
|
||||
: renderConst; // If render function is set, we send the value to the function.
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span className={isSelected ? "selected" : ""}>{renderElement}</span>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
// Function to calculate common column width for elements with no with size
|
||||
const calculateColumnRest = (
|
||||
columns: IColumns[],
|
||||
containerWidth: number,
|
||||
actionsWidth: number,
|
||||
hasSelect: boolean,
|
||||
hasActions: boolean
|
||||
) => {
|
||||
let initialValue = containerWidth;
|
||||
|
||||
if (hasSelect) {
|
||||
initialValue -= selectWidth;
|
||||
}
|
||||
|
||||
if (hasActions) {
|
||||
initialValue -= actionsWidth;
|
||||
}
|
||||
|
||||
let freeSpacing = columns.reduce((total, currValue) => {
|
||||
return currValue.width ? total - currValue.width : total;
|
||||
}, initialValue);
|
||||
|
||||
return freeSpacing / columns.filter((el) => !el.width).length;
|
||||
};
|
||||
|
||||
// Function that renders Columns in table
|
||||
const generateColumnsMap = (
|
||||
columns: IColumns[],
|
||||
containerWidth: number,
|
||||
actionsWidth: number,
|
||||
hasSelect: boolean,
|
||||
hasActions: boolean,
|
||||
selectedItems: string[],
|
||||
idField: string
|
||||
) => {
|
||||
const commonRestWidth = calculateColumnRest(
|
||||
columns,
|
||||
containerWidth,
|
||||
actionsWidth,
|
||||
hasSelect,
|
||||
hasActions
|
||||
);
|
||||
return columns.map((column: IColumns, index: number) => {
|
||||
return (
|
||||
<TableCell
|
||||
key={`tbRE-${column.elementKey}-${index}`}
|
||||
className={`${column.rowClass} ${
|
||||
isSelected ? classes.rowSelected : classes.rowUnselected
|
||||
<Column
|
||||
key={`col-tb-${index.toString()}`}
|
||||
dataKey={column.elementKey}
|
||||
headerClassName={`titleHeader ${
|
||||
column.headerTextAlign ? `text-${column.headerTextAlign}` : ""
|
||||
}`}
|
||||
>
|
||||
{renderElement}
|
||||
</TableCell>
|
||||
headerRenderer={() => <React.Fragment>{column.label}</React.Fragment>}
|
||||
className={
|
||||
column.contentTextAlign ? `text-${column.contentTextAlign}` : ""
|
||||
}
|
||||
cellRenderer={({ rowData }) => {
|
||||
const isSelected = selectedItems
|
||||
? selectedItems.includes(
|
||||
isString(rowData) ? rowData : rowData[idField]
|
||||
)
|
||||
: false;
|
||||
return subRenderFunction(rowData, column, isSelected);
|
||||
}}
|
||||
width={column.width || commonRestWidth}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
@@ -265,6 +332,22 @@ const elementActions = (
|
||||
});
|
||||
};
|
||||
|
||||
// Function to calculate the options column width according elements inside
|
||||
const calculateOptionsSize = (containerWidth: number, totalOptions: number) => {
|
||||
const minContainerSize = 80;
|
||||
const sizeOptions = totalOptions * 45;
|
||||
|
||||
if (sizeOptions < minContainerSize) {
|
||||
return minContainerSize;
|
||||
}
|
||||
|
||||
if (sizeOptions > containerWidth) {
|
||||
return containerWidth;
|
||||
}
|
||||
|
||||
return sizeOptions;
|
||||
};
|
||||
|
||||
// Main function to render the Table Wrapper
|
||||
const TableWrapper = ({
|
||||
itemActions,
|
||||
@@ -276,10 +359,9 @@ const TableWrapper = ({
|
||||
selectedItems,
|
||||
idField,
|
||||
classes,
|
||||
stickyHeader = false,
|
||||
radioSelection = false,
|
||||
customEmptyMessage = "",
|
||||
paginatorConfig,
|
||||
customPaperHeight = "",
|
||||
}: TableWrapperProps) => {
|
||||
const findView = itemActions
|
||||
? itemActions.find((el) => el.type === "view")
|
||||
@@ -301,7 +383,13 @@ const TableWrapper = ({
|
||||
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
<Paper className={classes.paper}>
|
||||
<Paper
|
||||
className={`${classes.paper} ${
|
||||
customPaperHeight !== ""
|
||||
? customPaperHeight
|
||||
: classes.defaultPaperHeight
|
||||
}`}
|
||||
>
|
||||
{isLoading && (
|
||||
<Grid container className={classes.loadingBox}>
|
||||
<Grid item xs={12} style={{ textAlign: "center" }}>
|
||||
@@ -313,105 +401,133 @@ const TableWrapper = ({
|
||||
</Grid>
|
||||
)}
|
||||
{records && !isLoading && records.length > 0 ? (
|
||||
<Table
|
||||
size="small"
|
||||
stickyHeader={stickyHeader}
|
||||
className={classes.allTableSettings}
|
||||
>
|
||||
<TableHead className={classes.minTableHeader}>
|
||||
<TableRow>
|
||||
{onSelect && selectedItems && (
|
||||
<TableCell align="center" className={classes.checkBoxHeader}>
|
||||
Select
|
||||
</TableCell>
|
||||
)}
|
||||
{titleColumnsMap(columns)}
|
||||
{((itemActions && itemActions.length > 1) ||
|
||||
(itemActions &&
|
||||
itemActions.length === 1 &&
|
||||
itemActions[0].type !== "view")) && (
|
||||
<TableCell
|
||||
align="center"
|
||||
className={classes.actionsContainer}
|
||||
>
|
||||
Actions
|
||||
</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{records.map((record: any, index: number) => {
|
||||
const isSelected = selectedItems
|
||||
? selectedItems.includes(
|
||||
isString(record) ? record : record[idField]
|
||||
)
|
||||
: false;
|
||||
<AutoSizer>
|
||||
{({ width, height }: any) => {
|
||||
const optionsWidth = calculateOptionsSize(
|
||||
width,
|
||||
itemActions
|
||||
? itemActions.filter((el) => el.type !== "view").length
|
||||
: 0
|
||||
);
|
||||
const hasSelect: boolean = !!(onSelect && selectedItems);
|
||||
const hasOptions: boolean = !!(
|
||||
(itemActions && itemActions.length > 1) ||
|
||||
(itemActions &&
|
||||
itemActions.length === 1 &&
|
||||
itemActions[0].type !== "view")
|
||||
);
|
||||
return (
|
||||
<Table
|
||||
ref="Table"
|
||||
disableHeader={false}
|
||||
headerClassName={"headerItem"}
|
||||
headerHeight={40}
|
||||
height={height}
|
||||
noRowsRenderer={() => (
|
||||
<React.Fragment>
|
||||
{customEmptyMessage !== ""
|
||||
? customEmptyMessage
|
||||
: `There are no ${entityName} yet.`}
|
||||
</React.Fragment>
|
||||
)}
|
||||
overscanRowCount={10}
|
||||
rowHeight={40}
|
||||
width={width}
|
||||
rowCount={records.length}
|
||||
rowGetter={({ index }) => records[index]}
|
||||
onRowClick={({ rowData }) => {
|
||||
clickAction(rowData);
|
||||
}}
|
||||
rowClassName={`rowLine ${findView ? "canClick" : ""}`}
|
||||
>
|
||||
{hasSelect && (
|
||||
<Column
|
||||
headerRenderer={() => (
|
||||
<React.Fragment>Select</React.Fragment>
|
||||
)}
|
||||
dataKey={idField}
|
||||
width={selectWidth}
|
||||
cellRenderer={({ rowData }) => {
|
||||
const isSelected = selectedItems
|
||||
? selectedItems.includes(
|
||||
isString(rowData) ? rowData : rowData[idField]
|
||||
)
|
||||
: false;
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
key={`tb-${entityName}-${index.toString()}`}
|
||||
className={`${findView ? classes.rowClickable : ""} ${
|
||||
classes.rowElement
|
||||
} rowElementRaw`}
|
||||
onClick={() => {
|
||||
clickAction(record);
|
||||
}}
|
||||
>
|
||||
{onSelect && selectedItems && (
|
||||
<TableCell align="center" className={classes.checkBoxRow}>
|
||||
<Checkbox
|
||||
value={isString(record) ? record : record[idField]}
|
||||
color="primary"
|
||||
inputProps={{ "aria-label": "secondary checkbox" }}
|
||||
checked={isSelected}
|
||||
onChange={onSelect}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
checkedIcon={
|
||||
<span
|
||||
className={
|
||||
radioSelection
|
||||
? classes.radioSelectedIcon
|
||||
: classes.checkedIcon
|
||||
}
|
||||
/>
|
||||
}
|
||||
icon={
|
||||
<span
|
||||
className={
|
||||
radioSelection
|
||||
? classes.radioUnselectedIcon
|
||||
: classes.unCheckedIcon
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
)}
|
||||
{rowColumnsMap(columns, record, classes, isSelected)}
|
||||
{((itemActions && itemActions.length > 1) ||
|
||||
(itemActions &&
|
||||
itemActions.length === 1 &&
|
||||
itemActions[0].type !== "view")) && (
|
||||
<TableCell
|
||||
align="center"
|
||||
className={classes.actionsContainer}
|
||||
>
|
||||
{elementActions(
|
||||
itemActions,
|
||||
record,
|
||||
return (
|
||||
<Checkbox
|
||||
value={
|
||||
isString(rowData) ? rowData : rowData[idField]
|
||||
}
|
||||
color="primary"
|
||||
inputProps={{
|
||||
"aria-label": "secondary checkbox",
|
||||
}}
|
||||
checked={isSelected}
|
||||
onChange={onSelect}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
checkedIcon={
|
||||
<span
|
||||
className={
|
||||
radioSelection
|
||||
? classes.radioSelectedIcon
|
||||
: classes.checkedIcon
|
||||
}
|
||||
/>
|
||||
}
|
||||
icon={
|
||||
<span
|
||||
className={
|
||||
radioSelection
|
||||
? classes.radioUnselectedIcon
|
||||
: classes.unCheckedIcon
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{generateColumnsMap(
|
||||
columns,
|
||||
width,
|
||||
optionsWidth,
|
||||
hasSelect,
|
||||
hasOptions,
|
||||
selectedItems || [],
|
||||
idField
|
||||
)}
|
||||
{hasOptions && (
|
||||
<Column
|
||||
headerRenderer={() => (
|
||||
<React.Fragment>Options</React.Fragment>
|
||||
)}
|
||||
dataKey={idField}
|
||||
width={optionsWidth}
|
||||
headerClassName="optionsAlignment"
|
||||
className="optionsAlignment"
|
||||
cellRenderer={({ rowData }) => {
|
||||
const isSelected = selectedItems
|
||||
? selectedItems.includes(
|
||||
isString(rowData) ? rowData : rowData[idField]
|
||||
)
|
||||
: false;
|
||||
return elementActions(
|
||||
itemActions || [],
|
||||
rowData,
|
||||
isSelected,
|
||||
idField
|
||||
)}
|
||||
</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Table>
|
||||
);
|
||||
}}
|
||||
</AutoSizer>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
{!isLoading && (
|
||||
@@ -424,20 +540,6 @@ const TableWrapper = ({
|
||||
</React.Fragment>
|
||||
)}
|
||||
</Paper>
|
||||
{paginatorConfig && (
|
||||
<Grid item xs={12} className={classes.paginatorContainer}>
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TablePagination
|
||||
{...paginatorConfig}
|
||||
className={classes.paginatorComponent}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -100,7 +100,7 @@ const ConfTargetGeneric = ({
|
||||
|
||||
return (
|
||||
<FormSwitchWrapper
|
||||
indicatorLabel="On"
|
||||
indicatorLabels={["On", "Off"]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.checked ? "true" : "false";
|
||||
setValueElement(field.name, value, item);
|
||||
|
||||
@@ -143,7 +143,7 @@ const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => {
|
||||
name="checkedB"
|
||||
onChange={switcherChangeEvt}
|
||||
value={"dnsString"}
|
||||
indicatorLabel={"On"}
|
||||
indicatorLabels={["On", "Off"]}
|
||||
/>
|
||||
</Grid>
|
||||
{useDsnString ? (
|
||||
|
||||
@@ -216,7 +216,7 @@ const ConfPostgres = ({ onChange, classes }: IConfPostgresProps) => {
|
||||
setUseConnectionString(e.target.checked);
|
||||
}}
|
||||
value={"manualString"}
|
||||
indicatorLabel={"On"}
|
||||
indicatorLabels={["On", "Off"]}
|
||||
/>
|
||||
</Grid>
|
||||
{useConnectionString ? (
|
||||
|
||||
@@ -46,11 +46,11 @@ import Heal from "./Heal/Heal";
|
||||
import Watch from "./Watch/Watch";
|
||||
import ListTenants from "./Tenants/ListTenants/ListTenants";
|
||||
import { ISessionResponse } from "./types";
|
||||
import { saveSessionResponse } from "./actions";
|
||||
import TenantDetails from "./Tenants/TenantDetails/TenantDetails";
|
||||
import { clearSession } from "../../common/utils";
|
||||
import ObjectBrowser from "./ObjectBrowser/ObjectBrowser";
|
||||
import ListObjects from "./Buckets/ListBuckets/Objects/ListObjects/ListObjects";
|
||||
import ObjectDetails from "./Buckets/ListBuckets/Objects/ObjectDetails/ObjectDetails";
|
||||
import ObjectRouting from "./Buckets/ListBuckets/Objects/ListObjects/ObjectRouting";
|
||||
import License from "./License/License";
|
||||
|
||||
const drawerWidth = 245;
|
||||
@@ -160,7 +160,6 @@ interface IConsoleProps {
|
||||
setMenuOpen: typeof setMenuOpen;
|
||||
serverNeedsRestart: typeof serverNeedsRestart;
|
||||
serverIsLoading: typeof serverIsLoading;
|
||||
saveSessionResponse: typeof saveSessionResponse;
|
||||
session: ISessionResponse;
|
||||
}
|
||||
|
||||
@@ -171,24 +170,8 @@ const Console = ({
|
||||
isServerLoading,
|
||||
serverNeedsRestart,
|
||||
serverIsLoading,
|
||||
saveSessionResponse,
|
||||
session,
|
||||
}: IConsoleProps) => {
|
||||
useEffect(() => {
|
||||
api
|
||||
.invoke("GET", `/api/v1/session`)
|
||||
.then((res) => {
|
||||
saveSessionResponse(res);
|
||||
})
|
||||
.catch(() => {
|
||||
// if server returns 401 for /api/v1/session call invoke function will internally call clearSession()
|
||||
// and redirecto to window.location.href = "/"; and this code will be not reached
|
||||
// in case that not happen we clear session here and redirect as well
|
||||
clearSession();
|
||||
window.location.href = "/login";
|
||||
});
|
||||
}, [saveSessionResponse]);
|
||||
|
||||
const restartServer = () => {
|
||||
serverIsLoading(true);
|
||||
api
|
||||
@@ -231,11 +214,11 @@ const Console = ({
|
||||
path: "/object-browser",
|
||||
},
|
||||
{
|
||||
component: ListObjects,
|
||||
component: ObjectRouting,
|
||||
path: "/object-browser/:bucket",
|
||||
},
|
||||
{
|
||||
component: ListObjects,
|
||||
component: ObjectRouting,
|
||||
path: "/object-browser/:bucket/*",
|
||||
},
|
||||
{
|
||||
@@ -375,7 +358,6 @@ const connector = connect(mapState, {
|
||||
setMenuOpen,
|
||||
serverNeedsRestart,
|
||||
serverIsLoading,
|
||||
saveSessionResponse,
|
||||
});
|
||||
|
||||
export default connector(withStyles(styles)(Console));
|
||||
|
||||
@@ -179,7 +179,7 @@ const AddGroup = ({
|
||||
{selectedGroup !== null && (
|
||||
<div className={classes.floatingEnabled}>
|
||||
<FormSwitchWrapper
|
||||
indicatorLabel={"Enabled"}
|
||||
indicatorLabels={["Enabled", "Disabled"]}
|
||||
checked={groupEnabled}
|
||||
value={"group_enabled"}
|
||||
id="group-status"
|
||||
|
||||
@@ -257,20 +257,6 @@ const Groups = ({ classes }: IGroupsProps) => {
|
||||
records={filteredRecords}
|
||||
entityName="Groups"
|
||||
idField=""
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: totalRecords,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -27,7 +27,10 @@ import TextField from "@material-ui/core/TextField";
|
||||
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||
import SearchIcon from "@material-ui/icons/Search";
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
actionsTray,
|
||||
selectorsCommon,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
interface IGroupsProps {
|
||||
classes: any;
|
||||
@@ -102,6 +105,7 @@ const styles = (theme: Theme) =>
|
||||
},
|
||||
},
|
||||
...actionsTray,
|
||||
...selectorsCommon,
|
||||
});
|
||||
|
||||
const UsersSelectors = ({
|
||||
@@ -211,6 +215,7 @@ const UsersSelectors = ({
|
||||
records={filteredRecords}
|
||||
entityName="Users"
|
||||
idField="accessKey"
|
||||
customPaperHeight={classes.multiSelectTable}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -205,27 +205,6 @@ const ListNotificationEndpoints = ({ classes }: IListNotificationEndpoints) => {
|
||||
records={filteredRecords}
|
||||
entityName="Notification Endpoints"
|
||||
idField="service_name"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: totalRecords,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: (event: unknown, newPage: number) => {
|
||||
setPage(newPage);
|
||||
},
|
||||
onChangeRowsPerPage: (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
const rPP = parseInt(event.target.value, 10);
|
||||
setRowsPerPage(rPP);
|
||||
},
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -90,10 +90,13 @@ const styles = (theme: Theme) =>
|
||||
marginRight: 10,
|
||||
},
|
||||
"@global": {
|
||||
".rowElementRaw:hover .iconBucketElm": {
|
||||
".rowLine:hover .iconBucketElm": {
|
||||
backgroundImage: "url(/images/ob_bucket_filled.svg)",
|
||||
},
|
||||
},
|
||||
browsePaper: {
|
||||
height: "calc(100vh - 280px)",
|
||||
},
|
||||
...actionsTray,
|
||||
...searchField,
|
||||
...objectBrowserCommon,
|
||||
@@ -101,7 +104,7 @@ const styles = (theme: Theme) =>
|
||||
|
||||
interface IBrowseBucketsProps {
|
||||
classes: any;
|
||||
addRoute: (path: string, label: string) => any;
|
||||
addRoute: (path: string, label: string, type: string) => any;
|
||||
resetRoutesList: (doVar: boolean) => any;
|
||||
match: any;
|
||||
}
|
||||
@@ -131,10 +134,8 @@ const BrowseBuckets = ({
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets?offset=${offset}&limit=${rowsPerPage}`)
|
||||
.then((res: BucketList) => {
|
||||
const buckets = get(res, "buckets", []);
|
||||
|
||||
setLoading(false);
|
||||
setRecords(buckets);
|
||||
setRecords(res.buckets || []);
|
||||
setError("");
|
||||
// if we get 0 results, and page > 0 , go down 1 page
|
||||
if (
|
||||
@@ -170,8 +171,6 @@ const BrowseBuckets = ({
|
||||
return b.name.indexOf(filterBuckets) >= 0;
|
||||
});
|
||||
|
||||
const showInPage = filteredRecords.slice(offset, offset + rowsPerPage);
|
||||
|
||||
const handleChangePage = (event: unknown, newPage: number) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
@@ -188,7 +187,7 @@ const BrowseBuckets = ({
|
||||
const currentPath = get(match, "url", "/object-browser");
|
||||
const newPath = `${currentPath}/${idElement}`;
|
||||
|
||||
addRoute(newPath, idElement);
|
||||
addRoute(newPath, idElement, "path");
|
||||
};
|
||||
|
||||
const renderBucket = (bucketName: string) => {
|
||||
@@ -270,26 +269,16 @@ const BrowseBuckets = ({
|
||||
renderFunction: niceBytes,
|
||||
globalClass: classes.usedSpaceCol,
|
||||
rowClass: classes.usedSpaceCol,
|
||||
width: 100,
|
||||
contentTextAlign: "right",
|
||||
headerTextAlign: "right",
|
||||
},
|
||||
]}
|
||||
isLoading={loading}
|
||||
records={showInPage}
|
||||
records={filteredRecords}
|
||||
entityName="Buckets"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: filteredRecords.length,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
customPaperHeight={classes.browsePaper}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -21,11 +21,14 @@ export const OBJECT_BROWSER_REMOVE_ROUTE_LEVEL =
|
||||
"OBJECT_BROWSER/REMOVE_ROUTE_LEVEL";
|
||||
export const OBJECT_BROWSER_SET_ALL_ROUTES = "OBJECT_BROWSER/SET_ALL_ROUTES";
|
||||
export const OBJECT_BROWSER_CREATE_FOLDER = "OBJECT_BROWSER/CREATE_FOLDER";
|
||||
export const OBJECT_BROWSER_SET_LAST_AS_FILE =
|
||||
"OBJECT_BROWSER/SET_LAST_AS_FILE";
|
||||
|
||||
interface AddRouteAction {
|
||||
type: typeof OBJECT_BROWSER_ADD_ROUTE;
|
||||
route: string;
|
||||
label: string;
|
||||
routeType: string;
|
||||
}
|
||||
|
||||
interface ResetRoutesList {
|
||||
@@ -48,23 +51,28 @@ interface CreateFolder {
|
||||
newRoute: string;
|
||||
}
|
||||
|
||||
interface SetLastAsFile {
|
||||
type: typeof OBJECT_BROWSER_SET_LAST_AS_FILE;
|
||||
}
|
||||
|
||||
export type ObjectBrowserActionTypes =
|
||||
| AddRouteAction
|
||||
| ResetRoutesList
|
||||
| RemoveRouteLevel
|
||||
| SetAllRoutes
|
||||
| CreateFolder;
|
||||
| CreateFolder
|
||||
| SetLastAsFile;
|
||||
|
||||
export const addRoute = (route: string, label: string) => {
|
||||
export const addRoute = (route: string, label: string, routeType: string) => {
|
||||
return {
|
||||
type: OBJECT_BROWSER_ADD_ROUTE,
|
||||
route,
|
||||
label,
|
||||
routeType,
|
||||
};
|
||||
};
|
||||
|
||||
export const resetRoutesList = (reset: boolean) => {
|
||||
console.log("RESET");
|
||||
return {
|
||||
type: OBJECT_BROWSER_RESET_ROUTES_LIST,
|
||||
reset,
|
||||
@@ -91,3 +99,9 @@ export const createFolder = (newRoute: string) => {
|
||||
newRoute,
|
||||
};
|
||||
};
|
||||
|
||||
export const setLastAsFile = () => {
|
||||
return {
|
||||
type: OBJECT_BROWSER_SET_LAST_AS_FILE,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -21,19 +21,23 @@ import {
|
||||
OBJECT_BROWSER_REMOVE_ROUTE_LEVEL,
|
||||
OBJECT_BROWSER_RESET_ROUTES_LIST,
|
||||
OBJECT_BROWSER_SET_ALL_ROUTES,
|
||||
OBJECT_BROWSER_SET_LAST_AS_FILE,
|
||||
ObjectBrowserActionTypes,
|
||||
} from "./actions";
|
||||
|
||||
export interface Route {
|
||||
route: string;
|
||||
label: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface ObjectBrowserState {
|
||||
routesList: Route[];
|
||||
}
|
||||
|
||||
const initialRoute = [{ route: "/object-browser", label: "All Buckets" }];
|
||||
const initialRoute = [
|
||||
{ route: "/object-browser", label: "All Buckets", type: "path" },
|
||||
];
|
||||
|
||||
const initialState: ObjectBrowserState = {
|
||||
routesList: initialRoute,
|
||||
@@ -47,7 +51,7 @@ export function objectBrowserReducer(
|
||||
case OBJECT_BROWSER_ADD_ROUTE:
|
||||
const newRouteList = [
|
||||
...state.routesList,
|
||||
{ route: action.route, label: action.label },
|
||||
{ route: action.route, label: action.label, type: action.routeType },
|
||||
];
|
||||
history.push(action.route);
|
||||
|
||||
@@ -76,7 +80,12 @@ export function objectBrowserReducer(
|
||||
splitRoutes.forEach((route) => {
|
||||
if (route !== "" && route !== "object-browser") {
|
||||
initRoute = `${initRoute}/${route}`;
|
||||
routesArray.push({ route: initRoute, label: route });
|
||||
|
||||
routesArray.push({
|
||||
route: initRoute,
|
||||
label: route,
|
||||
type: "path",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -97,7 +106,7 @@ export function objectBrowserReducer(
|
||||
if (folderTrim !== "") {
|
||||
lastRoute = `${lastRoute}/${folderTrim}`;
|
||||
|
||||
const newItem = { route: lastRoute, label: folderTrim };
|
||||
const newItem = { route: lastRoute, label: folderTrim, type: "path" };
|
||||
newFoldersRoutes.push(newItem);
|
||||
}
|
||||
});
|
||||
@@ -108,6 +117,20 @@ export function objectBrowserReducer(
|
||||
...state,
|
||||
routesList: newFoldersRoutes,
|
||||
};
|
||||
case OBJECT_BROWSER_SET_LAST_AS_FILE:
|
||||
const currentList = state.routesList;
|
||||
const lastItem = currentList.slice(-1)[0];
|
||||
|
||||
if (lastItem.type === "path") {
|
||||
lastItem.type = "file";
|
||||
}
|
||||
|
||||
const newList = [...currentList.slice(0, -1), lastItem];
|
||||
|
||||
return {
|
||||
...state,
|
||||
routesList: newList,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -257,20 +257,6 @@ const Policies = ({ classes }: IPoliciesProps) => {
|
||||
records={paginatedRecords}
|
||||
entityName="Policies"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: filteredRecords.length,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -25,7 +25,10 @@ import TextField from "@material-ui/core/TextField";
|
||||
import api from "../../../common/api";
|
||||
import { policySort } from "../../../utils/sortFunctions";
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
actionsTray,
|
||||
selectorsCommon,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import { PolicyList } from "./types";
|
||||
|
||||
interface ISelectPolicyProps {
|
||||
@@ -100,6 +103,7 @@ const styles = (theme: Theme) =>
|
||||
},
|
||||
},
|
||||
...actionsTray,
|
||||
...selectorsCommon,
|
||||
});
|
||||
|
||||
const PolicySelectors = ({
|
||||
@@ -188,6 +192,7 @@ const PolicySelectors = ({
|
||||
records={filteredRecords}
|
||||
entityName="Policies"
|
||||
idField="name"
|
||||
customPaperHeight={classes.multiSelectTable}
|
||||
radioSelection
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
@@ -278,20 +278,6 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
|
||||
idField={""}
|
||||
columns={[{ label: "Service Account", elementKey: "" }]}
|
||||
itemActions={tableActions}
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 4,
|
||||
count: records.length,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -913,8 +913,6 @@ const AddTenant = ({
|
||||
.invoke("POST", `/api/v1/tenants`, dataSend)
|
||||
.then((res) => {
|
||||
const newSrvAcc: NewServiceAccount = {
|
||||
accessKey: res.access_key,
|
||||
secretKey: res.secret_key,
|
||||
console: {
|
||||
accessKey: res.console.access_key,
|
||||
secretKey: res.console.secret_key,
|
||||
|
||||
@@ -301,20 +301,6 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
records={filteredRecords}
|
||||
entityName="Tenants"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: filteredRecords.length,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
containerForHeader,
|
||||
modalBasic,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import { Button } from "@material-ui/core";
|
||||
@@ -34,6 +37,7 @@ import api from "../../../../common/api";
|
||||
import { ITenant, IZone } from "../ListTenants/types";
|
||||
import Logs from "./Logs/Logs";
|
||||
import Trace from "./Trace/Trace";
|
||||
import PageHeader from "../../Common/PageHeader/PageHeader";
|
||||
|
||||
interface ITenantDetailsProps {
|
||||
classes: any;
|
||||
@@ -90,13 +94,14 @@ const styles = (theme: Theme) =>
|
||||
textAlign: "right",
|
||||
},
|
||||
...modalBasic,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||
const [capacity, setCapacity] = useState<number>(0);
|
||||
const [zoneCount, setZoneCount] = useState<number>(0);
|
||||
const [zones, setZones] = useState<IZone[]>([]);
|
||||
const [serverSets, setServerSets] = useState<IZone[]>([]);
|
||||
const [instances, setInstances] = useState<number>(0);
|
||||
const [volumes, setVolumes] = useState<number>(0);
|
||||
const [addZoneOpen, setAddZone] = useState<boolean>(false);
|
||||
@@ -157,7 +162,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
setVolumes(totalVolumes);
|
||||
setInstances(totalInstances);
|
||||
|
||||
setZones(resZones);
|
||||
setServerSets(resZones);
|
||||
|
||||
setTenant(res);
|
||||
setError("");
|
||||
@@ -193,12 +198,9 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
closeModalAndRefresh={closeReplicationAndRefresh}
|
||||
/>
|
||||
)}
|
||||
<PageHeader label={`Tenant > ${match.params["tenantName"]}`} />
|
||||
<Grid item xs={12} className={classes.container} />
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6">
|
||||
{`Tenant > ${match.params["tenantName"]}`}
|
||||
</Typography>
|
||||
</Grid>
|
||||
{error !== "" && (
|
||||
<Grid item xs={12}>
|
||||
{error}
|
||||
@@ -214,7 +216,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
<div>{niceBytes(capacity.toString(10))}</div>
|
||||
<div>Minio:</div>
|
||||
<div>{tenant ? tenant.image : ""}</div>
|
||||
<div>Zones:</div>
|
||||
<div>Clusters:</div>
|
||||
<div>{zoneCount}</div>
|
||||
<div>Console:</div>
|
||||
<div>{tenant ? tenant.console_image : ""}</div>
|
||||
@@ -238,7 +240,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
}}
|
||||
aria-label="tenant-tabs"
|
||||
>
|
||||
<Tab label="Zones" />
|
||||
<Tab label="Clusters" />
|
||||
<Tab label="Logs" />
|
||||
<Tab label="Trace" />
|
||||
</Tabs>
|
||||
@@ -252,7 +254,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
setAddZone(true);
|
||||
}}
|
||||
>
|
||||
Add Zone
|
||||
Expand Tenant
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
@@ -277,23 +279,9 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
{ label: "# of Drives", elementKey: "volumes" },
|
||||
]}
|
||||
isLoading={false}
|
||||
records={zones}
|
||||
entityName="Zones"
|
||||
records={serverSets}
|
||||
entityName="Servers"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: zoneCount,
|
||||
rowsPerPage: 10,
|
||||
page: 0,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
onChangePage: () => {},
|
||||
onChangeRowsPerPage: () => {},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
@@ -24,7 +24,6 @@ import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { niceBytes, timeFromDate } from "../../../../../common/utils";
|
||||
import { wsProtocol } from "../../../../../utils/wsUtils";
|
||||
import { containerForHeader } from "../../../Common/FormComponents/common/styleLibrary";
|
||||
import PageHeader from "../../../Common/PageHeader/PageHeader";
|
||||
import { Grid } from "@material-ui/core";
|
||||
import TableWrapper from "../../../Common/TableWrapper/TableWrapper";
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ class AddUserContent extends React.Component<
|
||||
{selectedUser !== null && (
|
||||
<div className={classes.floatingEnabled}>
|
||||
<FormSwitchWrapper
|
||||
indicatorLabel={"Enabled"}
|
||||
indicatorLabels={["Enabled", "Disabled"]}
|
||||
checked={enabled}
|
||||
value={"user_enabled"}
|
||||
id="user-status"
|
||||
|
||||
@@ -27,7 +27,10 @@ import { stringSort } from "../../../utils/sortFunctions";
|
||||
import { GroupsList } from "../Groups/types";
|
||||
import get from "lodash/get";
|
||||
import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
actionsTray,
|
||||
selectorsCommon,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
interface IGroupsProps {
|
||||
classes: any;
|
||||
@@ -101,6 +104,7 @@ const styles = (theme: Theme) =>
|
||||
},
|
||||
},
|
||||
...actionsTray,
|
||||
...selectorsCommon,
|
||||
});
|
||||
|
||||
const GroupsSelectors = ({
|
||||
@@ -205,6 +209,7 @@ const GroupsSelectors = ({
|
||||
records={filteredRecords}
|
||||
entityName="Groups"
|
||||
idField=""
|
||||
customPaperHeight={classes.multiSelectTable}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -361,20 +361,6 @@ class Users extends React.Component<IUsersProps, IUsersState> {
|
||||
records={paginatedRecords}
|
||||
entityName="Users"
|
||||
idField="accessKey"
|
||||
paginatorConfig={{
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: filteredRecords.length,
|
||||
rowsPerPage: rowsPerPage,
|
||||
page: page,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
onChangePage: handleChangePage,
|
||||
onChangeRowsPerPage: handleChangeRowsPerPage,
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -38,9 +38,7 @@ import { SystemState } from "../../types";
|
||||
import { userLoggedIn } from "../../actions";
|
||||
import api from "../../common/api";
|
||||
import { ILoginDetails, loginStrategyType } from "./types";
|
||||
import { setSession } from "../../common/utils";
|
||||
import history from "../../history";
|
||||
import { isBoolean } from "util";
|
||||
import { OutlinedInputProps } from "@material-ui/core/OutlinedInput";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -226,10 +224,7 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
|
||||
.send(loginStrategyPayload[loginStrategy.loginStrategy])
|
||||
.then((res: any) => {
|
||||
const bodyResponse = res.body;
|
||||
if (bodyResponse.sessionId) {
|
||||
// store the jwt token
|
||||
setSession(bodyResponse.sessionId);
|
||||
} else if (bodyResponse.error) {
|
||||
if (bodyResponse.error) {
|
||||
setLoginSending(false);
|
||||
// throw will be moved to catch block once bad login returns 403
|
||||
throw bodyResponse.error;
|
||||
|
||||
@@ -1685,6 +1685,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
|
||||
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
|
||||
|
||||
"@types/react-copy-to-clipboard@^4.3.0":
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.3.0.tgz#8e07becb4f11cfced4bd36038cb5bdf5c2658be5"
|
||||
integrity sha512-iideNPRyroENqsOFh1i2Dv3zkviYS9r/9qD9Uh3Z9NNoAAqqa2x53i7iGndGNnJFIo20wIu7Hgh77tx1io8bgw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@16.9.4":
|
||||
version "16.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.4.tgz#0b58df09a60961dcb77f62d4f1832427513420df"
|
||||
@@ -1726,6 +1733,14 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-virtualized@^9.21.10":
|
||||
version "9.21.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.10.tgz#cd072dc9c889291ace2c4c9de8e8c050da8738b7"
|
||||
integrity sha512-f5Ti3A7gGdLkPPFNHTrvKblpsPNBiQoSorOEOD+JPx72g/Ng2lOt4MYfhvQFQNgyIrAro+Z643jbcKafsMW2ag==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*":
|
||||
version "16.9.53"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23"
|
||||
@@ -3368,6 +3383,13 @@ copy-descriptor@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
||||
|
||||
copy-to-clipboard@^3:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
|
||||
integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==
|
||||
dependencies:
|
||||
toggle-selection "^1.0.6"
|
||||
|
||||
core-js-compat@^3.6.2:
|
||||
version "3.6.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c"
|
||||
@@ -4038,7 +4060,7 @@ dom-helpers@^3.4.0:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.1.2"
|
||||
|
||||
dom-helpers@^5.0.1:
|
||||
dom-helpers@^5.0.1, dom-helpers@^5.1.3:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b"
|
||||
integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==
|
||||
@@ -8875,7 +8897,7 @@ prompts@^2.0.1:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.4"
|
||||
|
||||
prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@@ -9076,6 +9098,14 @@ react-codemirror2@^7.1.0:
|
||||
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-7.2.1.tgz#38dab492fcbe5fb8ebf5630e5bb7922db8d3a10c"
|
||||
integrity sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==
|
||||
|
||||
react-copy-to-clipboard@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz#d82a437e081e68dfca3761fbd57dbf2abdda1316"
|
||||
integrity sha512-/2t5mLMMPuN5GmdXo6TebFa8IoFxZ+KTDDqYhcDm0PhkgEzSxVvIX26G20s1EB02A4h2UZgwtfymZ3lGJm0OLg==
|
||||
dependencies:
|
||||
copy-to-clipboard "^3"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-dev-utils@^10.2.1:
|
||||
version "10.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-10.2.1.tgz#f6de325ae25fa4d546d09df4bb1befdc6dd19c19"
|
||||
@@ -9290,6 +9320,23 @@ react-transition-group@^4.4.0:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react-virtualized@^9.22.2:
|
||||
version "9.22.2"
|
||||
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.2.tgz#217a870bad91e5438f46f01a009e1d8ce1060a5a"
|
||||
integrity sha512-5j4h4FhxTdOpBKtePSs1yk6LDNT4oGtUwjT7Nkh61Z8vv3fTG/XeOf8J4li1AYaexOwTXnw0HFVxsV0GBUqwRw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.2"
|
||||
clsx "^1.0.4"
|
||||
dom-helpers "^5.1.3"
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.7.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react-window-infinite-loader@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/react-window-infinite-loader/-/react-window-infinite-loader-1.0.5.tgz#6fe094d538a88978c2c9b623052bc50cb28c2abc"
|
||||
integrity sha512-IcPIq8lADK3zsAcqoLqQGyduicqR6jWkiK2VUX5sKSI9X/rou6OWlOEexnGyujdNTG7hSG8OVBFEhLSDs4qrxg==
|
||||
|
||||
react@^16.13.1:
|
||||
version "16.14.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
|
||||
@@ -10736,6 +10783,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
|
||||
regex-not "^1.0.2"
|
||||
safe-regex "^1.1.0"
|
||||
|
||||
toggle-selection@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
|
||||
integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
|
||||
|
||||
toidentifier@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
|
||||
@@ -249,7 +249,13 @@ func getTenantAdminClient(ctx context.Context, client K8sClientI, tenant *operat
|
||||
log.Println("tenant's secret doesn't contain secretkey")
|
||||
return nil, errorGeneric
|
||||
}
|
||||
mAdmin, pErr := NewAdminClientWithInsecure(svcURL, string(accessKey), string(secretkey), insecure)
|
||||
// TODO:
|
||||
// We need to avoid using minio root credentials to talk to tenants, and instead use a different user credentials
|
||||
// when that its implemented we also need to check here if the tenant has LDAP enabled so we authenticate first against AD
|
||||
tenantAccessKey := string(accessKey)
|
||||
tenantSecretKey := string(secretkey)
|
||||
sessionToken := ""
|
||||
mAdmin, pErr := NewAdminClientWithInsecure(svcURL, tenantAccessKey, tenantSecretKey, sessionToken, insecure)
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
}
|
||||
@@ -681,7 +687,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
return nil, prepareError(errorGeneric)
|
||||
}
|
||||
|
||||
const consoleVersion = "minio/console:v0.4.4"
|
||||
const consoleVersion = "minio/console:v0.4.6"
|
||||
minInst.Spec.Console = &operator.ConsoleConfiguration{
|
||||
Replicas: 1,
|
||||
Image: consoleVersion,
|
||||
@@ -778,10 +784,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
}
|
||||
response = &models.CreateTenantResponse{
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
}
|
||||
response = &models.CreateTenantResponse{}
|
||||
// Attach Console Credentials
|
||||
if enableConsole {
|
||||
response.Console = &models.CreateTenantResponseConsole{
|
||||
|
||||
@@ -1016,7 +1016,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Body: &models.UpdateTenantRequest{
|
||||
ConsoleImage: "minio/console:v0.4.4",
|
||||
ConsoleImage: "minio/console:v0.4.6",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -19,10 +19,13 @@ package restapi
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/pkg/auth"
|
||||
"github.com/minio/console/pkg/auth/ldap"
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
"github.com/minio/mc/pkg/probe"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
@@ -34,22 +37,22 @@ import (
|
||||
const globalAppName = "console"
|
||||
|
||||
// NewAdminClient gives a new madmin client interface
|
||||
func NewAdminClient(url, accessKey, secretKey string) (*madmin.AdminClient, *probe.Error) {
|
||||
return NewAdminClientWithInsecure(url, accessKey, secretKey, false)
|
||||
func NewAdminClient(url, accessKey, secretKey, sessionToken string) (*madmin.AdminClient, *probe.Error) {
|
||||
return NewAdminClientWithInsecure(url, accessKey, secretKey, sessionToken, false)
|
||||
}
|
||||
|
||||
// NewAdminClientWithInsecure gives a new madmin client interface either secure or insecure based on parameter
|
||||
func NewAdminClientWithInsecure(url, accessKey, secretKey string, insecure bool) (*madmin.AdminClient, *probe.Error) {
|
||||
func NewAdminClientWithInsecure(url, accessKey, secretKey, sessionToken string, insecure bool) (*madmin.AdminClient, *probe.Error) {
|
||||
appName := filepath.Base(globalAppName)
|
||||
|
||||
s3Client, err := s3AdminNew(&mcCmd.Config{
|
||||
HostURL: url,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
AppName: appName,
|
||||
AppVersion: ConsoleVersion,
|
||||
AppComments: []string{appName, runtime.GOOS, runtime.GOARCH},
|
||||
Insecure: insecure,
|
||||
HostURL: url,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
SessionToken: sessionToken,
|
||||
AppName: appName,
|
||||
AppVersion: ConsoleVersion,
|
||||
AppComments: []string{appName, runtime.GOOS, runtime.GOARCH},
|
||||
Insecure: insecure,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err.Trace(url)
|
||||
@@ -304,16 +307,54 @@ func newAdminFromClaims(claims *models.Principal) (*madmin.AdminClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stsClient := PrepareSTSClient(false)
|
||||
adminClient.SetCustomTransport(stsClient.Transport)
|
||||
adminClient.SetCustomTransport(GetConsoleSTSClient().Transport)
|
||||
return adminClient, nil
|
||||
}
|
||||
|
||||
var (
|
||||
consoleAccessKey = getAccessKey()
|
||||
consoleSecretKey = getSecretKey()
|
||||
)
|
||||
|
||||
// stsClient is a custom http client, this client should not be called directly and instead be
|
||||
// called using GetConsoleSTSClient() to ensure is initialized and the certificates are loaded correctly
|
||||
var stsClient *http.Client
|
||||
|
||||
// GetConsoleSTSClient will initialize the console STS Client with Custom TLS Transport that with loads certs at .console/certs/CAs
|
||||
func GetConsoleSTSClient() *http.Client {
|
||||
if stsClient == nil {
|
||||
stsClient = PrepareSTSClient(false)
|
||||
}
|
||||
return stsClient
|
||||
}
|
||||
|
||||
var consoleLDAPAdminCreds consoleCredentials
|
||||
|
||||
func newSuperMAdminClient() (*madmin.AdminClient, error) {
|
||||
endpoint := getMinIOServer()
|
||||
accessKeyID := getAccessKey()
|
||||
secretAccessKey := getSecretKey()
|
||||
adminClient, pErr := NewAdminClient(endpoint, accessKeyID, secretAccessKey)
|
||||
accessKey := consoleAccessKey
|
||||
secretKey := consoleSecretKey
|
||||
sessionToken := ""
|
||||
// If LDAP is enabled (External IDP) in minio, then obtain the session tokens associated with the super admin credentials
|
||||
// configured in console
|
||||
if ldap.GetLDAPEnabled() {
|
||||
// initialize LDAP super Admin Credentials once
|
||||
if consoleLDAPAdminCreds.consoleCredentials == nil {
|
||||
consoleCredentialsFromLDAP, err := auth.GetCredentialsFromLDAP(GetConsoleSTSClient(), MinioEndpoint, consoleAccessKey, consoleSecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
consoleLDAPAdminCreds = consoleCredentials{consoleCredentials: consoleCredentialsFromLDAP}
|
||||
}
|
||||
tokens, err := consoleLDAPAdminCreds.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accessKey = tokens.AccessKeyID
|
||||
secretKey = tokens.SecretAccessKey
|
||||
sessionToken = tokens.SessionToken
|
||||
}
|
||||
|
||||
adminClient, pErr := NewAdminClient(MinioEndpoint, accessKey, secretKey, sessionToken)
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
}
|
||||
|
||||
@@ -266,7 +266,6 @@ func (s consoleSTSAssumeRole) IsExpired() bool {
|
||||
return s.stsAssumeRole.IsExpired()
|
||||
}
|
||||
|
||||
// STSClient contains http.client configuration need it by STSAssumeRole
|
||||
var (
|
||||
MinioEndpoint = getMinIOServer()
|
||||
)
|
||||
@@ -289,7 +288,7 @@ func newConsoleCredentials(accessKey, secretKey, location string) (*credentials.
|
||||
if MinioEndpoint == "" {
|
||||
return nil, errors.New("endpoint cannot be empty for AssumeRoleSTS")
|
||||
}
|
||||
creds, err := auth.GetConsoleCredentialsFromLDAP(MinioEndpoint, accessKey, secretKey)
|
||||
creds, err := auth.GetCredentialsFromLDAP(GetConsoleSTSClient(), MinioEndpoint, accessKey, secretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -307,9 +306,8 @@ func newConsoleCredentials(accessKey, secretKey, location string) (*credentials.
|
||||
Location: location,
|
||||
DurationSeconds: xjwt.GetConsoleSTSDurationInSeconds(),
|
||||
}
|
||||
stsClient := PrepareSTSClient(false)
|
||||
stsAssumeRole := &credentials.STSAssumeRole{
|
||||
Client: stsClient,
|
||||
Client: GetConsoleSTSClient(),
|
||||
STSEndpoint: MinioEndpoint,
|
||||
Options: opts,
|
||||
}
|
||||
@@ -329,11 +327,10 @@ func getConsoleCredentialsFromSession(claims *models.Principal) *credentials.Cre
|
||||
// from the provided session token
|
||||
func newMinioClient(claims *models.Principal) (*minio.Client, error) {
|
||||
creds := getConsoleCredentialsFromSession(claims)
|
||||
stsClient := PrepareSTSClient(false)
|
||||
minioClient, err := minio.New(getMinIOEndpoint(), &minio.Options{
|
||||
Creds: creds,
|
||||
Secure: getMinIOEndpointIsSecure(),
|
||||
Transport: stsClient.Transport,
|
||||
Transport: GetConsoleSTSClient().Transport,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
@@ -41,6 +42,8 @@ var TLSPort = "9443"
|
||||
// TLSRedirect console tls redirect rule
|
||||
var TLSRedirect = "off"
|
||||
|
||||
var SessionDuration = 45 * time.Minute
|
||||
|
||||
func getAccessKey() string {
|
||||
return env.Get(ConsoleAccessKey, "minioadmin")
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package restapi
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -142,11 +143,13 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
|
||||
|
||||
// The TLS configuration before HTTPS server starts.
|
||||
func configureTLS(tlsConfig *tls.Config) {
|
||||
// Add the global public crts as part of global root CAs
|
||||
for _, publicCrt := range GlobalPublicCerts {
|
||||
GlobalRootCAs.AddCert(publicCrt)
|
||||
if GlobalRootCAs != nil {
|
||||
// Add the global public crts as part of global root CAs
|
||||
for _, publicCrt := range GlobalPublicCerts {
|
||||
GlobalRootCAs.AddCert(publicCrt)
|
||||
}
|
||||
tlsConfig.RootCAs = GlobalRootCAs
|
||||
}
|
||||
tlsConfig.RootCAs = GlobalRootCAs
|
||||
if GlobalTLSCertsManager != nil {
|
||||
tlsConfig.GetCertificate = GlobalTLSCertsManager.GetCertificate
|
||||
}
|
||||
@@ -168,8 +171,10 @@ func setupMiddlewares(handler http.Handler) http.Handler {
|
||||
// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
|
||||
// So this is a good place to plug in a panic handling middleware, logging and metrics
|
||||
func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||
// handle cookie or authorization header for session
|
||||
next := AuthenticationMiddleware(handler)
|
||||
// serve static files
|
||||
next := FileServerMiddleware(handler)
|
||||
next = FileServerMiddleware(next)
|
||||
// Secure middleware, this middleware wrap all the previous handlers and add
|
||||
// HTTP security headers
|
||||
secureOptions := secure.Options{
|
||||
@@ -200,6 +205,31 @@ func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||
return app
|
||||
}
|
||||
|
||||
func AuthenticationMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// prioritize authorization header and skip
|
||||
if r.Header.Get("Authorization") != "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
tokenCookie, err := r.Cookie("token")
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
currentTime := time.Now()
|
||||
if tokenCookie.Expires.After(currentTime) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
token := tokenCookie.Value
|
||||
if token != "" {
|
||||
r.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// FileServerMiddleware serves files from the static folder
|
||||
func FileServerMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -546,6 +546,12 @@ func init() {
|
||||
"name": "prefix",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "version_id",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3279,9 +3285,6 @@ func init() {
|
||||
"createTenantResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"console": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3292,9 +3295,6 @@ func init() {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"secret_key": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5412,6 +5412,12 @@ func init() {
|
||||
"name": "prefix",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "version_id",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -8668,9 +8674,6 @@ func init() {
|
||||
"createTenantResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"console": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -8681,9 +8684,6 @@ func init() {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"secret_key": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -58,6 +58,11 @@ type DownloadObjectParams struct {
|
||||
In: query
|
||||
*/
|
||||
Prefix string
|
||||
/*
|
||||
Required: true
|
||||
In: query
|
||||
*/
|
||||
VersionID string
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
@@ -81,6 +86,11 @@ func (o *DownloadObjectParams) BindRequest(r *http.Request, route *middleware.Ma
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
qVersionID, qhkVersionID, _ := qs.GetOK("version_id")
|
||||
if err := o.bindVersionID(qVersionID, qhkVersionID, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -122,3 +132,24 @@ func (o *DownloadObjectParams) bindPrefix(rawData []string, hasKey bool, formats
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindVersionID binds and validates parameter VersionID from query.
|
||||
func (o *DownloadObjectParams) bindVersionID(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
if !hasKey {
|
||||
return errors.Required("version_id", "query", rawData)
|
||||
}
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: true
|
||||
// AllowEmptyValue: false
|
||||
if err := validate.RequiredString("version_id", "query", raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.VersionID = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ import (
|
||||
type DownloadObjectURL struct {
|
||||
BucketName string
|
||||
|
||||
Prefix string
|
||||
Prefix string
|
||||
VersionID string
|
||||
|
||||
_basePath string
|
||||
// avoid unkeyed usage
|
||||
@@ -81,6 +82,11 @@ func (o *DownloadObjectURL) Build() (*url.URL, error) {
|
||||
qs.Set("prefix", prefixQ)
|
||||
}
|
||||
|
||||
versionIDQ := o.VersionID
|
||||
if versionIDQ != "" {
|
||||
qs.Set("version_id", versionIDQ)
|
||||
}
|
||||
|
||||
_result.RawQuery = qs.Encode()
|
||||
|
||||
return &_result, nil
|
||||
|
||||
@@ -96,7 +96,7 @@ func Test_ResourceQuota(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Handle error while fetching storage quota elementss",
|
||||
name: "Handle error while fetching storage quota elements",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
|
||||
@@ -19,7 +19,9 @@ package restapi
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/pkg/acl"
|
||||
@@ -45,21 +47,36 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
if err != nil {
|
||||
return user_api.NewLoginDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginCreated().WithPayload(loginResponse)
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse)
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
api.UserAPILoginOperatorHandler = user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOperatorResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOperatorDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginOperatorCreated().WithPayload(loginResponse)
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
@@ -27,7 +30,14 @@ func registerLogoutHandlers(api *operations.ConsoleAPI) {
|
||||
// logout from console
|
||||
api.UserAPILogoutHandler = user_api.LogoutHandlerFunc(func(params user_api.LogoutParams, session *models.Principal) middleware.Responder {
|
||||
getLogoutResponse(session)
|
||||
return user_api.NewLogoutOK()
|
||||
// Custom response writer to expire the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
expiredCookie := ExpireSessionCookie()
|
||||
// this will tell the browser to clear the cookie and invalidate user session
|
||||
// additionally we are deleting the cookie from the client side
|
||||
http.SetCookie(w, &expiredCookie)
|
||||
user_api.NewLogoutOK().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -221,18 +221,17 @@ func getDownloadObjectResponse(session *models.Principal, params user_api.Downlo
|
||||
// create a mc S3Client interface implementation
|
||||
// defining the client to be used
|
||||
mcClient := mcClient{client: s3Client}
|
||||
object, err := downloadObject(ctx, mcClient)
|
||||
object, err := downloadObject(ctx, mcClient, params.VersionID)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return object, nil
|
||||
}
|
||||
|
||||
func downloadObject(ctx context.Context, client MCClient) (io.ReadCloser, error) {
|
||||
// TODO: handle version
|
||||
func downloadObject(ctx context.Context, client MCClient, versionID string) (io.ReadCloser, error) {
|
||||
// TODO: handle encripted files
|
||||
var reader io.ReadCloser
|
||||
reader, pErr := client.get(ctx, mc.GetOptions{})
|
||||
reader, pErr := client.get(ctx, mc.GetOptions{VersionID: versionID})
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
}
|
||||
@@ -285,7 +284,7 @@ func deleteMultipleObjects(ctx context.Context, client MCClient, recursive bool)
|
||||
isRemoveBucket := false
|
||||
isIncomplete := false
|
||||
isBypass := false
|
||||
listOpts := mc.ListOptions{IsRecursive: recursive, IsIncomplete: isIncomplete, ShowDir: mc.DirNone}
|
||||
listOpts := mc.ListOptions{Recursive: recursive, Incomplete: isIncomplete, ShowDir: mc.DirNone}
|
||||
// TODO: support older Versions
|
||||
contentCh := make(chan *mc.ClientContent, 1)
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ package restapi
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Do not use:
|
||||
@@ -102,3 +104,37 @@ func FileExists(filename string) bool {
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
func NewSessionCookieForConsole(token string) http.Cookie {
|
||||
expiration := time.Now().Add(SessionDuration)
|
||||
|
||||
return http.Cookie{
|
||||
Path: "/",
|
||||
Name: "token",
|
||||
Value: token,
|
||||
MaxAge: int(SessionDuration.Seconds()), // 45 minutes
|
||||
Expires: expiration,
|
||||
HttpOnly: true,
|
||||
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
|
||||
// should not leak any cookie if we access the site using HTTP
|
||||
Secure: len(GlobalPublicCerts) > 0,
|
||||
// read more: https://web.dev/samesite-cookies-explained/
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
}
|
||||
}
|
||||
|
||||
func ExpireSessionCookie() http.Cookie {
|
||||
return http.Cookie{
|
||||
Path: "/",
|
||||
Name: "token",
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Expires: time.Now().Add(-100 * time.Hour),
|
||||
HttpOnly: true,
|
||||
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
|
||||
// should not leak any cookie if we access the site using HTTP
|
||||
Secure: len(GlobalPublicCerts) > 0,
|
||||
// read more: https://web.dev/samesite-cookies-explained/
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ func newWebSocketTenantAdminClient(conn *websocket.Conn, session *models.Princip
|
||||
minTenant.EnsureDefaults()
|
||||
|
||||
svcURL := GetTenantServiceURL(minTenant)
|
||||
|
||||
// TODO: in the feature we need to load all tenants public certificates under ~/.console/certs/CAs to avoid using insecure: true
|
||||
mAdmin, err := getTenantAdminClient(
|
||||
ctx,
|
||||
k8sClient,
|
||||
|
||||
@@ -328,6 +328,10 @@ paths:
|
||||
in: query
|
||||
required: true
|
||||
type: string
|
||||
- name: version_id
|
||||
in: query
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: A successful response.
|
||||
@@ -2967,10 +2971,6 @@ definitions:
|
||||
createTenantResponse:
|
||||
type: object
|
||||
properties:
|
||||
access_key:
|
||||
type: string
|
||||
secret_key:
|
||||
type: string
|
||||
console:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user