From d3d3b5a0023b2ddf181558008726f3e11cdcfa8f Mon Sep 17 00:00:00 2001 From: Ransom Williams Date: Wed, 25 Sep 2019 15:04:21 -0700 Subject: [PATCH] init PG sidecar Signed-off-by: Ransom Williams --- .circleci/config.yml | 2 +- .golangci.yml | 11 + Makefile | 43 ++- README.md | 174 +++++++--- cmd/datamon/cmd/cli_fuse_test.go | 3 +- go.mod | 35 +- go.sum | 312 +++++++++++++++++- hack/fuse-demo/coord-app-pg.Dockerfile | 60 ++++ hack/fuse-demo/create_coord_pg_pod.sh | 62 ++++ hack/fuse-demo/demo_pg_coord.sh | 220 +++++++++++++ hack/fuse-demo/mock_application_pg.sh | 95 ++++++ hack/fuse-demo/run_coord_pg_shell.sh | 30 ++ hack/fuse-demo/wrap_application.sh | 58 +++- hack/fuse-demo/wrap_datamon_pg.sh | 418 ++++++++++++++++++++++++ hack/k8s/example-coord-pg.template.yaml | 88 +++++ hack/k8s/example-coord.template.yaml | 2 +- sidecar-pg.Dockerfile | 75 +++++ 17 files changed, 1603 insertions(+), 85 deletions(-) create mode 100644 hack/fuse-demo/coord-app-pg.Dockerfile create mode 100755 hack/fuse-demo/create_coord_pg_pod.sh create mode 100755 hack/fuse-demo/demo_pg_coord.sh create mode 100644 hack/fuse-demo/mock_application_pg.sh create mode 100755 hack/fuse-demo/run_coord_pg_shell.sh create mode 100644 hack/fuse-demo/wrap_datamon_pg.sh create mode 100644 hack/k8s/example-coord-pg.template.yaml create mode 100644 sidecar-pg.Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml index 1aa7bfa14..7c902217a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,7 @@ jobs: name: Run golang linter command: | hack/go-generate.sh - golangci-lint run --disable golint,funlen,godox,whitespace,stylecheck --build-tags fuse_cli --max-same-issues 0 --verbose + golangci-lint run --verbose - run: name: Lint shell scripts command: | diff --git a/.golangci.yml b/.golangci.yml index 59bb8d1ba..5f0a8deee 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,6 @@ +run: + build-tags: fuse_cli + linters-settings: govet: check-shadowing: true @@ -23,3 +26,11 @@ linters: - lll - gochecknoinits - gochecknoglobals + - golint + - godox + - whitespace + - funlen + - stylecheck + - unparam + +max-same-issues: 0 diff --git a/Makefile b/Makefile index 01571e9ec..f04fc0841 100644 --- a/Makefile +++ b/Makefile @@ -46,9 +46,9 @@ help: } \ { lastLine = $$0 }' $(MAKEFILE_LIST) -.PHONY: build-and-push-fuse-sidecar -## build sidecar container used in Argo workflows -build-and-push-fuse-sidecar: build-datamon-binaries +.PHONY: build-and-push-fuse-sidecar-img +## build FUSE sidecar container used in Argo workflows +build-and-push-fuse-sidecar-img: @echo 'building fuse sidecar container' docker build \ --progress plain \ @@ -60,6 +60,27 @@ build-and-push-fuse-sidecar: build-datamon-binaries . docker push gcr.io/onec-co/datamon-fuse-sidecar +.PHONY: build-and-push-fuse-sidecar +## build FUSE sidecar container used in Argo workflows +build-and-push-fuse-sidecar: build-datamon-binaries build-and-push-fuse-sidecar-img + +.PHONY: build-and-push-pg-sidecar-img +## build postgres sidecar container used in Argo workflows +build-and-push-pg-sidecar-img: + @echo 'building pg sidecar container' + docker build \ + --progress plain \ + -t gcr.io/onec-co/datamon-pg-sidecar \ + -t gcr.io/onec-co/datamon-pg-sidecar:${GITHUB_USER}-$$(date '+%Y%m%d') \ + -t gcr.io/onec-co/datamon-pg-sidecar:$(subst /,_,$(GIT_BRANCH)) \ + --ssh default \ + -f sidecar-pg.Dockerfile \ + . + docker push gcr.io/onec-co/datamon-pg-sidecar + +.PHONY: build-and-push-pg-sidecar +## build postgres sidecar container used in Argo workflows +build-and-push-pg-sidecar: build-datamon-binaries build-and-push-pg-sidecar-img .PHONY: build-and-push-datamover ## build sidecar container used in Argo workflows @@ -249,7 +270,7 @@ fuse-demo-ro: fuse-demo-build-shell fuse-demo-build-sidecar .PHONY: fuse-demo-coord-build-app ## build shell container used in fuse demo fuse-demo-coord-build-app: - @echo 'building fuse demo container' + @echo 'building fuse demo application container' docker build \ --progress plain \ -t gcr.io/onec-co/datamon-fuse-demo-coord-app \ @@ -261,7 +282,7 @@ fuse-demo-coord-build-app: .PHONY: fuse-demo-coord-build-datamon ## build shell container used in fuse demo fuse-demo-coord-build-datamon: - @echo 'building fuse demo container' + @echo 'building fuse demo sidecar container' docker build \ --progress plain \ -t gcr.io/onec-co/datamon-fuse-demo-coord-datamon \ @@ -270,6 +291,18 @@ fuse-demo-coord-build-datamon: . docker push gcr.io/onec-co/datamon-fuse-demo-coord-datamon +.PHONY: pg-demo-coord-build-app +## build shell container used in fuse demo +pg-demo-coord-build-app: + @echo 'building pg demo application container' + docker build \ + --progress plain \ + -t gcr.io/onec-co/datamon-pg-demo-coord-app \ + --ssh default \ + -f ./hack/fuse-demo/coord-app-pg.Dockerfile \ + . + docker push gcr.io/onec-co/datamon-pg-demo-coord-app + .PHONY: profile-metrics ## Build the metrics collection binary and write output profile-metrics: diff --git a/README.md b/README.md index c535e2fdd..2643406cd 100644 --- a/README.md +++ b/README.md @@ -119,28 +119,71 @@ multiple labels can refer to the same bundle via its commit hash. Current use of Datamon at One Concern with respect to intra-Argo workflow usage relies on the [kubernetes sidecar](https://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/) -pattern where a shared volume is used as the transport layer for application layer +pattern wherein a shared volume (transport layer) ramifies application layer communication to coordinate between the _main container_, where a data-science program accesses data provided by Datamon and produces data for Datamon to upload, and the -_sidecar container_, where Datamon provides data for access (via streaming through -main memory directly from GCS) and then, after the main container is done outputting -data to a shared Kubernetes volume, uploads the results of the data-science program -to GCS. Ensuring that, for example, the streaming data is ready for access (sidecar to -main-container messaging) as well as notification that the data-science program has -produced output data to upload (main-container to sidecar messaging), is the responsibility -of a couple of shell scripts that both ship inside the `gcr.io/onec-co/datamon-fuse-sidecar` -container, which is versioned along with +_sidecar container_, where Datamon provides data for access (as hierarchical filesystems, +as SQL databases, etc.). +After the main container's DAG-node-specific data-science program outputs data +(to shared Kubernetes volume, to a PostgreSQL instance in the sidecar, and so on), +the sidecar container uploads the results of the data-science program to GCS. + +Ensuring that data is ready for access (sidecar to main-container messaging) +as well as notification that the data-science program has +produced output data to upload (main-container to sidecar messaging), +is the responsibility of a few shell scripts shipped as part and parcel of the +Docker images that practicably constitute sidecars. +While there's precisely one application container per Argo node, +a Kubernetes container created from an arbitrary image, +sidecars are additional containers in the same Kubernetes pod +-- or Argo DAG node, we can say, approximately synonymously -- +that concert datamon-based data-ferrying setups with the application container. + +_Aside_: as additional kinds of data sources and sinks are added, +we may also refer to "sidecars" as "batteries," and so on as semantic drift +of the shell scripts shears away feature creep in the application binary. + +There are currently two batteries-included® images + +* `gcr.io/onec-co/datamon-fuse-sidecar` + provides hierarchical filesystem access +* `gcr.io/onec-co/datamon-pg-sidecar` + provides PostgreSQL database access + +Both are versioned along with [github releases](https://github.com/oneconcern/datamon/releases/) -of the desktop binary: to access release `0.4` as listed on the github releases page, -use the tag `v0.4` as in `gcr.io/onec-co/datamon-fuse-sidecar:v0.4` when -writing Dockerfiles or Kubernetes-like YAML that accesses the sidecar container image. +of the +[desktop binary](#os-x-install-guide). +to access recent releases listed on the github releases page, +use the git tag as the Docker image tag: +At time of writing, +[v0.7](https://github.com/oneconcern/datamon/releases/tag/v0.7) +is the latest release tag, and (with some elisions) +```yaml +spec: + ... + containers: + - name: datamon-sidecar + - image: gcr.io/onec-co/datamon-fuse-sidecar:v0.7 + ... +``` +would be the corresponding Kubernetes YAML to access the sidecar container image. + +_Aside_: historically, and in case it's necessary to roll back to an now-antient +version of the sidecar image, releases were tagged in git without the `v` prefix, +and Docker tags prepended `v` to the git tag. +For instance, `0.4` is listed on the github releases page, while +the tag `v0.4` as in `gcr.io/onec-co/datamon-fuse-sidecar:v0.4` was used when writing +Dockerfiles or Kubernetes-like YAML to accesses the sidecar container image. Users need only place the `wrap_application.sh` script located in the root directory -of the sidecar container within the main container. This can be accomplished via -an `initContainer` without duplicating version of the Datamon sidecar image in -both the main application Dockerfile as well as the YAML. When using a block-storage GCS -product, we might've specified a data-science application's Argo DAG node with something -like +of each of the sidecar containers within the main container. +This +[can be accomplished](https://github.com/oneconcern/datamon/blob/master/hack/k8s/example-coord.template.yaml#L15-L24) +via an `initContainer` without duplicating version of the Datamon sidecar +image in both the main application Dockerfile as well as the YAML. +When using a block-storage GCS product, we might've specified a data-science application's +Argo DAG node with something like ```yaml command: ["app"] @@ -151,35 +194,49 @@ whereas with `wrap_application.sh` in place, this would be something to the effe ```yaml command: ["/path/to/wrap_application.sh"] -args: ["-c", "/path/to/coordination_directory", "--", "app", "param1", "param2"] +args: ["-c", "/path/to/coordination_directory", "-b", "fuse", "--", "app", "param1", "param2"] ``` That is, `wrap_application.sh` has the following usage ```shell -wrap_application.sh -c -- +wrap_application.sh -c -b -- +``` + +where +* `` is an empty directory in a shared volume + (an + [`emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) + using memory-backed storage suffices). each coordination directory (not necessarily the volume) + corresponds to a particular DAG node (i.e. Kubernetes pod) and vice-versa. +* `` is in correspondence with the containers specified in the YAML + and may be among + - `fuse` + - `postgres` +* `` is the data-science application command exactly as it + would appear without the wrapper script. That is, the wrapper script, relies the + [conventional UNIX syntax](http://zsh.sourceforge.net/Guide/zshguide02.html#l11) + for stating that options to a command are done being declared. + +Meanwhile, each sidecar's datamon-specific batteries have their corresponding usages. + +##### `gcr.io/onec-co/datamon-fuse-sidecar` -- `wrap_datamon.sh` + +Provides filesystem representations (i.e. a folder) of [datamon bundles](#data-modeling). +Since bundles' filelists are serialized filesystem representations, +the `wrap_datamon.sh` interface is tightly coupled to that of the self-documenting +`datamon` binary itself. + +```shell +./wrap_datamon.sh -c -d -d ... ``` -where `` is an empty directory in a shared volume -(an -[`emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) -using memory-backed storage suffices). In the case of Argo workflows in particular, -the empty directory (and not necessarily the volume) ought to be specific to a -particular DAG node (i.e. Kubernetes pod). Each node uses a unique directory. -Meanwhile, `` is the data-science application command exactly as it -would appear without the wrapper script. -That is, the wrapper script, relies the -[conventional UNIX syntax](http://zsh.sourceforge.net/Guide/zshguide02.html#l11) -for stating that options to a command are done being declared. - -Meanwhile, `wrap_datamon.sh` similarly accepts a single `-c` option to specify the -location of the coordination directory. -Additionally, `wrap_datamon.sh` accepts a `-d` option. The parameters to this option are -among the standard Datamon CLI commands: - -* `config` -* `bundle mount` -* `bundle upload` +* `-c` the same coordination directory passed to `wrap_application.sh` +* `-d` all parameters, exactly as passed to the datamon binary, except as a + single scalar (quoted) parameter, for one of the following commands + - `config` sets user information associated with any bundles created by the node + - `bundle mount` provides sources for data-science applications + - `bundle upload` provides sinks for data-science applications Multiple (or none) `bundle mount` and `bundle upload` commands may be specified, and at most one `config` command is allowed so that an example `wrap_datamon.sh` @@ -187,17 +244,48 @@ YAML might be ```yaml command: ["./wrap_datamon.sh"] -args: ["-c", "/tmp/coord", "-d", "config create --name \"Coord\" --email coord-bot@oneconcern.com", "-d", "bundle upload --path /tmp/upload --message \"result of container coordination demo\" --repo ransom-datamon-test-repo --label coordemo", "-d", "bundle mount --repo ransom-datamon-test-repo --label testlabel --destination /tmp --mount /tmp/mount --stream"] +args: ["-c", "/tmp/coord", "-d", "config create --name \"Coord\" --email coord-bot@oneconcern.com", "-d", "bundle upload --path /tmp/upload --message \"result of container coordination demo\" --repo ransom-datamon-test-repo --label coordemo", "-d", "bundle mount --repo ransom-datamon-test-repo --label testlabel --mount /tmp/mount --stream"] ``` or from the shell ```shell -./wrap_datamon.sh -c /tmp/coord -d 'config create --name "Coord" --email coord-bot@oneconcern.com' -d 'bundle upload --path /tmp/upload --message "result of container coordination demo" --repo ransom-datamon-test-repo --label coordemo' -d 'bundle mount --repo ransom-datamon-test-repo --label testlabel --destination /tmp --mount /tmp/mount --stream' +./wrap_datamon.sh -c /tmp/coord -d 'config create --name "Coord" --email coord-bot@oneconcern.com' -d 'bundle upload --path /tmp/upload --message "result of container coordination demo" --repo ransom-datamon-test-repo --label coordemo' -d 'bundle mount --repo ransom-datamon-test-repo --label testlabel --mount /tmp/mount --stream' ``` -where, in particular, the `-d` (Datamon) options passed to the shell wrapper are -scalars. +##### `gcr.io/onec-co/datamon-pg-sidecar` -- `wrap_datamon_pg.sh` + +Provides Postgres databases as bundles and vice versa. +Since the datamon binary does not include any Postgres-specific notions, +the UI here is more decoupled than that of `wrap_datamon.sh`. + +```shell +./wrap_datamon.sh -c -x [db_opts_1] -d [db_opts_2] ... +``` + +where `-c` is as before and each `-x` flag delimits per-database options. +Every database created in the sidecar is uploaded to datamon, and the `db_opts` +that affect the availability of the database from the application container +or the upload of the database to datamon are + +* `-p` IP port used to connect to the database +* `-m` message written to the database's bundle +* `-l` label written to the bundle +* `-r` repo containing bundle + +Additionally, databases may be initialized with databases previously +stored in datamon by this sidecar. The slightly expanded form of a +`[db_opts]` in the above usage is then + +``` +-p [sink_opts] -s [source_opts] +``` + +where `` and `[sink_opts]` are as above, and `[source_opts]` are + +* `-r` repo containing the source bundle +* `-l` label of the source bundle +* `-b` bundle id # OS X install guide diff --git a/cmd/datamon/cmd/cli_fuse_test.go b/cmd/datamon/cmd/cli_fuse_test.go index 4f9386f2e..cfdeea75d 100644 --- a/cmd/datamon/cmd/cli_fuse_test.go +++ b/cmd/datamon/cmd/cli_fuse_test.go @@ -133,8 +133,7 @@ func TestBundleMutableMount(t *testing.T) { bundles, err := listBundles(t, repo1) require.NoError(t, err, "error out of listBundles() test helper") require.Equal(t, 0, bundles.Len(), "bundle count in test repo") - - cmd := exec.Command( + cmd := exec.Command( // nolint:gosec "../datamon", "bundle", "mount", "new", "--repo", repo1, diff --git a/go.mod b/go.mod index e04e415cb..1e6217e0d 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,22 @@ require ( cloud.google.com/go v0.37.1 github.com/aws/aws-sdk-go v1.18.6 github.com/container-storage-interface/spec v0.3.0 + github.com/coreos/go-etcd v2.0.0+incompatible // indirect github.com/docker/go-units v0.3.3 github.com/go-chi/chi v4.0.2+incompatible github.com/gobuffalo/envy v1.7.1 // indirect github.com/gobuffalo/logger v1.0.1 // indirect github.com/gobuffalo/packd v0.3.0 github.com/gobuffalo/packr/v2 v2.6.0 + github.com/gogo/protobuf v1.3.0 // indirect + github.com/golang/mock v1.3.1 // indirect + github.com/golangci/go-tools v0.0.0-20190318055746-e32c54105b7c // indirect + github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d // indirect + github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a // indirect + github.com/golangci/golangci-lint v1.19.1 // indirect + github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547 // indirect + github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 // indirect + github.com/gostaticanalysis/analysisutil v0.0.3 // indirect github.com/hashicorp/go-immutable-radix v1.0.0 github.com/hashicorp/golang-lru v0.5.0 github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -25,33 +35,38 @@ require ( github.com/karrick/godirwalk v1.10.12 github.com/kylelemons/godebug v1.1.0 // indirect github.com/magiconair/properties v1.8.1 // indirect - github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd // indirect + github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2 // indirect + github.com/markbates/safe v1.0.1 // indirect + github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb // indirect + github.com/mattn/go-colorable v0.1.4 // indirect + github.com/mattn/go-isatty v0.0.9 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/nightlyone/lockfile v0.0.0-20180618180623-0ad87eef1443 github.com/opentracing/opentracing-go v1.0.2 github.com/pelletier/go-toml v1.4.0 // indirect - github.com/pkg/errors v0.8.1 // indirect + github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d // indirect github.com/segmentio/ksuid v1.0.2 github.com/spf13/afero v1.2.2 github.com/spf13/cobra v0.0.5 github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.4.0 - github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.4.0 + github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e // indirect + github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 // indirect + github.com/ultraware/whitespace v0.0.4 // indirect go.uber.org/zap v1.10.0 - golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 // indirect golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect - golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 - golang.org/x/text v0.3.2 // indirect - golang.org/x/tools v0.0.0-20191001184121-329c8d646ebe // indirect + golang.org/x/sys v0.0.0-20191003212358-c178f38b412c + golang.org/x/tools v0.0.0-20191004211743-43d3a2ca2ae9 google.golang.org/api v0.2.0 google.golang.org/grpc v1.21.0 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.2 + gopkg.in/yaml.v2 v2.2.4 + gotest.tools/gotestsum v0.3.5 // indirect k8s.io/apimachinery v0.0.0-20190531161113-d9689afd32c1 // indirect k8s.io/kubernetes v1.14.2 k8s.io/utils v0.0.0-20190520173318-324c5df7d3f0 // indirect + mvdan.cc/unparam v0.0.0-20190917161559-b83a221c10a2 // indirect + sourcegraph.com/sqs/pbtypes v1.0.0 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index eeb3e5ad5..b3d7979ea 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,11 @@ git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqbl github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.0 h1:k9QF73nrHT3nPLz3lu6G5s+3Hi8Je36ODr1F5gjAXXM= +github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= +github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -25,10 +30,12 @@ github.com/container-storage-interface/spec v0.3.0 h1:ALxSqFjptj8R5rL+cdyAbwbaLH github.com/container-storage-interface/spec v0.3.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +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-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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= @@ -39,6 +46,10 @@ github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU= +github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 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= @@ -46,42 +57,129 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540 h1:djv/qAomOVj8voCHt0M0OYwR/4vfDq1zNKSPKjJCexs= +github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= +github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db h1:GYXWx7Vr3+zv833u+8IoXbNnQY0AdXsxAgI0kX7xcwA= +github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU= github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2 h1:8thhT+kUJMTMy3HlX4+y9Da+BNJck+p109tqqKp7WDs= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= github.com/gobuffalo/logger v1.0.0 h1:xw9Ko9EcC5iAFprrjJ6oZco9UpzS5MQ4jAwghsLHdy4= -github.com/gobuffalo/logger v1.0.0 h1:xw9Ko9EcC5iAFprrjJ6oZco9UpzS5MQ4jAwghsLHdy4= -github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg= github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= -github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= +github.com/gobuffalo/packd v0.1.0 h1:4sGKOD8yaYJ+dek1FDkwcxCHA40M4kfKgFHx8N2kwbU= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.2.0 h1:9Mu1TYbSfH75zQIQtZEgHEaYeRR4485U4T9N1OQYrXk= +github.com/gobuffalo/packd v0.2.0/go.mod h1:k2CkHP3bjbqL2GwxwhxUy1DgnlbW644hkLC9iIUvZwY= github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= -github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg= +github.com/gobuffalo/packr/v2 v2.4.0 h1:FB8CdysPlcECofv3tpH21T4aJDWmv7NFq8m0X6JZMGc= +github.com/gobuffalo/packr/v2 v2.4.0/go.mod h1:ra341gygw9/61nSjAbfwcwh8IrYL4WmR4IsPkPBhQiY= +github.com/gobuffalo/packr/v2 v2.5.1 h1:TFOeY2VoGamPjQLiNDT3mn//ytzk236VMO2j7iHxJR4= +github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw= github.com/gobuffalo/packr/v2 v2.6.0 h1:EMUzJIb5rof6r087PtGmgdzdLKpRBESJ/8jyL9MexfY= github.com/gobuffalo/packr/v2 v2.6.0/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754 h1:tpom+2CJmpzAWj5/VEHync2rJGi+epHNIeRSWjzGA+4= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= 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/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= 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/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/go-tools v0.0.0-20190318055746-e32c54105b7c h1:/7detzz5stiXWPzkTlPTzkBEIIE4WGpppBJYjKqBiPI= +github.com/golangci/go-tools v0.0.0-20190318055746-e32c54105b7c/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d h1:pXTK/gkVNs7Zyy7WKgLXmpQ5bHTrq5GDsp8R9Qs67g0= +github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98 h1:0OkFarm1Zy2CjCiDKfK9XHgmc2wbDlRMD2hD8anAJHU= +github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.18.0 h1:XmQgfcLofSG/6AsQuQqmLizB+3GggD+o6ObBG9L+VMM= +github.com/golangci/golangci-lint v1.18.0/go.mod h1:kaqo8l0OZKYPtjNmG4z4HrWLgcYNIJ9B9q3LWri9uLg= +github.com/golangci/golangci-lint v1.19.1 h1:g9xL8KW7UZDCkVlgHYJMA6F4Sj/sRVa0FoCeXI+Z3iM= +github.com/golangci/golangci-lint v1.19.1/go.mod h1:2CEc4Fxx3vxDv7g8DyXkHCBF73AOzAymcJAprs2vCps= +github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547 h1:fUdgm/BdKvwOHxg5AhNbkNRp2mSy8sxTXyBVs/laQHo= +github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217 h1:En/tZdwhAn0JNwLuXzP3k2RVtMqMmOEK7Yu/g3tmtJE= +github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 h1:XQKc8IYQOeRwVs36tDrEmTgDgP88d5iEURwpmtiAlOM= +github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= @@ -94,6 +192,7 @@ github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSN github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= 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/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= @@ -103,6 +202,10 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC github.com/googleapis/google-api-go-client v0.2.1-0.20190318183801-2dc3ad4d67ba h1:fLSVhPNofm+GaLxz683Y1KyJl7EepiLVzkEeVNHYMpU= github.com/googleapis/google-api-go-client v0.2.1-0.20190318183801-2dc3ad4d67ba/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3 h1:iwp+5/UAyzQSFgQ4uR2sni99sJ8Eo9DEacKWM5pekIg= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -115,6 +218,7 @@ github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCS github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -136,11 +240,21 @@ github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwK github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karrick/godirwalk v1.8.0 h1:ycpSqVon/QJJoaT1t8sae0tp1Stg21j+dyuS7OoagcA= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3 h1:lOpSw2vJP0y5eLBW906QwKsUK/fe/QDyoqM5rnnuPDY= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/karrick/godirwalk v1.10.12 h1:BqUm+LuJcXjGv1d2mj3gBiQyrQ57a0rYoAmhvJQ7RDU= github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -149,36 +263,81 @@ 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/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd h1:HvFwW+cm9bCbZ/+vuGNq7CRWXql8c0y8nGeYpqmpvmk= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2 h1:JgVTCPf0uBVcUSWpyXmGpgOc62nK5HWUBKAGc3Qqa5k= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86 h1:q6SrfsK4FojRnJ1j8+8OJzyq3g9Y1oSVyL6nYGJXXBk= +github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/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 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663 h1:Ri1EhipkbhWsffPJ3IPlrb4SkTOPa2PfRXp3jchBczw= +github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/nightlyone/lockfile v0.0.0-20180618180623-0ad87eef1443 h1:+2OJrU8cmOstEoh0uQvYemRGVH1O6xtO2oANUWHFnP0= github.com/nightlyone/lockfile v0.0.0-20180618180623-0ad87eef1443/go.mod h1:JbxfV1Iifij2yhRjXai0oFrbpxszXHRx1E5RuM26o4Y= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= @@ -205,30 +364,51 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.2 h1:XU784Pr0wdahMY2bYcyK6N1KuaRAdLtqD4qd8D18Bfs= github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/securego/gosec v0.0.0-20190912120752-140048b2a218 h1:O0yPHYL49quNL4Oj2wVq+zbGMu4dAM6iLoOQtm49TrQ= +github.com/securego/gosec v0.0.0-20190912120752-140048b2a218/go.mod h1:q6oYAujd2qyeU4cJqIri4LBIgdHXGvxWHZ1E29HNFRE= +github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d h1:BzRvVq1EHuIjxpijCEKpAxzKUUMurOQ4sknehIATRh8= +github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do= github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc= github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU= +github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= +github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -243,27 +423,58 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec h1:AmoEvWAO3nDx1MEcMzPh+GzOOIA5Znpv6++c7bePPY0= +github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ultraware/funlen v0.0.1 h1:UeC9tpM4wNWzUJfan8z9sFE4QCzjjzlCZmuJN+aOkH0= +github.com/ultraware/funlen v0.0.1/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo= +github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.3 h1:S5BCRRB5sttNy0bSOhbpw+0mb+cHiCmWfrvxpEzuUk0= +github.com/ultraware/whitespace v0.0.3/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/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= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.19.1 h1:gPYKQ/GAQYR2ksU+qXNmq3CrOZWT1kkryvW6O0v1acY= go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190314133821-5284462c4bec/go.mod h1:atTaCNAy0f16Ah5aV1gMSwgiKVHwu/JncqDpuRr7lS4= +golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/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-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf h1:pZmAoqqjjxp5rjcjFhHcvDR/nXjNA57G6oHPNFTguuw= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A= golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -273,10 +484,14 @@ golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTk 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/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/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-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -287,9 +502,14 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6 h1:FP8hkuE6yUEaJnK7O2eTuejKWwW+Rhfj80dQ2JcKxCU= +golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/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-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -304,21 +524,38 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/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-20181029174526-d69651ed3497/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-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA= +golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190621203818-d432491b9138 h1:t8BZD9RDjkm9/h7yYN6kE8oaeov5r9aztkB7zKA5Tkg= +golang.org/x/sys v0.0.0-20190621203818-d432491b9138/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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-20191003212358-c178f38b412c h1:6Zx7DRlKXf79yfxuQ/7GqV3w2y7aDsk6bGg0MzF5RVU= +golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -328,18 +565,49 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/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-20190121143147-24cd39ecf745/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-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190613204242-ed0dc450797f/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624190245-7f2218787638 h1:uIfBkD8gLczr4XDgYpt/qJYds2YJwZRNw4zs7wSnNhk= +golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4 h1:1mMox4TgefDwqluYCv677yNXwlfTkija4owZve/jr78= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191001184121-329c8d646ebe h1:hFr8KcN0dM0/dqbUW0KZYN+YXJeZBpBWIG9ZkMuX1vQ= -golang.org/x/tools v0.0.0-20191001184121-329c8d646ebe/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190909030654-5b82db07426d h1:PhtdWYteEBebOX7KXm4qkIAVSUTHQ883/2hRB92r9lk= +golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911151314-feee8acb394c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190918192907-c886270503e0 h1:LHzc8r5JnbNLDsA94VrV8ecQeZlmR7C1nV+dojw7VeQ= +golang.org/x/tools v0.0.0-20190918192907-c886270503e0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190923183622-59c6680fe2c1 h1:TpmF7otf6ojQkHEG+HgRNCR/WZWfATFqdBeuJW3WO6U= +golang.org/x/tools v0.0.0-20190923183622-59c6680fe2c1/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190923195354-c85f9fa9581e h1:w9vD9GwY/Ge6MYjzCtwcw9S9fesidgGH7LtFxAO/u4s= +golang.org/x/tools v0.0.0-20190923195354-c85f9fa9581e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191004211743-43d3a2ca2ae9 h1:lDvxQHqJDNbjBHUpa13NhA7Fwet00FQlg27QUAY/CC4= +golang.org/x/tools v0.0.0-20191004211743-43d3a2ca2ae9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -359,14 +627,15 @@ google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -375,11 +644,20 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.1.0+incompatible h1:5USw7CrJBYKqjg9R7QlA6jzqZKEAtvW82aNmsxxGPxw= +gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools/gotestsum v0.3.5 h1:VePOWRsuWFYpfp/G8mbmOZKxO5T3501SEGQRUdvq7h0= +gotest.tools/gotestsum v0.3.5/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/apimachinery v0.0.0-20190531161113-d9689afd32c1 h1:9KWWbUiVx29bUgvbFrKYEe8D9x+SSwSdwc7KBbbBQIw= k8s.io/apimachinery v0.0.0-20190531161113-d9689afd32c1/go.mod h1:u/2VL7tgEMV0FFTV9q0JO+7cnTsV44LP8Pmx41R4AQ4= k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= @@ -391,5 +669,17 @@ k8s.io/kubernetes v1.14.2 h1:Gdq2hPpttbaJBoClIanCE6WSu4IZReA54yhkZtvPUOo= k8s.io/kubernetes v1.14.2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190520173318-324c5df7d3f0 h1:wXWxhjjZAWaJLV/TVwdT1mDZraXjgzHxvtHEPz5qnpY= k8s.io/utils v0.0.0-20190520173318-324c5df7d3f0/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34 h1:duVSyluuJA+u0BnkcLR01smoLrGgDTfWt5c8ODYG8fU= +mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY= +mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= +mvdan.cc/unparam v0.0.0-20190917161559-b83a221c10a2 h1:ujHaqw4YdQP41+lVP79aaouzIU8ZIRMT9/S3YUru+JI= +mvdan.cc/unparam v0.0.0-20190917161559-b83a221c10a2/go.mod h1:rCqoQrfAmpTX/h2APczwM7UymU/uvaOluiVPIYCSY/k= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +sourcegraph.com/sqs/pbtypes v1.0.0 h1:f7lAwqviDEGvON4kRv0o5V7FT/IQK+tbkF664XMbP3o= +sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4= diff --git a/hack/fuse-demo/coord-app-pg.Dockerfile b/hack/fuse-demo/coord-app-pg.Dockerfile new file mode 100644 index 000000000..30d5368cd --- /dev/null +++ b/hack/fuse-demo/coord-app-pg.Dockerfile @@ -0,0 +1,60 @@ +FROM debian + +RUN apt-get update &&\ + curl -sL https://deb.nodesource.com/setup_10.x | bash &&\ + apt-get install -y \ + curl \ + postgresql \ + ca-certificates \ + gnupg \ + zsh \ + vim \ + &&\ + apt-get autoremove -yqq &&\ + apt-get clean -y &&\ + apt-get autoclean -yqq &&\ + rm -rf \ + /tmp/* \ + /var/tmp/* \ + /var/lib/apt/lists/* \ + /usr/share/doc/* \ + /usr/share/locale/* \ + /var/cache/debconf/*-old + +RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + +## BEGIN tini + +ENV TINI_VERSION v0.18.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-amd64 /tmp/tini-static-amd64 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-amd64.asc /tmp/tini-static-amd64.asc + +# omitting gpg verification during development/demo +# RUN for key in \ +# 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 \ +# ; do \ +# gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" || \ +# gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \ +# gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" ; \ +# done + +# RUN gpg --verify /tmp/tini-static-amd64.asc + +RUN install -m 0755 /tmp/tini-static-amd64 /bin/tini + +## END tini + +RUN useradd -u 1020 -ms /bin/bash developer +RUN groupadd -g 2000 developers +RUN usermod -g developers developer +RUN chown -R developer:developers /bin/tini + +ADD hack/fuse-demo/mock_application_pg.sh . +RUN chmod a+x mock_application_pg.sh + +USER developer + +RUN touch ~/.zshrc + +ENTRYPOINT [ "/tmp/coord/.scripts/wrap_application.sh"] +CMD [ "./mock_application.sh"] diff --git a/hack/fuse-demo/create_coord_pg_pod.sh b/hack/fuse-demo/create_coord_pg_pod.sh new file mode 100755 index 000000000..2b4b33eac --- /dev/null +++ b/hack/fuse-demo/create_coord_pg_pod.sh @@ -0,0 +1,62 @@ +#! /bin/zsh + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +# OUTPUT_LABEL=pg-coord-example-input +OUTPUT_LABEL=pg-coord-example +IS_INIT=false + +proj_root_dir="$(dirname "$(dirname "$SCRIPT_DIR")")" + +pull_policy=Always + +typeset -i SOME_CONST + +while getopts ioc: opt; do + case $opt in + (i) + OUTPUT_LABEL=pg-coord-example-input + IS_INIT=true + ;; + (o) + # local deploy + pull_policy=IfNotPresent + ;; + (c) + SOME_CONST="$OPTARG" + ;; + (\?) + print Bad option, aborting. + exit 1 + ;; + esac +done +(( OPTIND > 1 )) && shift $(( OPTIND - 1 )) + +if [[ -z $GOOGLE_APPLICATION_CREDENTIALS ]]; then + echo 'GOOGLE_APPLICATION_CREDENTIALS env variable not set' 1>&2 + exit 1 +fi + +if kubectl get secret google-application-credentials &> /dev/null; then + kubectl delete secret google-application-credentials +fi + +# https://cloud.google.com/kubernetes-engine/docs/tutorials/authenticating-to-cloud-platform#step_4_import_credentials_as_a_secret +kubectl create secret generic \ + google-application-credentials \ + --from-file=google-application-credentials.json=$GOOGLE_APPLICATION_CREDENTIALS + +RES_DEF="$proj_root_dir"/hack/k8s/gen/example-coord-pg.yaml + +IS_INIT=$IS_INIT \ +PULL_POLICY=$pull_policy \ +OUTPUT_LABEL=$OUTPUT_LABEL \ +SOME_CONST=$SOME_CONST \ + "$proj_root_dir"/hack/envexpand "$proj_root_dir"/hack/k8s/example-coord-pg.template.yaml > "$RES_DEF" + +if kubectl get deployment datamon-coord-pg-demo &> /dev/null; then + kubectl delete -f "$RES_DEF" +fi + +kubectl create -f "$RES_DEF" diff --git a/hack/fuse-demo/demo_pg_coord.sh b/hack/fuse-demo/demo_pg_coord.sh new file mode 100755 index 000000000..e7f3e8118 --- /dev/null +++ b/hack/fuse-demo/demo_pg_coord.sh @@ -0,0 +1,220 @@ +#! /bin/zsh + +## demonstrate pg batteries + +setopt ERR_EXIT + +DATAMON_EXEC=./cmd/datamon/datamon + +build_datamon_base=false +build_sidecar=true +build_demo_app=true +init_demo_bundle=false + +# roundtrip thru sidecar. +# change this variable to demonstrate dynamic upload contents +typeset -i SOME_CONST + +while getopts dbsc: opt; do + case $opt in + (d) + init_demo_bundle=true + ;; + (b) + build_datamon_base=true + ;; + (s) + build_sidecar_base=false + build_sidecar=false + build_demo_app=false + ;; + (c) + SOME_CONST="$OPTARG" + ;; + (\?) + print Bad option, aborting. + exit 1 + ;; + esac +done +(( OPTIND > 1 )) && shift $(( OPTIND - 1 )) + +if $build_datamon_base; then + make build-datamon-binaries +fi +if $build_sidecar; then + make build-and-push-pg-sidecar-img +fi +if $build_demo_app; then + make pg-demo-coord-build-app +fi + +make build-datamon-local + +## + +date '+%s' > /tmp/datamon_pg_demo_coord_start_timestamp + +params_create_pod=(-c $SOME_CONST) +if $init_demo_bundle; then + params_create_pod=($params_create_pod -i) +fi +./hack/fuse-demo/create_coord_pg_pod.sh $init_demo_bundle + +##### follow_coord_logs.sh dupe + +STARTUP_POLL_INTERVAL=1 + + +pod_name= + +echo "waiting on pod start" + +while [[ -z $pod_name ]]; do + sleep "$STARTUP_POLL_INTERVAL" + pod_name=$(kubectl get pods -l app=datamon-coord-pg-demo | grep Running | sed 's/ .*//') +done + +echo "pod started, following logs of $pod_name" + +LOG_FILE=/tmp/datamon-coord-pg-demo.log +if [[ -e $LOG_FILE ]]; then + print "removing extant log file $LOG_FILE" + rm $LOG_FILE +fi + +kubectl logs "$pod_name" -f --all-containers=true |tee $LOG_FILE & +log_pid=$! + +WRAP_APPLICATION_DONE= +WRAP_DATAMON_DONE= +while [[ -z $WRAP_APPLICATION_DONE || -z $WRAP_DATAMON_DONE ]]; do + if cat $LOG_FILE | grep -q '^wrap_application sleeping indefinitely'; then + WRAP_APPLICATION_DONE=true + fi + if cat $LOG_FILE | grep -q '^wrap_datamon_pg sleeping indefinitely'; then + WRAP_DATAMON_DONE=true + fi + sleep 3 +done + +##### verify + +## in-bundle paths +# dupe: wrap_datamon_pg.sh +BP_META=meta +BP_PG_VERSION=${BP_META}/pg_version +BP_DATA=data +BP_PG_TAR=${BP_DATA}/backup.tar.gz + +## + +MY_PG_PORT=5430 +data_dir=/tmp/demo_pg_coord_verify_data_dir +mount_dir=/tmp/demo_pg_coord_verify_mount_dir +log_dir=/tmp/demo_pg_coord_verify_log_dir +blank_pg_dir=/tmp/demo_pg_coord_verify_data_dir_blank + +if [[ -d ${data_dir} ]]; then + rm -rf ${data_dir} +fi +mkdir -p ${data_dir} +if [[ -d ${mount_dir} ]]; then + umount ${mount_dir} || true + rm -rf ${mount_dir} +fi +mkdir -p ${mount_dir} +if [[ -d ${log_dir} ]]; then + rm -rf ${log_dir} +fi +mkdir -p ${log_dir} +if [[ -d ${blank_pg_dir} ]]; then + rm -rf ${blank_pg_dir} +fi +mkdir -p ${blank_pg_dir} + +# --repo --label params from YAML +mount_params=(bundle mount \ + --stream \ + --mount $mount_dir \ + --repo ransom-datamon-test-repo \ + --label pg-coord-example \ + ) +"$DATAMON_EXEC" $mount_params > ${log_dir}/datamon_mount.log 2>&1 & +datamon_pid=$! +print -- 'datamon mount setup' +sleep 10 +bundle_pg_version=$(cat ${mount_dir}/${BP_PG_VERSION}) +# todo: verify version string in more detail +print -- "in-bundle pg version ${bundle_pg_version}" +(cd $data_dir && \ + >${log_dir}/untar.log 2>${log_dir}/untar_err.log \ + tar -xvf ${mount_dir}/${BP_PG_TAR}) + + +# print "unpacked db from ${mount_dir}/${BP_PG_TAR} to $data_dir ," \ +# "return to con't" +# read + +# todo: slay() in wrap_datamon_pg.sh remains unimpl +print -- 'datamon mount teardown' +kill $datamon_pid +sleep 10 + +# todo: workaround version mismatch to wrap_datamon_pg +PG_VERSION=$(postgres --version) +if [[ ! ${bundle_pg_version} = ${PG_VERSION} ]]; then + print 'in-bundle pg version and desktop version mismatch' + if [[ -f ${data_dir}/postgresql.conf ]]; then + print -- 'workaround: use local pg configuration' + initdb --no-locale -D ${blank_pg_dir} + rm ${data_dir}/postgresql.conf + cp ${blank_pg_dir}/postgresql.conf ${data_dir}/postgresql.conf + fi +fi +# todo: perms bits to wrap_datamon_pg +chmod -R 750 ${data_dir} +postgres -D ${data_dir} -p ${MY_PG_PORT} > ${log_dir}/pg.log 2>&1 & +pg_pid=$! + +print -- "postgres hopefully running on ${MY_PG_PORT} " \ + "with pid ${pg_pid}" \ + ".. see ${log_dir}/pg.log" +sleep 10 + +# todo: psql-based verification + +# echo "sleeping indefinitely (for debug)" +# while true; do sleep 100; done + +get_tabla_idx_vals() { + print 'select an_idx from tabla_e;' | \ + psql -p 5430 -U testpguser testdb | \ + awk ' +BEGIN { on_row = 0 } +$0 ~ /^\(/ {if(on_row) {on_row = 0}} +{if(on_row) {print $1;}} +$0 ~ /^----/ { on_row = 1 } +' +} + +tabla_idx_vals_scalar=$(get_tabla_idx_vals) +tabla_idx_vals_array=(${(f)tabla_idx_vals_scalar}) + +typeset -i expected_value +if $init_demo_bundle; then + expected_value=5 +else + expected_value=$((5 + $SOME_CONST)) +fi + +if [[ ${tabla_idx_vals_array[3]} -eq ${expected_value} ]]; then + print "got an expected value out of database" +else + print "got unexpected value out of database artifact" + print "${tabla_idx_vals_array[3]} != $((5 + $SOME_CONST))" + exit 1 +fi + +# todo: slay +kill $pg_pid diff --git a/hack/fuse-demo/mock_application_pg.sh b/hack/fuse-demo/mock_application_pg.sh new file mode 100644 index 000000000..29ebb87d9 --- /dev/null +++ b/hack/fuse-demo/mock_application_pg.sh @@ -0,0 +1,95 @@ +#! /bin/zsh + +setopt ERR_EXIT +setopt PIPE_FAIL + +### data-science application placeholder/mock +# this program is a stand-in for a data-science application +# +# todo: sandbox poc python (sqla/pandas) use rather than psql + +OUTPUT_PG_PORT="$1" +INPUT_PG_PORT="$2" +SOME_CONST="$3" +IS_INIT="$4" + +usage() { + print -- 'usage: ' \ + './mock_application_pg.sh input-pg-port ouput-pg-port some-const is-init' \ + 1>&2 + exit 1 +} + +if [ -z "$OUTPUT_PG_PORT" ]; then + usage +fi +if [ -z "$INPUT_PG_PORT" ]; then + usage +fi +if [ -z "$SOME_CONST" ]; then + usage +fi +if [[ ! $IS_INIT = true && ! $IS_INIT = flase ]]; then + usage +fi + +# convention from sidecar is to create provide initial postgres su +PG_SU=postgres + +# other pg users and setup are the responsibility of the application +PG_U=testpguser +PG_DB=testdb + +run_sql() { + sql_str=$1 + my_pg_port=$2 + if [[ -z $my_pg_port ]]; then + my_pg_port=$OUTPUT_PG_PORT + fi + print -- "$sql_str" | psql -h localhost -p $my_pg_port -U ${PG_U} ${PG_DB} +} + +# aside: postgres defaults to UNIX (filesystem) +# socket at /var/run/postgresql/*, +# not IP (network) socket, so it's the client's responsibility +# to ensure that the conn is opened at the network location + +print -- "CREATE ROLE ${PG_U} WITH LOGIN CREATEDB; +CREATE DATABASE ${PG_DB} WITH OWNER ${PG_U};" | \ + psql -h localhost -p $OUTPUT_PG_PORT -U $PG_SU + +run_sql 'CREATE TABLE tabla_e ( + id serial PRIMARY KEY, + an_idx integer +);' + +get_tabla_idx_vals_with_const() { + print 'select an_idx from tabla_e;' | \ + psql -h localhost -p $INPUT_PG_PORT -U $PG_U $PG_DB | \ + awk ' +BEGIN { on_row = 0 } +$0 ~ /^\(/ {if(on_row) {on_row = 0}} +{if(on_row) {print $1;}} +$0 ~ /^----/ { on_row = 1 } +' | \ + awk "{print "'$1'" + $SOME_CONST }" +} + +initdb() { + for idx in $(seq 1 2 9); do + run_sql "INSERT INTO tabla_e (an_idx) VALUES (${idx}) RETURNING id;" + done +} + +updatedb() { + for idx in $(get_tabla_idx_vals_with_const); do + print -- "adding index $idx to output table" + run_sql "INSERT INTO tabla_e (an_idx) VALUES (${idx}) RETURNING id;" + done +} + +if $IS_INIT; then + initdb +else + updatedb +fi diff --git a/hack/fuse-demo/run_coord_pg_shell.sh b/hack/fuse-demo/run_coord_pg_shell.sh new file mode 100755 index 000000000..2b9b1ee82 --- /dev/null +++ b/hack/fuse-demo/run_coord_pg_shell.sh @@ -0,0 +1,30 @@ +#! /bin/zsh + +container_name=demo-app + +while getopts s opt; do + case $opt in + (s) + container_name='datamon-sidecar' + ;; + (\?) + print Bad option, aborting. + exit 1 + ;; + esac +done +(( OPTIND > 1 )) && shift $(( OPTIND - 1 )) + +STARTUP_POLL_INTERVAL=1 +typeset pod_name + +print -- "waiting on pod start" + +while [[ -z $pod_name ]]; do + sleep "$STARTUP_POLL_INTERVAL" + pod_name=$(kubectl get pods -l app=datamon-coord-pg-demo | grep Running | sed 's/ .*//') +done + +kubectl exec -it "$pod_name" \ + -c "$container_name" \ + -- "/bin/zsh" diff --git a/hack/fuse-demo/wrap_application.sh b/hack/fuse-demo/wrap_application.sh index d348bdd27..4ea242b2c 100644 --- a/hack/fuse-demo/wrap_application.sh +++ b/hack/fuse-demo/wrap_application.sh @@ -15,7 +15,10 @@ POLL_INTERVAL=1 # sec SLEEP_INSTEAD_OF_EXIT= -while getopts sc: opt; do +SC_FUSE= +SC_PG= + +while getopts sc:b: opt; do case $opt in (s) SLEEP_INSTEAD_OF_EXIT=true @@ -23,9 +26,20 @@ while getopts sc: opt; do (c) COORD_POINT="$OPTARG" ;; + (b) + battery_type="$OPTARG" + if [ "$battery_type" = "fuse" ]; then + SC_FUSE=true + elif [ "$battery_type" = "postgres" ]; then + SC_PG=true + else + echo "unkown battery type $battery_type" 1>&2 + exit 1 + fi + ;; (\?) echo "Bad option, aborting." - return 1 + exit 1 ;; esac done @@ -71,9 +85,16 @@ emit_event() { ### application wrapper ## the following waits on datamon to make a FUSE mount available -await_event \ - 'mountdone' \ - 'waiting on datamon mount (app wrap)' +if [ -n "$SC_FUSE" ]; then + await_event \ + 'mountdone' \ + 'waiting on datamon mount (app wrap)' +fi +if [ -n "$SC_PG" ]; then + await_event \ + 'dbstarted' \ + 'waiting on db start (app wrap)' +fi ## once data is available, the data-science application is started echo "mount done, executing mock application, '" "$@" "'" @@ -88,15 +109,28 @@ fi echo "mock application done" ## after the application writes its output, notify the sidecar to start uploading it - -emit_event \ - 'initupload' \ - 'dispatching init upload event' +if [ -n "$SC_FUSE" ]; then + emit_event \ + 'initupload' \ + 'dispatching init upload event' +fi +if [ -n "$SC_PG" ]; then + emit_event \ + 'initdbupload' \ + 'dispatching init db upload event' +fi ## block until the sidecar finishes uploading -await_event \ - 'uploaddone' \ - 'waiting on upload' +if [ -n "$SC_FUSE" ]; then + await_event \ + 'uploaddone' \ + 'waiting on upload' +fi +if [ -n "$SC_PG" ]; then + await_event \ + 'dbuploaddone' \ + 'waiting on db upload' +fi ## COORDINATION ENDS with this container exiting echo "recved upload done event, exiting" diff --git a/hack/fuse-demo/wrap_datamon_pg.sh b/hack/fuse-demo/wrap_datamon_pg.sh new file mode 100644 index 000000000..67aa1c2bf --- /dev/null +++ b/hack/fuse-demo/wrap_datamon_pg.sh @@ -0,0 +1,418 @@ +#! /bin/zsh + +##### + +### util + +terminate() { + print -- "$*" 1>&2 + exit 1 +} + +##### + +setopt ERR_EXIT +setopt PIPE_FAIL + +POLL_INTERVAL=1 # sec + +PG_VERSION=$(postgres --version | \ + sed 's/^.*(PostgreSQL) \([0-9]*\.[0-9]*\).*$/\1/') + +PG_SU=postgres + +STAGE_BASE=/pg_stage +PG_DATA_DIR_ROOT=${STAGE_BASE}/pg_data_dir +MNT_DIR_ROOT=${STAGE_BASE}/mounts +LOG_ROOT=${STAGE_BASE}/logs +UPLOAD_STAGE=${STAGE_BASE}/upload + +# todo: populate from pod info via downward api +# https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/ +CFG_EMAIL="pg_wrap@oneconcern.com" +CFG_NAME="pg_wrap" + +## in-bundle paths +BP_META=meta +BP_PG_VERSION=${BP_META}/pg_version +BP_DATA=data +BP_PG_TAR=${BP_DATA}/backup.tar.gz + +##### + +typeset COORD_POINT +typeset -a PG_DB_IDS +typeset -A PG_DB_PORTS +# dest +typeset -A PG_DB_REPOS +typeset -A PG_DB_MSGS +typeset -A PG_DB_LABELS +# src +typeset -A PG_DB_HAS_SRC +typeset -A PG_DB_SRC_REPOS +typeset -A PG_DB_SRC_BUNDLES +typeset -A PG_DB_SRC_LABELS +# temp +typeset -i pg_db_idx +typeset pg_db_id + +SLEEP_INSTEAD_OF_EXIT= + +while getopts Sc:xsm:l:r:b:p: opt; do + case $opt in + (S) + SLEEP_INSTEAD_OF_EXIT=true + ;; + (c) + COORD_POINT="$OPTARG" + ;; + (x) + ((pg_db_idx++)) || true + pg_db_id="db_${pg_db_idx}" + PG_DB_IDS=($PG_DB_IDS $pg_db_id) + ;; + (s) + PG_DB_HAS_SRC[$pg_db_id]=true + ;; + (p) + PG_DB_PORTS[$pg_db_id]="$OPTARG" + ;; + (m) + if [[ -n ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + terminate "messages aren't written to source" + fi + PG_DB_MSGS[$pg_db_id]="$OPTARG" + ;; + (l) + if [[ -z ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + PG_DB_LABELS[$pg_db_id]="$OPTARG" + else + PG_DB_SRC_LABELS[$pg_db_id]="$OPTARG" + fi + ;; + (r) + if [[ -z ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + PG_DB_REPOS[$pg_db_id]="$OPTARG" + else + PG_DB_SRC_REPOS[$pg_db_id]="$OPTARG" + fi + ;; + (b) + if [[ -z ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + terminate "bundle flag is only meaningful when specifying source" + fi + PG_DB_SRC_BUNDLES[$pg_db_id]="$OPTARG" + ;; + (\?) + print -- "Bad option, aborting." + exit 1 + ;; + esac +done +if [[ "$OPTIND" -gt 1 ]]; then + shift $(( OPTIND - 1 )) +fi + +## + +for pg_db_id in $PG_DB_IDS; do + if [[ -z ${PG_DB_PORTS[$pg_db_id]} ]]; then + terminate "missing port for $pg_db_id" + fi + if [[ -z ${PG_DB_REPOS[$pg_db_id]} ]]; then + terminate "missing repo for $pg_db_id" + fi + if [[ -z ${PG_DB_MSGS[$pg_db_id]} ]]; then + terminate "missing message for $pg_db_id" + fi + if [[ -n ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + if [[ -z ${PG_DB_SRC_REPOS[$pg_db_id]} ]]; then + terminate "missing source repo for $pg_db_id" + fi + if [[ -z ${PG_DB_SRC_BUNDLES[$pg_db_id]} && -z ${PG_DB_SRC_LABELS[$pg_db_id]} ]]; then + terminate "no source data specified for $pg_db_id" + fi + if [[ -n ${PG_DB_SRC_BUNDLES[$pg_db_id]} && -n ${PG_DB_SRC_LABELS[$pg_db_id]} ]]; then + terminate "specifying source data by bundleid or and labelid is mutually exclusive" + fi + fi +done + +##### + +### util + +# #% =EVENT_NAME= <- wrap_application.sh +await_event() { + COORD_DONE= + EVENT_NAME="$1" + DBG_MSG="$2" + DBG_POLLS="$3" + if [[ -n $DBG_MSG ]]; then + echo "$DBG_MSG" + fi + while [[ -z $COORD_DONE ]]; do + if [[ -f "${COORD_POINT}/${EVENT_NAME}" ]]; then + COORD_DONE=1 + fi + if [[ -n $DBG_POLLS ]]; then + echo "... $DBG_MSG ..." + fi + sleep "$POLL_INTERVAL" + done +} + +#% wrap_application.sh <- =EVENT_NAME= +emit_event() { + EVENT_NAME="$1" + DBG_MSG="$2" + echo "$DBG_MSG" + touch "${COORD_POINT}/${EVENT_NAME}" +} + +dbg_print() { + typeset dbg=true + if $dbg; then + print -- $* + fi +} + +slay() { + typeset -i pid + typeset pids_str + typeset -a pids_arr + typeset -i num_tries + typeset sent_term + sent_term=false + pid="$1" + kill $pid + while true; do + if [[ num_tries -eq 10 ]]; then + dbg_print "sending SIGTERM to $pid" + kill -9 $pid + fi + pids_str=$(ps | awk 'NR > 1 { print $1 }') + pids_arr=(${(f)pids_str}) + if ! ((${pids_arr[(Ie)$pid]})); then + break + fi + dbg_print "awaiting $pid exit after signal" + sleep 1 + ((num_tries++)) || true + done +} + +# placeholder for postgres-specific error-handling +stop_postgres() { + pid="$1" + slay $pid +} + +##### + +mkdir -p $PG_DATA_DIR_ROOT +mkdir -p $MNT_DIR_ROOT +mkdir -p $LOG_ROOT + +## + +datamon config create \ + --name $CFG_NAME \ + --email $CFG_EMAIL + +## + +dbg_print "setting privs on fuse device" +sudo chgrp developers /dev/fuse + +dbg_print "starting postgres database processes" + +typeset -A pg_pids +for pg_db_id in $PG_DB_IDS; do + data_dir=${PG_DATA_DIR_ROOT}/${pg_db_id} + if [[ -e ${data_dir} ]]; then + terminate "data directory path $data_dir already exists" + fi + mkdir ${data_dir} + # ??? could download the entire bundle upfront instead of mount? + if [[ -n ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + mount_dir=${MNT_DIR_ROOT}/${pg_db_id} + mount_params=(bundle mount \ + --stream \ + --repo ${PG_DB_SRC_REPOS[$pg_db_id]} \ + --mount $mount_dir) + log_file_mount=${LOG_ROOT}/datamon_mount.${pg_db_id}.log + if [[ -z ${PG_DB_SRC_BUNDLES[$pg_db_id]} ]]; then + mount_params=($mount_params --label ${PG_DB_SRC_LABELS[$pg_db_id]}) + else + mount_params=($mount_params --bundle ${PG_DB_SRC_BUNDLES[$pg_db_id]}) + fi + if [[ -e $mount_dir ]]; then + terminate "mount directory path $mount_dir already exists" + fi + mkdir $mount_dir + unsetopt ERR_EXIT + datamon $mount_params > $log_file_mount 2>&1 & + datamon_status=$? + datamon_pid=$! + setopt ERR_EXIT + if [[ ! $datamon_status -eq 0 ]]; then + cat $log_file_mount + terminate "error starting 'datamon $mount_params'" + fi + dbg_print "started 'datamon $mount_params' with log ${log_file_mount}" + # block until mount found by os + mount_waiting=true + mount_data=$(mount | cut -d" " -f 3,5) + if $mount_waiting; then + if print "$mount_data" | grep -q "^$mount_dir fuse$"; then + mount_waiting=false + fi + dbg_print "waiting on mount at $mount_dir" + sleep 1 + fi + # verify metadata + bundle_pg_version=$(cat ${mount_dir}/${BP_PG_VERSION}) + if [[ $bundle_pg_version != $PG_VERSION ]]; then + terminate "pg version mistmatch $bundle_pg_version -- $PG_VERSION" + fi + (cd $data_dir && \ + >${LOG_ROOT}/untar.${pg_db_id}.log \ + 2>${LOG_ROOT}/untar_err.${pg_db_id}.log \ + tar -xvf ${mount_dir}/${BP_PG_TAR}) + slay $datamon_pid + chmod -R 750 $data_dir + else + # --no-locale flag helps artifact portability + # ??? other parms to set here? + initdb --no-locale -D $data_dir + fi + log_file_pg=${LOG_ROOT}/pg.${pg_db_id}.log + log_file_pg_err=${LOG_ROOT}/pg_err.${pg_db_id}.log + unsetopt ERR_EXIT + >${log_file_pg} 2>${log_file_pg_err} \ + postgres -D $data_dir -p $PG_DB_PORTS[$pg_db_id] & + pg_pid=$! + pg_status=$? + setopt ERR_EXIT + if [[ ! $pg_status -eq 0 ]]; then + cat ${log_file_pg} + cat ${log_file_pg_err} + terminate "error starting postgres" + fi + pg_pids[$pg_db_id]=$pg_pid + dbg_print "begin block on db id ${pg_db_id} start" + if [[ -n ${PG_DB_HAS_SRC[$pg_db_id]} ]]; then + while ! &>/dev/null psql \ + -h localhost \ + -p $PG_DB_PORTS[$pg_db_id] \ + -U $PG_SU -l; do + print "waiting on ${pg_db_id} db start..." + sleep $POLL_INTERVAL + done + else + while ! &>/dev/null createuser -p $PG_DB_PORTS[$pg_db_id] -s $PG_SU; do + print "waiting on ${pg_db_id} db start..." + sleep $POLL_INTERVAL + done + fi +done + +dbg_print "postgres database processes started" + +emit_event \ + 'dbstarted' \ + 'dispatching db started event' + +await_event \ + 'initdbupload' \ + 'waiting on db upload event' + +# VACUUM is a Postgres-specific SQL addition +# that allows the filesystem representation of the database +# to take less disk usage. +typeset -A db_name_to_username +for pg_db_id in $PG_DB_IDS; do + db_name_to_username=() + du_str=$(psql -p $PG_DB_PORTS[$pg_db_id] -U postgres -l | \ + tail +4 | grep -v '^(.* rows)$' | \ + grep -v '^ *$' | awk -F '|' '{print $1 $2}') + for du_pair in ${(f)du_str}; do + db_name=$(print -- $du_pair | awk '{print $1}') + username=$(print -- $du_pair | awk '{print $2}') + db_name_to_username[$db_name]=$username + done + for db_name in ${(k)db_name_to_username}; do + if [[ $db_name == 'postgres' || \ + $db_name == 'template0' || \ + $db_name == 'template1' ]]; then + continue + fi + print -- 'VACUUM;' | \ + psql \ + -h localhost \ + -p $PG_DB_PORTS[$pg_db_id] \ + -U ${db_name_to_username[$db_name]} \ + $db_name + print -- 'CHECKPOINT;' | \ + psql \ + -h localhost \ + -p $PG_DB_PORTS[$pg_db_id] \ + -U $PG_SU \ + $db_name + done +done + +dbg_print "stopping postgres processes" + +for pg_db_id in $PG_DB_IDS; do + stop_postgres $pg_pids[$pg_db_id] +done + +dbg_print "uploading data directories" + +if [[ -e ${UPLOAD_STAGE} ]]; then + terminate "upload staging area ${UPLOAD_STAGE} already exists" +fi + +for pg_db_id in $PG_DB_IDS; do + mkdir -p ${UPLOAD_STAGE} + mkdir ${UPLOAD_STAGE}/${BP_META} + mkdir ${UPLOAD_STAGE}/${BP_DATA} + dbg_print "prepare staging area" + data_dir=${PG_DATA_DIR_ROOT}/${pg_db_id} + (cd $data_dir && \ + >${LOG_ROOT}/tar.${pg_db_id}.log 2>${LOG_ROOT}/tar_err.${pg_db_id}.log \ + tar -cvf ${UPLOAD_STAGE}/${BP_PG_TAR} *) + print -- ${PG_VERSION} > ${UPLOAD_STAGE}/${BP_PG_VERSION} + dbg_print "perform upload" + log_file_upload=${LOG_ROOT}/datamon_upload.${upload_idx}.log + upload_params=(bundle upload \ + --path ${UPLOAD_STAGE} \ + --message $PG_DB_MSGS[$pg_db_id] \ + --repo $PG_DB_REPOS[$pg_db_id]) + if [[ -n $PG_DB_LABELS[$pg_db_id] ]]; then + upload_params=($upload_params --label $PG_DB_LABELS[$pg_db_id]) + fi + unsetopt ERR_EXIT + datamon $upload_params > $log_file_upload 2>&1 + datamon_status=$? + setopt ERR_EXIT + if [[ ! $datamon_status -eq 0 ]]; then + cat $log_file_upload + terminate "upload command failed" + fi + dbg_print "upload command had nominal status" + rm -rf ${UPLOAD_STAGE} +done + +emit_event \ + 'dbuploaddone' \ + 'dispatching db upload done event' + +if [[ -z $SLEEP_INSTEAD_OF_EXIT ]]; then + exit 0 +fi + +echo "wrap_datamon_pg sleeping indefinitely (for debug)" +while true; do sleep 100; done diff --git a/hack/k8s/example-coord-pg.template.yaml b/hack/k8s/example-coord-pg.template.yaml new file mode 100644 index 000000000..f9424c6f9 --- /dev/null +++ b/hack/k8s/example-coord-pg.template.yaml @@ -0,0 +1,88 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: datamon-coord-pg-demo +spec: + selector: + matchLabels: + app: datamon-coord-pg-demo + replicas: 1 + template: + metadata: + labels: + app: datamon-coord-pg-demo + spec: + initContainers: + - name: init-application-wrap + image: gcr.io/onec-co/datamon-pg-sidecar:latest + imagePullPolicy: "$PULL_POLICY" + command: ["sh", "-c", + "mkdir /tmp/coord/.scripts; cp wrap_application.sh /tmp/coord/.scripts/wrap_application.sh; chmod a+x /tmp/coord/.scripts/wrap_application.sh; echo 'placed application wrapper'"] + stdin: true + tty: true + volumeMounts: + - mountPath: /tmp/coord + name: container-coord + containers: + - name: demo-app + image: gcr.io/onec-co/datamon-pg-demo-coord-app:latest + imagePullPolicy: "$PULL_POLICY" + + # command: ["/bin/tini"] + # args: ["--", "/bin/zsh"] + + command: ["/tmp/coord/.scripts/wrap_application.sh"] + args: ["-s", "-c", "/tmp/coord", "-b", "postgres", "--", + "./mock_application_pg.sh", + "5430", "5429", + "$SOME_CONST", "$IS_INIT"] + + stdin: true + tty: true + volumeMounts: + - mountPath: /tmp/coord + name: container-coord + - name: datamon-sidecar + image: gcr.io/onec-co/datamon-pg-sidecar:latest + imagePullPolicy: "$PULL_POLICY" + + # command: ["/bin/tini"] + # args: ["--", "/bin/zsh"] + + command: ["./wrap_datamon_pg.sh"] + args: ["-S", "-c", "/tmp/coord", + "-x", + "-r", "ransom-datamon-test-repo", + "-l", "pg-coord-example-input", + "-m", "postgres coordination example", + "-p", "5430", + "-x", + "-r", "ransom-datamon-test-repo", + "-m", "postgres coordination example input", + "-p", "5429", + "-s", + "-r", "ransom-datamon-test-repo", + "-l", "$OUTPUT_LABEL"] + + securityContext: + privileged: true + stdin: true + tty: true + volumeMounts: + - mountPath: /pg_stage + name: staging-area + - mountPath: /tmp/coord + name: container-coord + - mountPath: /tmp/gac + name: google-application-credentials + env: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /tmp/gac/google-application-credentials.json + volumes: + - name: container-coord + emptyDir: {} + - name: staging-area + emptyDir: {} + - name: google-application-credentials + secret: + secretName: google-application-credentials diff --git a/hack/k8s/example-coord.template.yaml b/hack/k8s/example-coord.template.yaml index 118fb3ba8..8263a5526 100644 --- a/hack/k8s/example-coord.template.yaml +++ b/hack/k8s/example-coord.template.yaml @@ -29,7 +29,7 @@ spec: command: ["/tmp/coord/.scripts/wrap_application.sh"] # use the wrong number of params in order to simulate error out of mock app # args: ["-c", "/tmp/coord", "--", "./mock_application.sh", "/tmp/mount"] - args: ["-s", "-c", "/tmp/coord", "--", + args: ["-s", "-c", "/tmp/coord", "-b", "fuse", "--", "./mock_application.sh", "/tmp/mount", "/tmp/upload"] stdin: true tty: true diff --git a/sidecar-pg.Dockerfile b/sidecar-pg.Dockerfile new file mode 100644 index 000000000..fdc7a7f3f --- /dev/null +++ b/sidecar-pg.Dockerfile @@ -0,0 +1,75 @@ +FROM datamon-binaries as base + +# dist-alike during development/debug +RUN cp /stage/usr/bin/datamon /usr/bin/datamon +ADD ./hack/fuse-demo/datamon.yaml /root/.datamon/datamon.yaml + +# Build the dist image +# ??? do not need fuse and sudo in case of bundle download instead of mount +FROM postgres:11.5 +RUN apt-get update && apt-get install -y --no-install-recommends \ + fuse \ + sudo \ + vim \ + zsh \ + curl \ + ca-certificates \ + gnupg \ + netcat netcat-openbsd \ + &&\ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# ??? do not need in case of bundle download instead of mount +RUN echo "allow_root" >> /etc/fuse.conf + +RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + +## BEGIN tini + +ENV TINI_VERSION v0.18.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-amd64 /tmp/tini-static-amd64 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-amd64.asc /tmp/tini-static-amd64.asc + +# omitting gpg verification during development/demo +# RUN for key in \ +# 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 \ +# ; do \ +# gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" || \ +# gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \ +# gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" ; \ +# done + +# RUN gpg --verify /tmp/tini-static-amd64.asc + +RUN install -m 0755 /tmp/tini-static-amd64 /bin/tini + +## END tini + +COPY --from=base /stage / +ENV ZONEINFO /zoneinfo.zip + +ADD ./hack/fuse-demo/datamon.yaml /root/.datamon/datamon.yaml + +ADD hack/fuse-demo/wrap_datamon_pg.sh . +ADD hack/fuse-demo/wrap_application.sh . + +# USER root +RUN chmod a+x wrap_datamon_pg.sh +# USER developer + +RUN useradd -u 1020 -ms /bin/bash developer +RUN groupadd -g 2000 developers +RUN usermod -g developers developer +RUN chown -R developer:developers /usr/bin/datamon + +# ??? do not need in case of bundle download instead of mount +# or if not using docker-desktop kubernetes distro +RUN mkdir -p /etc/sudoers.d &&\ + echo "developer ALL = (ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer &&\ + chmod 0400 /etc/sudoers.d/developer + +USER developer + +RUN touch ~/.zshrc + +ENTRYPOINT [ "datamon" ]