diff --git a/.gitignore b/.gitignore index f1c181e..95cf6da 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out +.DS_Store diff --git a/Dockerfile b/Dockerfile index 4683584..14abdab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.13-alpine +FROM golang:1.14-alpine LABEL maintainer="rzrbld " @@ -9,10 +9,9 @@ ENV GOPROXY https://proxy.golang.org RUN \ apk add --no-cache git && \ - git clone https://github.com/minio/minio && cd minio/ && git checkout d4dcf1d7225a38ecf94abe7cbe7c69a93dc7c0b0 && cd pkg/madmin/examples/ && \ git clone https://github.com/rzrbld/adminio-api && go build adminio-api/src/main.go && cp main /go/bin/adminio - -FROM alpine:3.9 + +FROM alpine:3.11 EXPOSE 8080 diff --git a/Dockerfile.dev b/Dockerfile.dev index 57424ef..e6a5c72 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM golang:1.13-alpine +FROM golang:1.14-alpine LABEL maintainer="rzrbld " @@ -7,15 +7,11 @@ ENV CGO_ENABLED 0 ENV GO111MODULE on ENV GOPROXY https://proxy.golang.org -RUN \ - apk add --no-cache git && \ - git clone https://github.com/minio/minio && cd minio/ && git checkout d4dcf1d7225a38ecf94abe7cbe7c69a93dc7c0b0 && cd pkg/madmin/examples/ +ADD src /src/ -COPY src/main.go minio/pkg/madmin/examples/ +RUN cd /src/ && go build main.go && cp main /go/bin/adminio -RUN cd minio/pkg/madmin/examples && go build main.go && cp main /go/bin/adminio - -FROM alpine:3.9 +FROM alpine:3.11 EXPOSE 8080 diff --git a/README.md b/README.md index 1aef84c..0f92a9f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,19 @@ # Adminio-api -This is a simple admin "REST" API for [minio](https://min.io/) s3 server. +This is a simple admin "REST" API for [minio](https://min.io/) s3 server. Here is a Web UI for this API - [adminio-ui](https://github.com/rzrbld/adminio-ui) +### Breaking changes in 0.9 version + + - env renamed: API_HOST_PORT > ADMINIO_HOST_PORT + - API version v1 is depicated and soon will be removed. + ### Run full stack demo obtain [docker-compose.yml](https://raw.githubusercontent.com/rzrbld/adminio-ui/master/docker-compose.yml) from [adminio-ui](https://github.com/rzrbld/adminio-ui) repository. And run it: `` docker-compose -f docker-compose.yml up `` it will bring up: - - minio server on 9000 port + - minio server on 9000 port - adminio API on 8080 port - adminio UI on 80 port @@ -25,10 +30,41 @@ after that you can go to `` http://localhost `` and try out ### Env variables | Variable | Description | Default | |--------------|:-----------------------:|-----------:| -| API_HOST_PORT | which host and port API should listening. This is Iris based API, so you will need to provide 0.0.0.0:8080 for listening on all interfaces | localhost:8080 | -| MINIO_HOST_PORT | provide a minio server host and port | localhost:9000 | -| MINIO_SSL | enable or disable ssl | false | -| MINIO_REGION | set minio region | us-east-1 | -| MINIO_ACCESS | set minio Access Key | test | -| MINIO_SECRET | set minio Secret Key | testtest123 | -| ADMINIO_CORS_DOMAIN | set adminio-api CORS policy domain | * | +| `ADMINIO_HOST_PORT` | which host and port API should listening. This is Iris based API, so you will need to provide 0.0.0.0:8080 for listening on all interfaces | localhost:8080 | +| `MINIO_HOST_PORT` | provide a minio server host and port | localhost:9000 | +| `MINIO_SSL` | enable or disable ssl | false | +| `MINIO_REGION` | set minio region | us-east-1 | +| `MINIO_ACCESS` | set minio Access Key | test | +| `MINIO_SECRET` | set minio Secret Key | testtest123 | +| `ADMINIO_CORS_DOMAIN` | set adminio-api CORS policy domain | * | +| `ADMINIO_OAUTH_ENABLE` | enable oauth over supported providers | false | +| `ADMINIO_OAUTH_PROVIDER` | oauth provider, for more information see the full list of supported providers | github | +| `ADMINIO_OAUTH_CLIENT_ID` | oauth app client id | my-github-oauth-app-client-id | +| `ADMINIO_OAUTH_CLIENT_SECRET` | oauth app secret | my-github-oauth-app-secret | +| `ADMINIO_OAUTH_CALLBACK` | oauth callback, default listener on /auth/callback | http://"+ADMINIO_HOST_PORT+"/auth/callback | +| `ADMINIO_OAUTH_CUSTOM_DOMAIN` | oauth custom domain, for supported providers (auth0\wso2) | - | +| `ADMINIO_COOKIE_HASH_KEY` | hash key for session cookies. AES only supports key sizes of 16, 24 or 32 bytes | NRUeuq6AdskNPa7ewZuxG9TrDZC4xFat | +| `ADMINIO_COOKIE_BLOCK_KEY` | block key for session cookies. AES only supports key sizes of 16, 24 or 32 bytes | bnfYuphzxPhJMR823YNezH83fuHuddFC | +| `ADMINIO_COOKIE_NAME` | name for the session cookie | adminiosessionid | +| `ADMINIO_AUDIT_LOG_ENABLE` | enable audit log, mae sense if oauth is enabled, othervise set to false | false | +| `ADMINIO_METRICS_ENABLE` | enable default iris\golang metrics and bucket sizes metric on /metric/ uri path | false | + +### Supported oauth providers + + - amazon + - auth0 + - bitbucket + - box + - digitalocean + - dropbox + - github + - gitlab + - heroku + - onedrive + - salesforce + - slack + - wso2 + + ### example config +prometheus config: `examples/prometheus.yml` +bucket policy: `examples/policy.xml` diff --git a/dist/main b/dist/main deleted file mode 100755 index 1088a86..0000000 Binary files a/dist/main and /dev/null differ diff --git a/examples/policy.xml b/examples/policy.xml new file mode 100644 index 0000000..e596988 --- /dev/null +++ b/examples/policy.xml @@ -0,0 +1,13 @@ + + + expire-bucket + Enabled + + + + + + 1 + + + diff --git a/examples/prometheus.yml b/examples/prometheus.yml new file mode 100644 index 0000000..025b088 --- /dev/null +++ b/examples/prometheus.yml @@ -0,0 +1,6 @@ +scrape_configs: +- job_name: adminio + metrics_path: /metrics + scheme: http + static_configs: + - targets: ['adminio-host:8080'] diff --git a/src/audit/log.go b/src/audit/log.go new file mode 100644 index 0000000..0fb3eb0 --- /dev/null +++ b/src/audit/log.go @@ -0,0 +1,15 @@ +package audit + +import ( + iris "github.com/kataras/iris/v12" + "github.com/markbates/goth" + cnf "github.com/rzrbld/adminio-api/config" + log "log" +) + +func DefaultAuditLog(user goth.User, ctx iris.Context) { + ctx.ViewData("", user) + if cnf.AuditLogEnable { + log.Print("userNickName: ", user.NickName, "; userID: ", user.UserID, "; method:", ctx.RouteName()) + } +} diff --git a/src/clients/clients.go b/src/clients/clients.go new file mode 100644 index 0000000..81dc98d --- /dev/null +++ b/src/clients/clients.go @@ -0,0 +1,21 @@ +package clients + +import ( + minio "github.com/minio/minio-go/v6" + madmin "github.com/minio/minio/pkg/madmin" + cnf "github.com/rzrbld/adminio-api/config" + "log" +) + +var MadmClnt, MadmErr = madmin.New(cnf.Server, cnf.Maccess, cnf.Msecret, cnf.Ssl) +var MinioClnt, MinioErr = minio.New(cnf.Server, cnf.Maccess, cnf.Msecret, cnf.Ssl) + +func main() { + if MadmErr != nil { + log.Fatal("Error while connecting via admin client ", MadmErr) + } + + if MinioErr != nil { + log.Fatal("Error while connecting via minio client ", MinioErr) + } +} diff --git a/src/config/config.go b/src/config/config.go new file mode 100644 index 0000000..47ea348 --- /dev/null +++ b/src/config/config.go @@ -0,0 +1,40 @@ +package config + +import ( + "os" + strconv "strconv" +) + +var ( + Server = getEnv("MINIO_HOST_PORT", "localhost:9000") + Maccess = getEnv("MINIO_ACCESS", "test") + Msecret = getEnv("MINIO_SECRET", "testtest123") + Region = getEnv("MINIO_REGION", "us-east-1") + Ssl, _ = strconv.ParseBool(getEnv("MINIO_SSL", "false")) + ServerHostPort = getEnv("ADMINIO_HOST_PORT", "localhost:8080") + AdminioCORS = getEnv("ADMINIO_CORS_DOMAIN", "*") + // AES only supports key sizes of 16, 24 or 32 bytes. + // You either need to provide exactly that amount or you derive the key from what you type in. + ScHashKey = getEnv("ADMINIO_COOKIE_HASH_KEY", "NRUeuq6AdskNPa7ewZuxG9TrDZC4xFat") + ScBlockKey = getEnv("ADMINIO_COOKIE_BLOCK_KEY", "bnfYuphzxPhJMR823YNezH83fuHuddFC") + // --------------- + ScCookieName = getEnv("ADMINIO_COOKIE_NAME", "adminiosessionid") + OauthEnable, _ = strconv.ParseBool(getEnv("ADMINIO_OAUTH_ENABLE", "false")) + AuditLogEnable, _ = strconv.ParseBool(getEnv("ADMINIO_AUDIT_LOG_ENABLE", "false")) + MetricsEnable, _ = strconv.ParseBool(getEnv("ADMINIO_METRICS_ENABLE", "false")) + OauthProvider = getEnv("ADMINIO_OAUTH_PROVIDER", "github") + OauthClientId = getEnv("ADMINIO_OAUTH_CLIENT_ID", "my-github-oauth-app-client-id") + OauthClientSecret = getEnv("ADMINIO_OAUTH_CLIENT_SECRET", "my-github-oauth-app-secret") + OauthCallback = getEnv("ADMINIO_OAUTH_CALLBACK", "http://"+ServerHostPort+"/auth/callback") + OauthCustomDomain = getEnv("ADMINIO_OAUTH_CUSTOM_DOMAIN", "") +) + +func getEnv(key, fallback string) string { + value, exist := os.LookupEnv(key) + + if !exist { + return fallback + } + + return value +} diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 0000000..4219afc --- /dev/null +++ b/src/go.mod @@ -0,0 +1,35 @@ +module github.com/rzrbld/adminio-api + +go 1.14 + +require ( + github.com/ajg/form v1.5.1 // indirect + github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect + github.com/google/go-querystring v1.0.0 // indirect + github.com/gorilla/securecookie v1.1.1 + github.com/imkira/go-interpol v1.1.0 // indirect + github.com/iris-contrib/middleware/cors v0.0.0-20191219204441-78279b78a367 + github.com/iris-contrib/middleware/prometheus v0.0.0-20191219204441-78279b78a367 + github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect + github.com/kataras/iris/v12 v12.1.8 + github.com/markbates/goth v1.62.0 + github.com/mattn/go-isatty v0.0.8 // indirect + github.com/minio/minio v0.0.0-20200315185552-c9212819afbf + github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570 + github.com/moul/http2curl v1.0.0 // indirect + github.com/onsi/ginkgo v1.12.0 // indirect + github.com/onsi/gomega v1.9.0 // indirect + github.com/prometheus/client_golang v1.2.1 + github.com/rzrbld/goth-provider-wso2 v0.0.0-20200321083654-32bbe73a67d4 + github.com/sergi/go-diff v1.1.0 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/valyala/fasthttp v1.9.0 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect + github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect + github.com/yudai/pp v2.0.1+incompatible // indirect + golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect +) diff --git a/src/go.sum b/src/go.sum new file mode 100644 index 0000000..3a644b5 --- /dev/null +++ b/src/go.sum @@ -0,0 +1,632 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= +contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= +git.apache.org/thrift.git v0.13.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= +github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible h1:rZgFj+Gtf3NMi/U5FvCvhzaxzW/TaPYgUYx3bAPz9DE= +github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/CloudyKit/jet/v3 v3.0.0 h1:1PwO5w5VCtlUUl+KTOBsTGZlhjWkcybsGaAau52tOy8= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 h1:WDC6ySpJzbxGWFh4aMxFFC28wwGp5pEuoTtvA4q/qQ4= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/sarama v1.24.1/go.mod h1:fGP8eQ6PugKEI0iUETYYtnP6d1pH/bdDMTel1X5ajsU= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +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/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= +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= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go v1.20.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= +github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M= +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/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= +github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +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/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +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-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 h1:DddqAaWDpywytcG8w/qoQ5sAN8X12d3Z3koB0C3Rxsc= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.4.1/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ= +github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= +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/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= +github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= +github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/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/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/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-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f h1:4Gslotqbs16iAg+1KR/XdabIfq8TlAWHdwS5QJFksLc= +github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= +github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +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/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/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +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/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.1.1-0.20190703171940-f639636d18e0/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/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= +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/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/iris-contrib/blackfriday v2.0.0+incompatible h1:o5sHQHHm0ToHUlAJSTjW9UWicjJSDDauOOQ2AHuIVp4= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible h1:XZubAYg61/JwnJNbZilGjf3b3pB80+OQg2qf6c8BfWE= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3 h1:p7J/50I0cjo0wq/VWVCDFd8taPJbuFC+bq23SniRFX0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/middleware/cors v0.0.0-20191219204441-78279b78a367 h1:8sqPsO9g8khKdBGu9jJ1O7EgOblntuv1sLra6UVpuNY= +github.com/iris-contrib/middleware/cors v0.0.0-20191219204441-78279b78a367/go.mod h1:2p74oN7zAlsFSyDjs23eCuG4lzouZycTEg9nHGe0cnM= +github.com/iris-contrib/middleware/prometheus v0.0.0-20191219204441-78279b78a367 h1:VvQdoH+6VUc8KTPXCHg6akE5ABVUnqTWR5bNKHtd3LE= +github.com/iris-contrib/middleware/prometheus v0.0.0-20191219204441-78279b78a367/go.mod h1:wqVrZEhnPIIBHjVtwYpIkWlJ4S3WAideBka0g+jQLi8= +github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1 h1:10g/WnoRR+U+XXHWKBHeNy/+tZmM2kcAVGLOsz+yaDA= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jarcoal/httpmock v1.0.5 h1:cHtVEcTxRSX4J0je7mWPfc9BpDpqzXSJ5HbymZmyHck= +github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kataras/golog v0.0.10 h1:vRDRUmwacco/pmBAm8geLn8rHEdc+9Z4NAr5Sh7TG/4= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.2/go.mod h1:x8XU9FcsqdBvFyDA9brryw7Px8UZ8lquXwVaYKRzBBc= +github.com/kataras/iris/v12 v12.1.8 h1:O3gJasjm7ZxpxwTH8tApZsvf274scSGQAUpNe47c37U= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.12/go.mod h1:V8lRtjUHJWfwwoJHI0Pv/AYnJa3gvr6TPBTQfGvGEaE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2 h1:6NAi+uPJ/Zuid6mrAKlgpbI11/zK/lV4B2rxWaJN98Y= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5 h1:4HCONX5RLgVy6G4RkYOV3vKNcma9p236LdGOipJsaFE= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/readahead v1.3.1/go.mod h1:AH9juHzNH7xqdqFHrMRSHeH2Ps+vFf+kblDqzPFiLJg= +github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/kurin/blazer v0.5.4-0.20190613185654-cf2f27cc0be3/go.mod h1:4FCXMUWo9DllR2Do4TtBd377ezyAJ51vB5uTBjt0pGU= +github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= +github.com/markbates/goth v1.62.0 h1:8gyLomXU/bbVcee1zbHmV+S2ieh4sFssPuydNVYmPmg= +github.com/markbates/goth v1.62.0/go.mod h1:qh2QfwZoWRucQ+DR5KVKC6dUGkNCToWh4vS45GIzFsY= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190805055040-f9202b1cfdeb/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/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.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= +github.com/mattn/go-isatty v0.0.7/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-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= +github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/minio/cli v1.22.0/go.mod h1:bYxnK0uS629N3Bq+AOZZ+6lwF77Sodk4+UL9vNuXhOY= +github.com/minio/gokrb5/v7 v7.2.5/go.mod h1:z6fE6twrvMN004M+KRTHnmtfpxsBIztP0PVsak0/4f8= +github.com/minio/hdfs/v3 v3.0.1/go.mod h1:6ALh9HsAwG9xAXdpdrZJcSY0vR6z3K+9XIz6Y9pQG/c= +github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= +github.com/minio/lsync v1.0.1/go.mod h1:tCFzfo0dlvdGl70IT4IAK/5Wtgb0/BrTmo/jE8pArKA= +github.com/minio/minio v0.0.0-20200315185552-c9212819afbf h1:srtxK7j7Pl46viXLDRGYcr+hQP/pNf5zqIQsPcpZ5bU= +github.com/minio/minio v0.0.0-20200315185552-c9212819afbf/go.mod h1:QbCnTGb/blyNjrkyxB9ecKxtuWWUdcHShqED1bItwa0= +github.com/minio/minio-go/v6 v6.0.45/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= +github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570 h1:GLTZoRC6rhCTucnkJAQ63LhMU2S4CM71MRc9gfX7ohE= +github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= +github.com/minio/parquet-go v0.0.0-20200125064549-a1e49702e174/go.mod h1:PXYM9yI2l0YPmxHUXe6mFTmkQcyaVasDshAPTbGpDoo= +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/go.mod h1:oKURrZZEBtqObgJrSjN1Ln2n9MJj2icuBTkeJzZnvSI= +github.com/minio/sio v0.2.0/go.mod h1:nKM5GIWSrqbOZp0uhyj6M1iA0X6xQzSGtYSaTKSCut0= +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.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mmcloughlin/avo v0.0.0-20200303042253-6df701fe672f/go.mod h1:L0u9qfRMLNBO97u6pPukRp6ncoQz0Q25W69fvtht3vA= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ= +github.com/nats-io/go-nats v1.7.2/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0= +github.com/nats-io/go-nats-streaming v0.4.4/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server v1.4.1/go.mod h1:c8f/fHd2B6Hgms3LtCaI7y6pC4WD1f4SUxcCud5vhBc= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats-streaming-server v0.14.2/go.mod h1:RyqtDJZvMZO66YmyjIYdIvS69zu/wDAkyNWa8PIUa5c= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nats-io/stan.go v0.4.5/go.mod h1:Ji7mK6gRZJSH1nc3ZJH6vi7zn/QnZhpR9Arm4iuzsUQ= +github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4= +github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk= +github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/ginkgo v1.6.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 v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +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/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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +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= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20190704165056-9c2d0518ed81/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/rzrbld/goth v1.62.3 h1:EKGvHbyU4IEPbMRpwOSyDmILV9FZqMKdkYfOlJCrU/Y= +github.com/rzrbld/goth v1.62.3/go.mod h1:hqgGa9cYUCo/mzJdZK3zyHPftrI2fS7Le8rgyjFw8S0= +github.com/rzrbld/goth-provider-wso2 v0.0.0-20200321083654-32bbe73a67d4 h1:HoI5blpd/i1X1eJZv6iFxMV0mrs1+zNSsESLLwc2y9A= +github.com/rzrbld/goth-provider-wso2 v0.0.0-20200321083654-32bbe73a67d4/go.mod h1:xOQjs3CZLeZPuO0TM+cmiIGA+HPVln0XT8u/pIx5dxs= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +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/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= +github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e/go.mod h1:d8hQseuYt4rJoOo21lFzYJdhMjmDqLY++ayArbgYjWI= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 h1:hBSHahWMEgzwRyS6dRpxY0XyjZsHyQ61s084wo5PJe0= +github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.9.0 h1:hNpmUdy/+ZXYpGy0OBfm7K0UQTzb73W0T0U4iJIVrMw= +github.com/valyala/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg= +golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190914235951-31e00f45c22e h1:nOOVVcLC+/3MeovP40q5lCiWmP1Z1DaN8yn8ngU63hw= +golang.org/x/tools v0.0.0-20190914235951-31e00f45c22e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +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= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw= +google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190513181449-d00d292a067c/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.48.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= +gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= +gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= +gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= +gopkg.in/ldap.v3 v3.0.3/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/olivere/elastic.v5 v5.0.80/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/src/handlers/auth.go b/src/handlers/auth.go new file mode 100644 index 0000000..0469ba4 --- /dev/null +++ b/src/handlers/auth.go @@ -0,0 +1,41 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + cnf "github.com/rzrbld/adminio-api/config" + auth "github.com/rzrbld/adminio-api/oauth" +) + +var AuthLogout = func(ctx iris.Context) { + auth.Logout(ctx) + ctx.Redirect("/", iris.StatusTemporaryRedirect) +} + +var AuthRoot = func(ctx iris.Context) { + // try to get the user without re-authenticating + if gothUser, err := auth.CompleteUserAuth(ctx); err == nil { + ctx.ViewData("", gothUser) + ctx.JSON(iris.Map{"name": gothUser.UserID, "auth": true, "oauth": cnf.OauthEnable}) + } else { + auth.BeginAuthHandler(ctx) + } +} + +var AuthCheck = func(ctx iris.Context) { + if gothUser, err := auth.CompleteUserAuth(ctx); err == nil { + ctx.ViewData("", gothUser) + ctx.JSON(iris.Map{"name": gothUser.UserID, "auth": true, "oauth": cnf.OauthEnable}) + } else { + ctx.JSON(iris.Map{"auth": false, "oauth": cnf.OauthEnable}) + } +} + +var AuthCallback = func(ctx iris.Context) { + _, err := auth.CompleteUserAuth(ctx) + if err != nil { + ctx.StatusCode(iris.StatusInternalServerError) + ctx.Writef("%v", err) + return + } + auth.RedirectOnCallback(ctx) +} diff --git a/src/handlers/buckets.go b/src/handlers/buckets.go new file mode 100644 index 0000000..8f07e3e --- /dev/null +++ b/src/handlers/buckets.go @@ -0,0 +1,137 @@ +package handlers + +import ( + "fmt" + log "log" + "strings" + + iris "github.com/kataras/iris/v12" + minio "github.com/minio/minio-go/v6" + cnf "github.com/rzrbld/adminio-api/config" + resph "github.com/rzrbld/adminio-api/response" +) + +var BuckList = func(ctx iris.Context) { + lb, err := minioClnt.ListBuckets() + var res = resph.BodyResHandler(ctx, err, lb) + ctx.JSON(res) +} + +var BuckListExtended = func(ctx iris.Context) { + lb, err := minioClnt.ListBuckets() + allBuckets := []interface{}{} + for _, bucket := range lb { + bn, err := minioClnt.GetBucketNotification(bucket.Name) + if err != nil { + log.Print("Error while getting bucket notification") + } + br := iris.Map{"name": bucket.Name, "info": bucket, "events": bn} + allBuckets = append(allBuckets, br) + } + + var res = resph.BodyResHandler(ctx, err, allBuckets) + ctx.JSON(res) +} + +var BuckMake = func(ctx iris.Context) { + var newBucket = ctx.FormValue("newBucket") + var newBucketRegion = ctx.FormValue("newBucketRegion") + if newBucketRegion == "" { + newBucketRegion = cnf.Region + } + + err := minioClnt.MakeBucket(newBucket, newBucketRegion) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var BuckDelete = func(ctx iris.Context) { + var bucketName = ctx.FormValue("bucketName") + + err := minioClnt.RemoveBucket(bucketName) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var BuckGetLifecycle = func(ctx iris.Context) { + var bucketName = ctx.FormValue("bucketName") + + lc, err := minioClnt.GetBucketLifecycle(bucketName) + var res = resph.BodyResHandler(ctx, err, lc) + ctx.JSON(res) +} + +var BuckSetLifecycle = func(ctx iris.Context) { + var bucketName = ctx.FormValue("bucketName") + var lifecycle = ctx.FormValue("lifecycle") + + err := minioClnt.SetBucketLifecycle(bucketName, lifecycle) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var BuckGetEvents = func(ctx iris.Context) { + var bucket = ctx.FormValue("bucket") + bn, err := minioClnt.GetBucketNotification(bucket) + + var res = resph.BodyResHandler(ctx, err, bn) + ctx.JSON(res) +} + +var BuckSetEvents = func(ctx iris.Context) { + var arrARN = strings.Split(ctx.FormValue("stsARN"), ":") + + var stsARN = minio.NewArn(arrARN[1], arrARN[2], arrARN[3], arrARN[4], arrARN[5]) + + var bucket = ctx.FormValue("bucket") + var eventTypes = strings.Split(ctx.FormValue("eventTypes"), ",") + var filterPrefix = ctx.FormValue("filterPrefix") + var filterSuffix = ctx.FormValue("filterSuffix") + + bucketNotify, err := minioClnt.GetBucketNotification(bucket) + + var newNotification = minio.NewNotificationConfig(stsARN) + for _, event := range eventTypes { + switch event { + case "put": + newNotification.AddEvents(minio.ObjectCreatedAll) + case "delete": + newNotification.AddEvents(minio.ObjectRemovedAll) + case "get": + newNotification.AddEvents(minio.ObjectAccessedAll) + } + } + if filterPrefix != "" { + newNotification.AddFilterPrefix(filterPrefix) + } + if filterSuffix != "" { + newNotification.AddFilterSuffix(filterSuffix) + } + + switch arrARN[2] { + case "sns": + if bucketNotify.AddTopic(newNotification) { + err = fmt.Errorf("Overlapping Topic configs") + } + case "sqs": + if bucketNotify.AddQueue(newNotification) { + err = fmt.Errorf("Overlapping Queue configs") + } + case "lambda": + if bucketNotify.AddLambda(newNotification) { + err = fmt.Errorf("Overlapping lambda configs") + } + } + + err = minioClnt.SetBucketNotification(bucket, bucketNotify) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var BuckRemoveEvents = func(ctx iris.Context) { + var bucket = ctx.FormValue("bucket") + err := minioClnt.RemoveAllBucketNotification(bucket) + + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} diff --git a/src/handlers/common.go b/src/handlers/common.go new file mode 100644 index 0000000..e174821 --- /dev/null +++ b/src/handlers/common.go @@ -0,0 +1,33 @@ +package handlers + +import ( + madmin "github.com/minio/minio/pkg/madmin" + clients "github.com/rzrbld/adminio-api/clients" +) + +// clients +var madmClnt = clients.MadmClnt +var minioClnt = clients.MinioClnt + +var err error + +type Policy struct { + policyName string `json:"policyName"` + policyString string `json:"policyString"` +} + +type policySet struct { + policyName string `json:"policyName"` + entityName string `json:"entityName"` + isGroup string `json:"isGroup"` +} + +type UserStatus struct { + accessKey string `json:"accessKey"` + status madmin.AccountStatus `json:"status"` +} + +type User struct { + accessKey string `json:"accessKey"` + secretKey string `json:"secretKey"` +} diff --git a/src/handlers/groups.go b/src/handlers/groups.go new file mode 100644 index 0000000..6b0c1af --- /dev/null +++ b/src/handlers/groups.go @@ -0,0 +1,49 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + madmin "github.com/minio/minio/pkg/madmin" + resph "github.com/rzrbld/adminio-api/response" + log "log" + strconv "strconv" + "strings" +) + +var GrSetStatus = func(ctx iris.Context) { + var group = ctx.FormValue("group") + var status = madmin.GroupStatus(ctx.FormValue("status")) + + err = madmClnt.SetGroupStatus(group, status) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var GrSetDescription = func(ctx iris.Context) { + var group = ctx.FormValue("group") + + grp, err := madmClnt.GetGroupDescription(group) + var res = resph.BodyResHandler(ctx, err, grp) + ctx.JSON(res) +} + +var GrUpdateMembers = func(ctx iris.Context) { + gar := madmin.GroupAddRemove{} + gar.Group = ctx.FormValue("group") + gar.Members = strings.Split(ctx.FormValue("members"), ",") + + gar.IsRemove, err = strconv.ParseBool(ctx.FormValue("IsRemove")) + if err != nil { + log.Print(err) + ctx.JSON(iris.Map{"error": err.Error()}) + } + + err = madmClnt.UpdateGroupMembers(gar) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var GrList = func(ctx iris.Context) { + lg, err := madmClnt.ListGroups() + var res = resph.BodyResHandler(ctx, err, lg) + ctx.JSON(res) +} diff --git a/src/handlers/kv.go b/src/handlers/kv.go new file mode 100644 index 0000000..f97e08f --- /dev/null +++ b/src/handlers/kv.go @@ -0,0 +1,14 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + resph "github.com/rzrbld/adminio-api/response" +) + +var KvGet = func(ctx iris.Context) { + var keyString = ctx.FormValue("keyString") + + values, err := madmClnt.GetConfigKV(keyString) + var res = resph.BodyResHandler(ctx, err, values) + ctx.JSON(res) +} diff --git a/src/handlers/metrics.go b/src/handlers/metrics.go new file mode 100644 index 0000000..373ce6a --- /dev/null +++ b/src/handlers/metrics.go @@ -0,0 +1,32 @@ +package handlers + +import ( + "log" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +var opsProcessed = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "bucket_size_current", + Help: "bucket size in kbytes", +}, []string{"bucket"}) + +func RecordMetrics() { + go func() { + for { + du, err := madmClnt.DataUsageInfo() + if err != nil { + log.Print("Error while getting bucket size metrics from server") + } else { + if len(du.BucketsSizes) != 0 { + for k, v := range du.BucketsSizes { + opsProcessed.WithLabelValues(string(k)).Set(float64(v)) + } + } + } + time.Sleep(30 * time.Minute) + } + }() +} diff --git a/src/handlers/policy.go b/src/handlers/policy.go new file mode 100644 index 0000000..4bb2b40 --- /dev/null +++ b/src/handlers/policy.go @@ -0,0 +1,51 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + resph "github.com/rzrbld/adminio-api/response" + log "log" + strconv "strconv" +) + +var PolList = func(ctx iris.Context) { + lp, err := madmClnt.ListCannedPolicies() + var res = resph.BodyResHandler(ctx, err, lp) + ctx.JSON(res) +} + +var PolAdd = func(ctx iris.Context) { + p := Policy{} + p.policyName = ctx.FormValue("policyName") + p.policyString = ctx.FormValue("policyString") + + err = madmClnt.AddCannedPolicy(p.policyName, p.policyString) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var PolDelete = func(ctx iris.Context) { + p := policySet{} + p.policyName = ctx.FormValue("policyName") + + err = madmClnt.RemoveCannedPolicy(p.policyName) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var PolSet = func(ctx iris.Context) { + p := policySet{} + p.policyName = ctx.FormValue("policyName") + p.entityName = ctx.FormValue("entityName") + p.isGroup = ctx.FormValue("isGroup") + + isGroupBool, err := strconv.ParseBool(p.isGroup) + + if err != nil { + log.Print(err) + ctx.JSON(iris.Map{"error": err.Error()}) + } + + err = madmClnt.SetPolicy(p.policyName, p.entityName, isGroupBool) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} diff --git a/src/handlers/server.go b/src/handlers/server.go new file mode 100644 index 0000000..bdb0824 --- /dev/null +++ b/src/handlers/server.go @@ -0,0 +1,18 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + resph "github.com/rzrbld/adminio-api/response" +) + +var ServerInfo = func(ctx iris.Context) { + si, err := madmClnt.ServerInfo() + var res = resph.BodyResHandler(ctx, err, si) + ctx.JSON(res) +} + +var DiskInfo = func(ctx iris.Context) { + du, err := madmClnt.DataUsageInfo() + var res = resph.BodyResHandler(ctx, err, du) + ctx.JSON(res) +} diff --git a/src/handlers/users.go b/src/handlers/users.go new file mode 100644 index 0000000..8fe408e --- /dev/null +++ b/src/handlers/users.go @@ -0,0 +1,92 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + madmin "github.com/minio/minio/pkg/madmin" + resph "github.com/rzrbld/adminio-api/response" + log "log" +) + +var UsrList = func(ctx iris.Context) { + st, err := madmClnt.ListUsers() + var res = resph.BodyResHandler(ctx, err, st) + ctx.JSON(res) +} + +var UsrSetStats = func(ctx iris.Context) { + us := UserStatus{} + us.accessKey = ctx.FormValue("accessKey") + us.status = madmin.AccountStatus(ctx.FormValue("status")) + + err = madmClnt.SetUserStatus(us.accessKey, us.status) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var UsrDelete = func(ctx iris.Context) { + user := User{} + user.accessKey = ctx.FormValue("accessKey") + + err = madmClnt.RemoveUser(user.accessKey) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var UsrAdd = func(ctx iris.Context) { + user := User{} + user.accessKey = ctx.FormValue("accessKey") + user.secretKey = ctx.FormValue("secretKey") + + err = madmClnt.AddUser(user.accessKey, user.secretKey) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) +} + +var UsrCreateExtended = func(ctx iris.Context) { + p := policySet{} + p.policyName = ctx.FormValue("policyName") + p.entityName = ctx.FormValue("accessKey") + + u := User{} + u.accessKey = ctx.FormValue("accessKey") + u.secretKey = ctx.FormValue("secretKey") + + err = madmClnt.AddUser(u.accessKey, u.secretKey) + if err != nil { + log.Print(err) + ctx.JSON(iris.Map{"error": err.Error()}) + } else { + err = madmClnt.SetPolicy(p.policyName, p.entityName, false) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) + } +} + +var UsrSet = func(ctx iris.Context) { + u := User{} + p := policySet{} + us := UserStatus{} + + u.accessKey = ctx.FormValue("accessKey") + u.secretKey = ctx.FormValue("secretKey") + us.status = madmin.AccountStatus(ctx.FormValue("status")) + p.policyName = ctx.FormValue("policyName") + if u.secretKey == "" { + err = madmClnt.SetUserStatus(u.accessKey, us.status) + } else { + err = madmClnt.SetUser(u.accessKey, u.secretKey, us.status) + } + if err != nil { + log.Print(err) + ctx.JSON(iris.Map{"error": err.Error()}) + } else { + if p.policyName == "" { + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) + } else { + err = madmClnt.SetPolicy(p.policyName, u.accessKey, false) + var res = resph.DefaultResHandler(ctx, err) + ctx.JSON(res) + } + } +} diff --git a/src/main.go b/src/main.go index b35e2d1..38251d7 100644 --- a/src/main.go +++ b/src/main.go @@ -2,474 +2,149 @@ package main import ( "fmt" + "github.com/iris-contrib/middleware/cors" + prometheusMiddleware "github.com/iris-contrib/middleware/prometheus" iris "github.com/kataras/iris/v12" - minio "github.com/minio/minio-go/v6" - madmin "github.com/minio/minio/pkg/madmin" - log "log" - "os" - strconv "strconv" - strings "strings" + "github.com/markbates/goth" + "github.com/markbates/goth/providers/amazon" + "github.com/markbates/goth/providers/auth0" + "github.com/markbates/goth/providers/bitbucket" + "github.com/markbates/goth/providers/box" + "github.com/markbates/goth/providers/digitalocean" + "github.com/markbates/goth/providers/dropbox" + "github.com/markbates/goth/providers/github" + "github.com/markbates/goth/providers/gitlab" + "github.com/markbates/goth/providers/heroku" + "github.com/markbates/goth/providers/onedrive" + "github.com/markbates/goth/providers/salesforce" + "github.com/markbates/goth/providers/slack" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/rzrbld/goth-provider-wso2" + + cnf "github.com/rzrbld/adminio-api/config" + hdl "github.com/rzrbld/adminio-api/handlers" ) -type defaultRes struct { - Success string -} - -type User struct { - accessKey string `json:"accessKey"` - secretKey string `json:"secretKey"` -} - -type policySet struct { - policyName string `json:"policyName"` - entityName string `json:"entityName"` - isGroup string `json:"isGroup"` -} - -type Policy struct { - policyName string `json:"policyName"` - policyString string `json:"policyString"` -} - -type UserStatus struct { - accessKey string `json:"accessKey"` - status madmin.AccountStatus `json:"status"` -} - -type bucketComplex struct { - bucket string - // bucketInfo minio.BucketInfo - // bucketEvents minio.BucketNotification -} - -type candidate struct { - name string - interests []string - language string - experience bool -} - -func defaultResHandler(ctx iris.Context, err error) iris.Map { - var resp iris.Map - if err != nil { - log.Print(err) - resp = iris.Map{"error": err.Error()} - } else { - resp = iris.Map{"Success": "OK"} - } - return resp -} - -func bodyResHandler(ctx iris.Context, err error, body interface{}) interface{} { - var resp interface{} - if err != nil { - log.Print(err) - resp = iris.Map{"error": err.Error()} - } else { - resp = body - } - return resp -} - func main() { + goth.UseProviders( + github.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + dropbox.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + digitalocean.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + bitbucket.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + box.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + salesforce.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + amazon.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + onedrive.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + slack.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + heroku.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + gitlab.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback), + auth0.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback, cnf.OauthCustomDomain), + wso2.New(cnf.OauthClientId, cnf.OauthClientSecret, cnf.OauthCallback, cnf.OauthCustomDomain), + ) + fmt.Println("\033[31m\r\n ________ ________ _____ ______ ___ ________ ___ ________ \r\n|\\ __ \\ |\\ ___ \\ |\\ _ \\ _ \\ |\\ \\ |\\ ___ \\ |\\ \\ |\\ __ \\ \r\n\\ \\ \\|\\ \\\\ \\ \\_|\\ \\\\ \\ \\\\\\__\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\|\\ \\ \r\n \\ \\ __ \\\\ \\ \\ \\\\ \\\\ \\ \\\\|__| \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\\\ \\ \r\n \\ \\ \\ \\ \\\\ \\ \\_\\\\ \\\\ \\ \\ \\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\ \\ \\\\\\ \\ \r\n \\ \\__\\ \\__\\\\ \\_______\\\\ \\__\\ \\ \\__\\\\ \\__\\\\ \\__\\\\ \\__\\\\ \\__\\\\ \\_______\\\r\n \\|__|\\|__| \\|_______| \\|__| \\|__| \\|__| \\|__| \\|__| \\|__| \\|_______|\r\n \r\n \r\n \033[m") fmt.Println("\033[33mAdmin REST API for http://min.io (minio) s3 server") - fmt.Println("version : 0.8 ") + fmt.Println("version : 0.9 ") fmt.Println("Author : rzrbld") fmt.Println("License : MIT") fmt.Println("Git-repo : https://github.com/rzrbld/adminio \033[m \r\n") - var ssl = false - //config - server, exists := os.LookupEnv("MINIO_HOST_PORT") - if !exists { - server = "localhost:9000" - } - - maccess, exists := os.LookupEnv("MINIO_ACCESS") - if !exists { - maccess = "test" - } - - msecret, exists := os.LookupEnv("MINIO_SECRET") - if !exists { - msecret = "testtest123" - } - - region, exists := os.LookupEnv("MINIO_REGION") - if !exists { - region = "us-east-1" - } - - sslstr, exists := os.LookupEnv("MINIO_SSL") - if exists { - sslbool, err := strconv.ParseBool(sslstr) - if err != nil { - log.Print(err) - } - ssl = sslbool - } - - serverHostPort, exists := os.LookupEnv("API_HOST_PORT") - if !exists { - serverHostPort = os.Getenv("API_HOST_PORT") - } - - adminioCORS, exists := os.LookupEnv("ADMINIO_CORS_DOMAIN") - if !exists { - adminioCORS = "*" - } - - // connect - madmClnt, err := madmin.New(server, maccess, msecret, ssl) - if err != nil { - log.Print(err) - } - - minioClnt, err := minio.New(server, maccess, msecret, ssl) - if err != nil { - log.Print(err) - } - app := iris.New() crs := cors.New(cors.Options{ - AllowedOrigins: []string{adminioCORS}, // allows everything, use that to change the hosts. + AllowedOrigins: []string{cnf.AdminioCORS}, // allows everything, use that to change the hosts. AllowCredentials: true, }) - v1 := app.Party("/api/v1", crs).AllowMethods(iris.MethodOptions) // <- important for the preflight. - { - - v1.Get("/list-groups", func(ctx iris.Context) { - st, err := madmClnt.ListGroups() - var res = bodyResHandler(ctx, err, st) - ctx.JSON(res) - }) - - v1.Post("/set-status-group", func(ctx iris.Context) { - var group = ctx.FormValue("group") - var status = madmin.GroupStatus(ctx.FormValue("status")) - - err = madmClnt.SetGroupStatus(group, status) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/get-description-group", func(ctx iris.Context) { - var group = ctx.FormValue("group") - - grp, err := madmClnt.GetGroupDescription(group) - var res = bodyResHandler(ctx, err, grp) - ctx.JSON(res) - }) - - v1.Post("/update-members-group", func(ctx iris.Context) { - gar := madmin.GroupAddRemove{} - gar.Group = ctx.FormValue("group") - gar.Members = strings.Split(ctx.FormValue("members"), ",") - - gar.IsRemove, err = strconv.ParseBool(ctx.FormValue("IsRemove")) - if err != nil { - log.Print(err) - ctx.JSON(iris.Map{"error": err.Error()}) - } - - err = madmClnt.UpdateGroupMembers(gar) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/add-user", func(ctx iris.Context) { - - // debug body - // rawBodyAsBytes, err := ioutil.ReadAll(ctx.Request().Body) - // if err != nil { /* handle the error */ ctx.Writef("%v", err) } - - // rawBodyAsString := string(rawBodyAsBytes) - // println(rawBodyAsString) - - user := User{} - user.accessKey = ctx.FormValue("accessKey") - user.secretKey = ctx.FormValue("secretKey") - - err = madmClnt.AddUser(user.accessKey, user.secretKey) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - - }) - - v1.Post("/create-user-extended", func(ctx iris.Context) { - - p := policySet{} - p.policyName = ctx.FormValue("policyName") - p.entityName = ctx.FormValue("accessKey") - - u := User{} - u.accessKey = ctx.FormValue("accessKey") - u.secretKey = ctx.FormValue("secretKey") - - err = madmClnt.AddUser(u.accessKey, u.secretKey) - if err != nil { - log.Print(err) - ctx.JSON(iris.Map{"error": err.Error()}) - } else { - err = madmClnt.SetPolicy(p.policyName, p.entityName, false) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - } - }) - - v1.Post("/set-user", func(ctx iris.Context) { - u := User{} - p := policySet{} - us := UserStatus{} - - u.accessKey = ctx.FormValue("accessKey") - u.secretKey = ctx.FormValue("secretKey") - us.status = madmin.AccountStatus(ctx.FormValue("status")) - p.policyName = ctx.FormValue("policyName") - if u.secretKey == "" { - err = madmClnt.SetUserStatus(u.accessKey, us.status) - } else { - err = madmClnt.SetUser(u.accessKey, u.secretKey, us.status) - } - if err != nil { - log.Print(err) - ctx.JSON(iris.Map{"error": err.Error()}) - } else { - if p.policyName == "" { - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - } else { - err = madmClnt.SetPolicy(p.policyName, u.accessKey, false) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - } - } - }) - - v1.Get("/list-users", func(ctx iris.Context) { - st, err := madmClnt.ListUsers() - var res = bodyResHandler(ctx, err, st) - ctx.JSON(res) - }) - - v1.Post("/set-status-user", func(ctx iris.Context) { - us := UserStatus{} - us.accessKey = ctx.FormValue("accessKey") - us.status = madmin.AccountStatus(ctx.FormValue("status")) - - err = madmClnt.SetUserStatus(us.accessKey, us.status) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/delete-user", func(ctx iris.Context) { - user := User{} - user.accessKey = ctx.FormValue("accessKey") - - err = madmClnt.RemoveUser(user.accessKey) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/make-bucket", func(ctx iris.Context) { - var newBucket = ctx.FormValue("newBucket") - var newBucketRegion = ctx.FormValue("newBucketRegion") - if newBucketRegion == "" { - newBucketRegion = region - } - - err = minioClnt.MakeBucket(newBucket, newBucketRegion) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/get-bucket-events", func(ctx iris.Context) { - var bucket = ctx.FormValue("bucket") - bn, err := minioClnt.GetBucketNotification(bucket) - - var res = bodyResHandler(ctx, err, bn) - ctx.JSON(res) - }) - - v1.Post("/remove-bucket-events", func(ctx iris.Context) { - var bucket = ctx.FormValue("bucket") - err := minioClnt.RemoveAllBucketNotification(bucket) - - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/set-bucket-events", func(ctx iris.Context) { - var arrARN = strings.Split(ctx.FormValue("stsARN"), ":") - - var stsARN = minio.NewArn(arrARN[1], arrARN[2], arrARN[3], arrARN[4], arrARN[5]) - - var bucket = ctx.FormValue("bucket") - var eventTypes = strings.Split(ctx.FormValue("eventTypes"), ",") - var filterPrefix = ctx.FormValue("filterPrefix") - var filterSuffix = ctx.FormValue("filterSuffix") - - bucketNotify, err := minioClnt.GetBucketNotification(bucket) - - var newNotification = minio.NewNotificationConfig(stsARN) - for _, event := range eventTypes { - switch event { - case "put": - newNotification.AddEvents(minio.ObjectCreatedAll) - case "delete": - newNotification.AddEvents(minio.ObjectRemovedAll) - case "get": - newNotification.AddEvents(minio.ObjectAccessedAll) - } - } - if filterPrefix != "" { - newNotification.AddFilterPrefix(filterPrefix) - } - if filterSuffix != "" { - newNotification.AddFilterSuffix(filterSuffix) - } - - switch arrARN[2] { - case "sns": - if bucketNotify.AddTopic(newNotification) { - err = fmt.Errorf("Overlapping Topic configs") - } - case "sqs": - if bucketNotify.AddQueue(newNotification) { - err = fmt.Errorf("Overlapping Queue configs") - } - case "lambda": - if bucketNotify.AddLambda(newNotification) { - err = fmt.Errorf("Overlapping lambda configs") - } - } - - err = minioClnt.SetBucketNotification(bucket, bucketNotify) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Get("/list-buckets-extended", func(ctx iris.Context) { - lb, err := minioClnt.ListBuckets() - allBuckets := []interface{}{} - for _, bucket := range lb { - bn, err := minioClnt.GetBucketNotification(bucket.Name) - if err != nil { - fmt.Errorf("Error while getting bucket notification") - } - br := iris.Map{"name": bucket.Name, "info": bucket, "events": bn} - allBuckets = append(allBuckets, br) - } - - var res = bodyResHandler(ctx, err, allBuckets) - ctx.JSON(res) - }) - - v1.Get("/list-buckets", func(ctx iris.Context) { - lb, err := minioClnt.ListBuckets() - var res = bodyResHandler(ctx, err, lb) - ctx.JSON(res) - }) - - v1.Post("/delete-bucket", func(ctx iris.Context) { - var bucketName = ctx.FormValue("bucketName") - - err := minioClnt.RemoveBucket(bucketName) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/get-bucket-lifecycle", func(ctx iris.Context) { - var bucketName = ctx.FormValue("bucketName") - - lc, err := minioClnt.GetBucketLifecycle(bucketName) - var res = bodyResHandler(ctx, err, lc) - ctx.JSON(res) - }) - - v1.Post("/set-bucket-lifecycle", func(ctx iris.Context) { - var bucketName = ctx.FormValue("bucketName") - var lifecycle = ctx.FormValue("lifecycle") - - err := minioClnt.SetBucketLifecycle(bucketName, lifecycle) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Get("/server-info", func(ctx iris.Context) { - si, err := madmClnt.ServerInfo() - var res = bodyResHandler(ctx, err, si) - ctx.JSON(res) - }) - - v1.Get("/disk-info", func(ctx iris.Context) { - du, err := madmClnt.DataUsageInfo() - var res = bodyResHandler(ctx, err, du) - ctx.JSON(res) - }) - - v1.Get("/list-groups", func(ctx iris.Context) { - lg, err := madmClnt.ListGroups() - var res = bodyResHandler(ctx, err, lg) - ctx.JSON(res) - }) - - v1.Get("/list-policies", func(ctx iris.Context) { - lp, err := madmClnt.ListCannedPolicies() - var res = bodyResHandler(ctx, err, lp) - ctx.JSON(res) - }) - - v1.Post("/add-policy", func(ctx iris.Context) { - p := Policy{} - p.policyName = ctx.FormValue("policyName") - p.policyString = ctx.FormValue("policyString") - - err = madmClnt.AddCannedPolicy(p.policyName, p.policyString) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/delete-policy", func(ctx iris.Context) { - p := policySet{} - p.policyName = ctx.FormValue("policyName") - - err = madmClnt.RemoveCannedPolicy(p.policyName) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) - - v1.Post("/set-policy", func(ctx iris.Context) { - p := policySet{} - p.policyName = ctx.FormValue("policyName") - p.entityName = ctx.FormValue("entityName") - p.isGroup = ctx.FormValue("isGroup") - - isGroupBool, err := strconv.ParseBool(p.isGroup) - - if err != nil { - log.Print(err) - ctx.JSON(iris.Map{"error": err.Error()}) - } + // prometheus metrics + if cnf.MetricsEnable { + m := prometheusMiddleware.New("adminio", 0.3, 1.2, 5.0) + hdl.RecordMetrics() + app.Use(m.ServeHTTP) + app.Get("/metrics", iris.FromStd(promhttp.Handler())) + } - err = madmClnt.SetPolicy(p.policyName, p.entityName, isGroupBool) - var res = defaultResHandler(ctx, err) - ctx.JSON(res) - }) + v1auth := app.Party("/auth/", crs).AllowMethods(iris.MethodOptions) + { + v1auth.Get("/logout/", hdl.AuthLogout) + v1auth.Get("/", hdl.AuthRoot) + v1auth.Get("/check", hdl.AuthCheck) + v1auth.Get("/callback", hdl.AuthCallback) + } - v1.Post("/get-kv", func(ctx iris.Context) { - var keyString = ctx.FormValue("keyString") + //deprecated, will be removed + v1 := app.Party("/api/v1", crs).AllowMethods(iris.MethodOptions) + { + v1.Get("/list-buckets", hdl.BuckList) + v1.Post("/make-bucket", hdl.BuckMake) + v1.Get("/list-buckets-extended", hdl.BuckListExtended) + v1.Post("/delete-bucket", hdl.BuckDelete) + v1.Post("/get-bucket-lifecycle", hdl.BuckGetLifecycle) + v1.Post("/set-bucket-lifecycle", hdl.BuckSetLifecycle) + v1.Post("/get-bucket-events", hdl.BuckGetEvents) + v1.Post("/set-bucket-events", hdl.BuckSetEvents) + v1.Post("/remove-bucket-events", hdl.BuckRemoveEvents) + + v1.Get("/list-users", hdl.UsrList) + v1.Post("/set-status-user", hdl.UsrSetStats) + v1.Post("/delete-user", hdl.UsrDelete) + v1.Post("/add-user", hdl.UsrAdd) + v1.Post("/create-user-extended", hdl.UsrCreateExtended) + v1.Post("/set-user", hdl.UsrSet) + + v1.Get("/list-policies", hdl.PolList) + v1.Post("/add-policy", hdl.PolAdd) + v1.Post("/delete-policy", hdl.PolDelete) + v1.Post("/set-policy", hdl.PolSet) + + v1.Post("/set-status-group", hdl.GrSetStatus) + v1.Post("/get-description-group", hdl.GrSetDescription) + v1.Post("/update-members-group", hdl.GrUpdateMembers) + v1.Get("/list-groups", hdl.GrList) + + v1.Get("/server-info", hdl.ServerInfo) + v1.Get("/disk-info", hdl.DiskInfo) + + v1.Post("/get-kv", hdl.KvGet) - values, err := madmClnt.GetConfigKV(keyString) - var res = bodyResHandler(ctx, err, values) - ctx.JSON(res) - }) + } + // ------------------------------------------- + v2 := app.Party("/api/v2", crs).AllowMethods(iris.MethodOptions) + { + v2.Get("/buckets/list", hdl.BuckList) + v2.Post("/bucket/create", hdl.BuckMake) + v2.Get("/buckets/list-extended", hdl.BuckListExtended) + v2.Post("/bucket/delete", hdl.BuckDelete) + v2.Post("/bucket/get-lifecycle", hdl.BuckGetLifecycle) + v2.Post("/bucket/set-lifecycle", hdl.BuckSetLifecycle) + v2.Post("/bucket/get-events", hdl.BuckGetEvents) + v2.Post("/bucket/set-events", hdl.BuckSetEvents) + v2.Post("/bucket/remove-events", hdl.BuckRemoveEvents) + + v2.Get("/users/list", hdl.UsrList) + v2.Post("/user/set-status", hdl.UsrSetStats) + v2.Post("/user/delete", hdl.UsrDelete) + v2.Post("/user/create", hdl.UsrAdd) + v2.Post("/user/create-extended", hdl.UsrCreateExtended) + v2.Post("/user/update", hdl.UsrSet) + + v2.Get("/policies/list", hdl.PolList) + v2.Post("/policy/create", hdl.PolAdd) + v2.Post("/policy/delete", hdl.PolDelete) + v2.Post("/policy/update", hdl.PolSet) + + v2.Post("/group/set-status", hdl.GrSetStatus) + v2.Post("/group/get-description", hdl.GrSetDescription) + v2.Post("/group/update-members", hdl.GrUpdateMembers) + v2.Get("/groups/list", hdl.GrList) + + v2.Get("/server/common-info", hdl.ServerInfo) + v2.Get("/server/disk-info", hdl.DiskInfo) + + v2.Post("/kv/get", hdl.KvGet) } - app.Run(iris.Addr(serverHostPort)) + app.Run(iris.Addr(cnf.ServerHostPort)) } diff --git a/src/oauth/oauth.go b/src/oauth/oauth.go new file mode 100644 index 0000000..4820e06 --- /dev/null +++ b/src/oauth/oauth.go @@ -0,0 +1,132 @@ +package oauth + +import ( + "errors" + "github.com/gorilla/securecookie" + iris "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/sessions" + "github.com/markbates/goth" + cnf "github.com/rzrbld/adminio-api/config" +) + +var ( + sessionsManager *sessions.Sessions +) + +func init() { + cookieName := cnf.ScCookieName + hashKey := []byte(cnf.ScHashKey) + blockKey := []byte(cnf.ScBlockKey) + secureCookie := securecookie.New(hashKey, blockKey) + + sessionsManager = sessions.New(sessions.Config{ + Cookie: cookieName, + Encode: secureCookie.Encode, + Decode: secureCookie.Decode, + }) +} + +var GetProviderName = func(ctx iris.Context) (string, error) { + return cnf.OauthProvider, nil +} + +func BeginAuthHandler(ctx iris.Context) { + url, err := GetAuthURL(ctx) + if err != nil { + ctx.StatusCode(iris.StatusBadRequest) + ctx.Writef("%v", err) + return + } + + ctx.Redirect(url, iris.StatusTemporaryRedirect) +} + +func GetAuthURL(ctx iris.Context) (string, error) { + providerName, err := GetProviderName(ctx) + if err != nil { + return "", err + } + + provider, err := goth.GetProvider(providerName) + if err != nil { + return "", err + } + sess, err := provider.BeginAuth(SetState(ctx)) + if err != nil { + return "", err + } + + url, err := sess.GetAuthURL() + if err != nil { + return "", err + } + session := sessionsManager.Start(ctx) + session.Set(providerName, sess.Marshal()) + return url, nil +} + +var SetState = func(ctx iris.Context) string { + state := ctx.URLParam("state") + if len(state) > 0 { + return state + } + + return "state" +} + +var GetState = func(ctx iris.Context) string { + return ctx.URLParam("state") +} + +var CompleteUserAuth = func(ctx iris.Context) (goth.User, error) { + providerName, err := GetProviderName(ctx) + if err != nil { + return goth.User{}, err + } + + provider, err := goth.GetProvider(providerName) + if err != nil { + return goth.User{}, err + } + session := sessionsManager.Start(ctx) + value := session.GetString(providerName) + + if value == "" { + return goth.User{}, errors.New("session value for " + providerName + " not found") + } + + sess, err := provider.UnmarshalSession(value) + if err != nil { + return goth.User{}, err + } + + user, err := provider.FetchUser(sess) + if err == nil { + // user can be found with existing session data + return user, err + } + + // get new token and retry fetch + _, err = sess.Authorize(provider, ctx.Request().URL.Query()) + if err != nil { + return goth.User{}, err + } + + session.Set(providerName, sess.Marshal()) + return provider.FetchUser(sess) +} + +func Logout(ctx iris.Context) error { + providerName, err := GetProviderName(ctx) + if err != nil { + return err + } + session := sessionsManager.Start(ctx) + session.Delete(providerName) + return nil +} + +func RedirectOnCallback(ctx iris.Context) { + url := GetState(ctx) + ctx.Redirect(url, iris.StatusTemporaryRedirect) +} diff --git a/src/response/response.go b/src/response/response.go new file mode 100644 index 0000000..cc41bb5 --- /dev/null +++ b/src/response/response.go @@ -0,0 +1,60 @@ +package handlers + +import ( + iris "github.com/kataras/iris/v12" + audit "github.com/rzrbld/adminio-api/audit" + cnf "github.com/rzrbld/adminio-api/config" + auth "github.com/rzrbld/adminio-api/oauth" + log "log" +) + +func DefaultResHandler(ctx iris.Context, err error) iris.Map { + if cnf.OauthEnable { + if gothUser, err := auth.CompleteUserAuth(ctx); err == nil { + audit.DefaultAuditLog(gothUser, ctx) + return DefaultResConstructor(ctx, err) + } else { + return iris.Map{"auth": false, "oauth": cnf.OauthEnable} + } + } else { + return DefaultResConstructor(ctx, err) + } + + return nil +} + +func BodyResHandler(ctx iris.Context, err error, body interface{}) interface{} { + if cnf.OauthEnable { + if gothUser, err := auth.CompleteUserAuth(ctx); err == nil { + audit.DefaultAuditLog(gothUser, ctx) + return BodyResConstructor(ctx, err, body) + } else { + return iris.Map{"auth": false, "oauth": cnf.OauthEnable} + } + } else { + return BodyResConstructor(ctx, err, body) + } + return nil +} + +func BodyResConstructor(ctx iris.Context, err error, body interface{}) interface{} { + var resp interface{} + if err != nil { + log.Print(err) + resp = iris.Map{"error": err.Error()} + } else { + resp = body + } + return resp +} + +func DefaultResConstructor(ctx iris.Context, err error) iris.Map { + var resp iris.Map + if err != nil { + log.Print(err) + resp = iris.Map{"error": err.Error()} + } else { + resp = iris.Map{"Success": "OK"} + } + return resp +}