finish initial task driver skeleton implementation
This commit is contained in:
parent
7b455b415e
commit
ad2ca32ec0
12 changed files with 968 additions and 488 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
nomad-runtime-driver-skeleton
|
55
Makefile
55
Makefile
|
@ -1,55 +0,0 @@
|
|||
NAME := nomad-driver-skeleton
|
||||
PKG := github.com/hashicorp/$(NAME)
|
||||
|
||||
CGO_ENABLED := 0
|
||||
|
||||
# Set any default go build tags.
|
||||
BUILDTAGS :=
|
||||
# Set an output prefix, which is the local directory if not specified
|
||||
PREFIX?=$(shell pwd)
|
||||
|
||||
GOOSARCHES=linux/amd64
|
||||
|
||||
GO=go
|
||||
|
||||
.PHONY: build
|
||||
build: $(NAME) ## Builds a dynamic executable or package.
|
||||
|
||||
$(NAME): $(wildcard *.go) $(wildcard */*.go)
|
||||
@echo "+ $@"
|
||||
$(V)GO111MODULE=on GOOS=linux $(GO) build -tags "$(BUILDTAGS)" ${GO_LDFLAGS} -o $(NAME) ./cmd/driver/main.go
|
||||
|
||||
.PHONY: static
|
||||
static: ## Builds a static executable.
|
||||
@echo "+ $@"
|
||||
CGO_ENABLED=$(CGO_ENABLED) $(GO) build \
|
||||
-tags "$(BUILDTAGS) static_build" \
|
||||
${GO_LDFLAGS_STATIC} -o $(NAME) .
|
||||
|
||||
all: clean build fmt lint test vet
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Verifies all files have been `gofmt`ed.
|
||||
@echo "+ $@"
|
||||
@gofmt -s -l . | grep -v '.pb.go:' | grep -v vendor | tee /dev/stderr
|
||||
|
||||
.PHONY: test
|
||||
test: ## Runs the go tests.
|
||||
@echo "+ $@"
|
||||
@$(GO) test -v -tags "$(BUILDTAGS) cgo" $(shell $(GO) list ./... | grep -v vendor)
|
||||
|
||||
.PHONY: vet
|
||||
vet: ## Verifies `go vet` passes.
|
||||
@echo "+ $@"
|
||||
@$(GO) vet -printfuncs Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln -all ./...
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Cleanup any build binaries or packages.
|
||||
@echo "+ $@"
|
||||
$(RM) $(NAME)
|
||||
$(RM) -r $(BUILDDIR)
|
||||
|
||||
dep:
|
||||
$(V)GO111MODULE=on go mod download
|
||||
$(V)GO111MODULE=on go mod vendor
|
||||
$(V)GO111MODULE=on go mod tidy
|
59
README.md
59
README.md
|
@ -1,50 +1,49 @@
|
|||
# nomad-driver-skeleton
|
||||
This project is a [Hashicorp Nomad](https://www.nomadproject.io/) runtime driver plugin skeleton implementation.
|
||||
You can clone and modify this to get started writing your
|
||||
own driver plugin.
|
||||
nomad-runtime-driver-skeleton
|
||||
==========
|
||||
|
||||
Note that this is only a skeleton to help you get started. The Makefile only builds
|
||||
for linux/amd64
|
||||
This project is a [Hashicorp Nomad](https://www.nomadproject.io/) [task driver
|
||||
plugin](https://www.nomadproject.io/docs/drivers/index.html) skeleton
|
||||
implementation. You can clone and modify this to get started writing your own
|
||||
task driver plugin.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
-------------------
|
||||
|
||||
- [Nomad](https://www.nomadproject.io/downloads.html) v0.9.5+
|
||||
- [Go](https://golang.org/doc/install) v1.11+ (to build the plugin)
|
||||
|
||||
Get Started
|
||||
-----------
|
||||
-------------------
|
||||
|
||||
Clone repository to: `$GOPATH/src/github.com/hashicorp/nomad-driver-skeleton
|
||||
|
||||
Copy the files into your new driver's package and change package names as needed.
|
||||
Download the project module:
|
||||
|
||||
```sh
|
||||
$ cd $GOPATH/src/github.com/hashicorp/nomad-driver-skeleton
|
||||
$ make dep
|
||||
$ make build
|
||||
go get github.com/hashicorp/nomad-skeleton-task-driver-plugin
|
||||
```
|
||||
|
||||
Requirements
|
||||
------------
|
||||
Follow the comments marked with a `TODO` tag to implement your driver's logic.
|
||||
For more information consult the Nomad documentation on
|
||||
[plugins](https://www.nomadproject.io/docs/internals/plugins/index.html).
|
||||
|
||||
[Go](http://www.golang.org) should be installed on your machine.
|
||||
You will also need to correctly setup a [GOPATH](http://golang.org/doc/code.html#GOPATH)
|
||||
and add `$GOPATH/bin` to your `$PATH`.
|
||||
|
||||
To compile the driver plugin, run `make build`. This will build the plugin and put the task driver binary under the
|
||||
NOMAD plugin dir, which by default is located under `<nomad-data-dir>/plugins/`.
|
||||
Check Nomad `-data-dir` and `-plugin-dir` flags for more information.
|
||||
The initial state of the skeleton is a simple task that outputs a greeting. You
|
||||
can try it out by starting a Nomad server and client and running the job
|
||||
provided in the `config` folder:
|
||||
|
||||
```sh
|
||||
$ make build
|
||||
go build
|
||||
nomad agent -dev -config=./config/client.hcl -plugin-dir=$(PWD)
|
||||
|
||||
# in another shell
|
||||
nomad run ./config/example.nomad
|
||||
```
|
||||
|
||||
Makefile and project module structure were inspired by [Sylab's singularity]() driver.
|
||||
You should rename the project's root folder and the `hello` module to fit your
|
||||
own driver.
|
||||
|
||||
Code Organization
|
||||
-----------------
|
||||
The skeleton driver comes with an in memory task state store (see state.go).
|
||||
This in-memory map is for storing runtime details (like a process id). The details
|
||||
of what to store is left to the implementation of the runtime driver.
|
||||
Fields stored in the base implementation in this skeleton can be found in the `taskHandle` struct.
|
||||
-------------------
|
||||
The skeleton driver comes with an in memory task state store (see
|
||||
`hello/state.go`). This in-memory map is for storing runtime details (like a
|
||||
process id). The details of what to store is left to the implementation of the
|
||||
task driver. Fields stored in the base implementation in this skeleton can be
|
||||
found in the `taskHandle` struct.
|
||||
|
|
7
config/client.hcl
Normal file
7
config/client.hcl
Normal file
|
@ -0,0 +1,7 @@
|
|||
log_level = "TRACE"
|
||||
|
||||
plugin "nomad-runtime-driver-skeleton" {
|
||||
config {
|
||||
shell = "bash"
|
||||
}
|
||||
}
|
14
config/example.nomad
Normal file
14
config/example.nomad
Normal file
|
@ -0,0 +1,14 @@
|
|||
job "example" {
|
||||
datacenters = ["dc1"]
|
||||
type = "batch"
|
||||
|
||||
group "example" {
|
||||
task "hello-world" {
|
||||
driver = "hello-world-example"
|
||||
|
||||
config {
|
||||
greeting = "hello"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
go.mod
120
go.mod
|
@ -1,49 +1,85 @@
|
|||
module github.com/hashicorp/nomad-driver-skeleton
|
||||
module github.com/hashicorp/nomad-runtime-driver-skeleton
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/LK4D4/joincontext v0.0.0-20171026170139-1724345da6d5 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.7 // indirect
|
||||
github.com/go-ole/go-ole v1.2.2 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/gorhill/cronexpr v0.0.0-20140423231348-a557574d6c02 // indirect
|
||||
github.com/hashicorp/consul v1.0.7 // indirect
|
||||
github.com/hashicorp/go-hclog v0.8.0
|
||||
github.com/hashicorp/go-plugin v0.0.0-20190212232519-b838ffee39ce // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3 // indirect
|
||||
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.1 // indirect
|
||||
github.com/hashicorp/go-version v1.0.0 // indirect
|
||||
github.com/hashicorp/hcl v0.0.0-20161101180025-6e968a3fcdcb // indirect
|
||||
github.com/hashicorp/memberlist v0.1.3 // indirect
|
||||
github.com/hashicorp/nomad v0.9.0-rc2
|
||||
github.com/hashicorp/raft v0.0.0-20190104133720-9c733b2b7f53 // indirect
|
||||
github.com/hashicorp/serf v0.0.0-20180119224300-b6017ae61f44 // indirect
|
||||
github.com/hashicorp/vault v1.1.0 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
|
||||
github.com/hpcloud/tail v0.0.0-20180514194441-a1dbeea552b7 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/mitchellh/copystructure v0.0.0-20170525013902-d23ffcb85de3 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
github.com/mitchellh/hashstructure v0.0.0-20160118175604-1ef5c71b025a // indirect
|
||||
github.com/mitchellh/mapstructure v1.1.2 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||
github.com/pascaldekloe/goe v0.1.0 // indirect
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 // indirect
|
||||
github.com/shirou/gopsutil v0.0.0-20190131151121-071446942108 // indirect
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 // indirect
|
||||
github.com/hashicorp/consul-template v0.23.0
|
||||
github.com/hashicorp/go-hclog v0.9.1
|
||||
github.com/hashicorp/go-plugin v1.0.1
|
||||
github.com/hashicorp/go-version v1.2.0 // indirect
|
||||
github.com/hashicorp/nomad v0.10.0
|
||||
github.com/hashicorp/raft v1.1.1 // indirect
|
||||
github.com/hpcloud/tail v1.0.0 // indirect
|
||||
github.com/kr/pretty v0.1.0
|
||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b // indirect
|
||||
github.com/shirou/gopsutil v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
||||
github.com/ugorji/go v0.0.0-20170620060102-0053ebfd9d0e // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.2+incompatible // indirect
|
||||
github.com/zclconf/go-cty v0.0.0-20180718220526-02bd58e97b57 // indirect
|
||||
golang.org/x/sys v0.0.0-20190220154126-629670e5acc5 // indirect
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||
google.golang.org/appengine v1.4.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20190219182410-082222b4a5c5 // indirect
|
||||
google.golang.org/grpc v1.18.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
|
||||
github.com/ugorji/go v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/zclconf/go-cty v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf // indirect
|
||||
google.golang.org/grpc v1.22.0
|
||||
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
)
|
||||
|
||||
// don't use shirou/gopsutil, use the hashicorp fork
|
||||
replace github.com/shirou/gopsutil => github.com/hashicorp/gopsutil v0.0.0-20180427102116-62d5761ddb7d
|
||||
|
||||
// don't use ugorji/go, use the hashicorp fork
|
||||
replace github.com/ugorji/go => github.com/hashicorp/go-msgpack v0.0.0-20190927083313-23165f7bc3c2
|
||||
|
||||
// fix the version of hashicorp/go-msgpack to 96ddbed8d05b
|
||||
replace github.com/hashicorp/go-msgpack => github.com/hashicorp/go-msgpack v0.0.0-20191101193846-96ddbed8d05b
|
||||
|
||||
//require (
|
||||
// github.com/LK4D4/joincontext v0.0.0-20171026170139-1724345da6d5 // indirect
|
||||
// github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||
// github.com/fsnotify/fsnotify v1.4.7 // indirect
|
||||
// github.com/go-ole/go-ole v1.2.2 // indirect
|
||||
// github.com/golang/snappy v0.0.1 // indirect
|
||||
// github.com/gorhill/cronexpr v0.0.0-20140423231348-a557574d6c02 // indirect
|
||||
// github.com/hashicorp/consul v1.0.7 // indirect
|
||||
// github.com/hashicorp/go-hclog v0.8.0
|
||||
// github.com/hashicorp/go-plugin v0.0.0-20190212232519-b838ffee39ce // indirect
|
||||
// github.com/hashicorp/go-retryablehttp v0.5.3 // indirect
|
||||
// github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 // indirect
|
||||
// github.com/hashicorp/go-uuid v1.0.1 // indirect
|
||||
// github.com/hashicorp/go-version v1.0.0 // indirect
|
||||
// github.com/hashicorp/hcl v0.0.0-20161101180025-6e968a3fcdcb // indirect
|
||||
// github.com/hashicorp/memberlist v0.1.3 // indirect
|
||||
// github.com/hashicorp/nomad v0.9.0-rc2
|
||||
// github.com/hashicorp/raft v0.0.0-20190104133720-9c733b2b7f53 // indirect
|
||||
// github.com/hashicorp/serf v0.0.0-20180119224300-b6017ae61f44 // indirect
|
||||
// github.com/hashicorp/vault v1.1.0 // indirect
|
||||
// github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
|
||||
// github.com/hpcloud/tail v0.0.0-20180514194441-a1dbeea552b7 // indirect
|
||||
// github.com/kr/pretty v0.1.0 // indirect
|
||||
// github.com/mitchellh/copystructure v0.0.0-20170525013902-d23ffcb85de3 // indirect
|
||||
// github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
// github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
// github.com/mitchellh/hashstructure v0.0.0-20160118175604-1ef5c71b025a // indirect
|
||||
// github.com/mitchellh/mapstructure v1.1.2 // indirect
|
||||
// github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||
// github.com/pascaldekloe/goe v0.1.0 // indirect
|
||||
// github.com/pierrec/lz4 v2.0.5+incompatible // indirect
|
||||
// github.com/pkg/errors v0.8.1 // indirect
|
||||
// github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 // indirect
|
||||
// github.com/shirou/gopsutil v0.0.0-20190131151121-071446942108 // indirect
|
||||
// github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
||||
// github.com/ugorji/go v0.0.0-20170620060102-0053ebfd9d0e // indirect
|
||||
// github.com/vmihailenco/msgpack v4.0.2+incompatible // indirect
|
||||
// github.com/zclconf/go-cty v0.0.0-20180718220526-02bd58e97b57 // indirect
|
||||
// golang.org/x/sys v0.0.0-20190220154126-629670e5acc5 // indirect
|
||||
// golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||
// google.golang.org/appengine v1.4.0 // indirect
|
||||
// google.golang.org/genproto v0.0.0-20190219182410-082222b4a5c5 // indirect
|
||||
// google.golang.org/grpc v1.18.0 // indirect
|
||||
// gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
// gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
|
||||
// gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
//)
|
||||
|
|
170
go.sum
170
go.sum
|
@ -1,94 +1,199 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/LK4D4/joincontext v0.0.0-20171026170139-1724345da6d5 h1:U7q69tqXiCf6m097GRlNQB0/6SI1qWIOHYHhCEvDxF4=
|
||||
github.com/LK4D4/joincontext v0.0.0-20171026170139-1724345da6d5/go.mod h1:nxQPcNPR/34g+HcK2hEsF99O+GJgIkW/OmPl8wtzhmk=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM=
|
||||
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/frankban/quicktest v1.4.0/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
|
||||
github.com/go-ole/go-ole v1.2.2 h1:QNWhweRd9D5Py2rRVboZ2L4SEoW/dyraWJCc8bgS8kE=
|
||||
github.com/go-ole/go-ole v1.2.2/go.mod h1:pnvuG7BrDMZ8ifMurTQmxwhQM/odqm9sSqNe5BUI7v4=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
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/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0 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/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/gorhill/cronexpr v0.0.0-20140423231348-a557574d6c02 h1:Spo+4PFAGDqULAsZ7J69MOxq4/fwgZ0zvmDTBqpq7yU=
|
||||
github.com/gorhill/cronexpr v0.0.0-20140423231348-a557574d6c02/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY=
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
|
||||
github.com/hashicorp/consul v1.0.7 h1:GuHjalgSkzFdlBVxfKzlLJJ6bT4VCvAXV678UWpuJbw=
|
||||
github.com/hashicorp/consul v1.0.7/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
|
||||
github.com/hashicorp/consul v1.6.2 h1:OjnFfc1vHPLtwrYAMC9HlJ4WTSmgBTq2erWuBERm3hY=
|
||||
github.com/hashicorp/consul-template v0.23.0 h1:cEQ3eEK8XRj0DdvLAcqNd/eSV2IAnSj+zPJeo/5C330=
|
||||
github.com/hashicorp/consul-template v0.23.0/go.mod h1:KcTEopo2kCp7kww0d4oG7d3oX2Uou4hzb1Rs/wY9TVI=
|
||||
github.com/hashicorp/consul/api v1.2.0 h1:oPsuzLp2uk7I7rojPKuncWbZ+m5TMoD4Ivs+2Rkeh4Y=
|
||||
github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw=
|
||||
github.com/hashicorp/consul/sdk v0.2.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-gatedio v0.5.0/go.mod h1:Lr3t8L6IyxD3DAeaUxGcgl2JnRUpWMCsmBl4Omu/2t4=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.8.0 h1:z3ollgGRg8RjfJH6UVBaG54R70GFd++QOkvnJH3VSBY=
|
||||
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.9.1 h1:9PZfAcVEvez4yhLH2TBU64/h/z4xlFI80cWXRrxuKuM=
|
||||
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc=
|
||||
github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20190927083313-23165f7bc3c2 h1:kZFZ8oAS1Rfk3QG3dgd0iiBNnOf0cQliaWZgfRz1eQw=
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20190927083313-23165f7bc3c2/go.mod h1:CNnb6ZvPKQMR+Hz6QI76TRCBNgyJIxEmTBn+1u8HELw=
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20191101193846-96ddbed8d05b h1:lB+3FXrgs94Mz066O5Yz59m3l/O0uEsf2jPiZyUpKTU=
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20191101193846-96ddbed8d05b/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4=
|
||||
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-plugin v0.0.0-20190212232519-b838ffee39ce h1:I3KJUf8jyMubLFeHit2ibr9YeVxJX2CXMXVM6xlB+Qk=
|
||||
github.com/hashicorp/go-plugin v0.0.0-20190212232519-b838ffee39ce/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
|
||||
github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
|
||||
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E=
|
||||
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
|
||||
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/gopsutil v0.0.0-20180427102116-62d5761ddb7d h1:SFth5WDiMWzND4B4iAGynG5MUhlLeKPaojk8u2qMVQ0=
|
||||
github.com/hashicorp/gopsutil v0.0.0-20180427102116-62d5761ddb7d/go.mod h1:Mz8xr0ujmCW1qsmWMIUDOc+RgaN9QMvrgnBzQF12nYM=
|
||||
github.com/hashicorp/hcl v0.0.0-20161101180025-6e968a3fcdcb h1:S76lj//ZzHoMTiOOi3P9NcBQhoUxi4ZnYTcGqQnkCcE=
|
||||
github.com/hashicorp/hcl v0.0.0-20161101180025-6e968a3fcdcb/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/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/nomad v0.9.0-rc2 h1:sN6Dy8ve/fwrWFSNzYSikYaXqqoUm1o4pqtJIOTaRQo=
|
||||
github.com/hashicorp/nomad v0.9.0-rc2/go.mod h1:WRaKjdO1G2iqi86TvTjIYtKTyxg4pl7NLr9InxtWaI0=
|
||||
github.com/hashicorp/nomad v0.10.0 h1:GDoqEklnNV9McCFp7PmcD96xGgSzKLfpJtJM96cOTH0=
|
||||
github.com/hashicorp/nomad v0.10.0/go.mod h1:WRaKjdO1G2iqi86TvTjIYtKTyxg4pl7NLr9InxtWaI0=
|
||||
github.com/hashicorp/raft v0.0.0-20190104133720-9c733b2b7f53 h1:Kcs5PApYrQyn+RLWUvk3eQhKNGDj8M/r1mt0X8p9HAA=
|
||||
github.com/hashicorp/raft v0.0.0-20190104133720-9c733b2b7f53/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI=
|
||||
github.com/hashicorp/raft v1.1.1 h1:HJr7UE1x/JrJSc9Oy6aDBHtNHUUBHjcQjTgvUVihoZs=
|
||||
github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
|
||||
github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
|
||||
github.com/hashicorp/serf v0.0.0-20180119224300-b6017ae61f44 h1:uY64+3NuMxFyc9+nchedxCBabBhU67QF+ymrIedtexE=
|
||||
github.com/hashicorp/serf v0.0.0-20180119224300-b6017ae61f44/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE=
|
||||
github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/serf v0.8.3 h1:MWYcmct5EtKz0efYooPcL0yNkem+7kWxqXDi/UIh+8k=
|
||||
github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k=
|
||||
github.com/hashicorp/vault v1.1.0 h1:v79NUgO5xCZnXVzUkIqFOXtP8YhpnHAi1fk3eo9cuOE=
|
||||
github.com/hashicorp/vault v1.1.0/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
|
||||
github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU=
|
||||
github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
|
||||
github.com/hashicorp/vault/api v1.0.5-0.20190730042357-746c0b111519/go.mod h1:i9PKqwFko/s/aihU1uuHGh/FaQS+Xcgvd9dvnfAvQb0=
|
||||
github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8=
|
||||
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
|
||||
github.com/hashicorp/vault/sdk v0.1.14-0.20190730042320-0dc007d98cc8/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hpcloud/tail v0.0.0-20180514194441-a1dbeea552b7 h1:lus8hJKTrh146vNoUWNHv2F1jdtsud5ajNL0/YndJUw=
|
||||
github.com/hpcloud/tail v0.0.0-20180514194441-a1dbeea552b7/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
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 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v0.0.0-20170525013902-d23ffcb85de3 h1:dECZqiJYhKdj9QlLpiQaRDXHDXRTdiyZI3owdDGhlYY=
|
||||
github.com/mitchellh/copystructure v0.0.0-20170525013902-d23ffcb85de3/go.mod h1:eOsF2yLPlBBJPvD+nhl5QMTBSOBbOph6N7j/IDUw7PY=
|
||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
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-20190716172923-621e5597135b h1:9+ke9YJ9KGWw5ANXK6ozjoK47uI3uNbXv4YVINBnGm8=
|
||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/hashstructure v0.0.0-20160118175604-1ef5c71b025a h1:2p2+qxgbcNvMPt/Q/Nfd0mEHJokUf7rHAYDVQH1dKpM=
|
||||
github.com/mitchellh/hashstructure v0.0.0-20160118175604-1ef5c71b025a/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
|
||||
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||
|
@ -100,12 +205,22 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw
|
|||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.2.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shirou/gopsutil v0.0.0-20190131151121-071446942108 h1:XXgDK65TPH+Qbo2sdYHldM5avclwThBXVYZHxroFkTQ=
|
||||
|
@ -116,50 +231,105 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go v0.0.0-20170620060102-0053ebfd9d0e h1:Eurc/1QbldPTy6eU1WSHOH1vuFc7BAUdKDWSsZd4ieo=
|
||||
github.com/ugorji/go v0.0.0-20170620060102-0053ebfd9d0e/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible h1:wapg9xDUZDzGCNFlwc5SqI1rvcciqcxEHac4CYj89xI=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmihailenco/msgpack v4.0.2+incompatible h1:6ujmmycMfB62Mwv2N4atpnf8CKLSzhgodqMenpELKIQ=
|
||||
github.com/vmihailenco/msgpack v4.0.2+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/zclconf/go-cty v0.0.0-20180718220526-02bd58e97b57 h1:FWjfWQtNK83IJMe58FfMCSNkySe0PO9TvrQyLOKcPxw=
|
||||
github.com/zclconf/go-cty v0.0.0-20180718220526-02bd58e97b57/go.mod h1:LnDKxj8gN4aatfXUqmUNooaDjvmDcLPbAN3hYBIVoJE=
|
||||
github.com/zclconf/go-cty v1.1.0 h1:uJwc9HiBOCpoKIObTQaLR+tsEXx1HBHnOsOOpcdhZgw=
|
||||
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953 h1:LuZIitY8waaxUfNIdtajyE/YzA/zyf0YxXG27VpLrkg=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
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-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190220154126-629670e5acc5 h1:3Nsfe5Xa1wTt01QxlAFIY5j9ycDtS+d7mhvI8ZY5bn0=
|
||||
golang.org/x/sys v0.0.0-20190220154126-629670e5acc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5 h1:sM3evRHxE/1RuMe1FYAL3j7C7fUfIjkbE+NiDAYUF8U=
|
||||
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365 h1:SaXEMXhWzMJThc05vu6uh61Q245r4KaWMrsTedk0FDc=
|
||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
|
||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190219182410-082222b4a5c5 h1:SdCO7As+ChE1iV3IjBleIIWlj8VjZWuYEUF5pjELOOQ=
|
||||
google.golang.org/genproto v0.0.0-20190219182410-082222b4a5c5/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQNFHMSRPjT2RkOV4OXM7P5TVy9xATo=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.18.0 h1:IZl7mfBGfbhYx2p2rKRtYgDFw6SBz+kclmxYrCksPPA=
|
||||
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw=
|
||||
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
640
hello/driver.go
Normal file
640
hello/driver.go
Normal file
|
@ -0,0 +1,640 @@
|
|||
package hello
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/consul-template/signals"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/nomad/drivers/shared/eventer"
|
||||
"github.com/hashicorp/nomad/drivers/shared/executor"
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
"github.com/hashicorp/nomad/plugins/drivers"
|
||||
"github.com/hashicorp/nomad/plugins/shared/hclspec"
|
||||
"github.com/hashicorp/nomad/plugins/shared/structs"
|
||||
)
|
||||
|
||||
const (
|
||||
// pluginName is the name of the plugin
|
||||
// this is used for logging and (along with the version) for uniquely
|
||||
// identifying plugin binaries fingerprinted by the client
|
||||
pluginName = "hello-world-example"
|
||||
|
||||
// pluginVersion allows the client to identify and use newer versions of
|
||||
// an installed plugin
|
||||
pluginVersion = "v0.1.0"
|
||||
|
||||
// fingerprintPeriod is the interval at which the plugin will send
|
||||
// fingerprint responses
|
||||
fingerprintPeriod = 30 * time.Second
|
||||
|
||||
// taskHandleVersion is the version of task handle which this plugin sets
|
||||
// and understands how to decode
|
||||
// this is used to allow modification and migration of the task schema
|
||||
// used by the plugin
|
||||
taskHandleVersion = 1
|
||||
)
|
||||
|
||||
var (
|
||||
// pluginInfo describes the plugin
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the specification of the plugin's configuration
|
||||
// this is used to validate the configuration specified for the plugin
|
||||
// on the client.
|
||||
// this is not global, but can be specified on a per-client basis.
|
||||
configSpec = hclspec.NewObject(map[string]*hclspec.Spec{
|
||||
// TODO: define plugin's agent configuration schema.
|
||||
//
|
||||
// The schema should be defined using HCL specs and it will be used to
|
||||
// validate the agent configuration provided by the user in the
|
||||
// `plugin` stanza (https://www.nomadproject.io/docs/configuration/plugin.html).
|
||||
//
|
||||
// For example, for the schema below a valid configuration would be:
|
||||
//
|
||||
// plugin "hello-driver-plugin" {
|
||||
// config {
|
||||
// shell = "fish"
|
||||
// }
|
||||
// }
|
||||
"shell": hclspec.NewDefault(
|
||||
hclspec.NewAttr("shell", "string", false),
|
||||
hclspec.NewLiteral(`"bash"`),
|
||||
),
|
||||
})
|
||||
|
||||
// taskConfigSpec is the specification of the plugin's configuration for
|
||||
// a task
|
||||
// this is used to validated the configuration specified for the plugin
|
||||
// when a job is submitted.
|
||||
taskConfigSpec = hclspec.NewObject(map[string]*hclspec.Spec{
|
||||
// TODO: define plugin's task configuration schema
|
||||
//
|
||||
// The schema should be defined using HCL specs and it will be used to
|
||||
// validate the task configuration provided by the user when they
|
||||
// submit a job.
|
||||
//
|
||||
// For example, for the schema below a valid task would be:
|
||||
// job "example" {
|
||||
// group "example" {
|
||||
// task "say-hi" {
|
||||
// driver = "hello-driver-plugin"
|
||||
// config {
|
||||
// greeting = "Hi"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
"greeting": hclspec.NewDefault(
|
||||
hclspec.NewAttr("greeting", "string", false),
|
||||
hclspec.NewLiteral(`"Hello, World!"`),
|
||||
),
|
||||
})
|
||||
|
||||
// capabilities indicates what optional features this driver supports
|
||||
// this should be set according to the target run time.
|
||||
capabilities = &drivers.Capabilities{
|
||||
// TODO: set plugin's capabilities
|
||||
//
|
||||
// The plugin's capabilities signal Nomad which extra functionalities
|
||||
// are supported. For a list of available options check the docs page:
|
||||
// https://godoc.org/github.com/hashicorp/nomad/plugins/drivers#Capabilities
|
||||
SendSignals: true,
|
||||
Exec: false,
|
||||
}
|
||||
)
|
||||
|
||||
// Config contains configuration information for the plugin
|
||||
type Config struct {
|
||||
// TODO: create decoded plugin configuration struct
|
||||
//
|
||||
// This struct is the decoded version of the schema defined in the
|
||||
// configSpec variable above. It's used to convert the HCL configuration
|
||||
// passed by the Nomad agent into Go contructs.
|
||||
Shell string `codec:"shell"`
|
||||
}
|
||||
|
||||
// TaskConfig contains configuration information for a task that runs with
|
||||
// this plugin
|
||||
type TaskConfig struct {
|
||||
// TODO: create decoded plugin task configuration struct
|
||||
//
|
||||
// This struct is the decoded version of the schema defined in the
|
||||
// taskConfigSpec variable above. It's used to convert the string
|
||||
// configuration for the task into Go contructs.
|
||||
Greeting string `codec:"greeting"`
|
||||
}
|
||||
|
||||
// TaskState is the runtime state which is encoded in the handle returned to
|
||||
// Nomad client.
|
||||
// This information is needed to rebuild the task state and handler during
|
||||
// recovery.
|
||||
type TaskState struct {
|
||||
ReattachConfig *structs.ReattachConfig
|
||||
TaskConfig *drivers.TaskConfig
|
||||
StartedAt time.Time
|
||||
|
||||
// TODO: add any extra important values that must be persisted in order
|
||||
// to restore a task.
|
||||
//
|
||||
// The plugin keeps track of its running tasks in a in-memory data
|
||||
// structure. If the plugin crashes, this data will be lost, so Nomad
|
||||
// will respawn a new instance of the plugin and try to restore its
|
||||
// in-memory representation of the running tasks using the RecoverTask()
|
||||
// method below.
|
||||
Pid int
|
||||
}
|
||||
|
||||
// HelloDriverPlugin is an example driver plugin. When provisioned in a job,
|
||||
// the taks will output a greet specified by the user.
|
||||
type HelloDriverPlugin struct {
|
||||
// eventer is used to handle multiplexing of TaskEvents calls such that an
|
||||
// event can be broadcast to all callers
|
||||
eventer *eventer.Eventer
|
||||
|
||||
// config is the plugin configuration set by the SetConfig RPC
|
||||
config *Config
|
||||
|
||||
// nomadConfig is the client config from Nomad
|
||||
nomadConfig *base.ClientDriverConfig
|
||||
|
||||
// tasks is the in memory datastore mapping taskIDs to driver handles
|
||||
tasks *taskStore
|
||||
|
||||
// ctx is the context for the driver. It is passed to other subsystems to
|
||||
// coordinate shutdown
|
||||
ctx context.Context
|
||||
|
||||
// signalShutdown is called when the driver is shutting down and cancels
|
||||
// the ctx passed to any subsystems
|
||||
signalShutdown context.CancelFunc
|
||||
|
||||
// logger will log to the Nomad agent
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
// NewPlugin returns a new example driver plugin
|
||||
func NewPlugin(logger log.Logger) drivers.DriverPlugin {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
logger = logger.Named(pluginName)
|
||||
|
||||
return &HelloDriverPlugin{
|
||||
eventer: eventer.NewEventer(ctx, logger),
|
||||
config: &Config{},
|
||||
tasks: newTaskStore(),
|
||||
ctx: ctx,
|
||||
signalShutdown: cancel,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// PluginInfo returns information describing the plugin.
|
||||
func (d *HelloDriverPlugin) PluginInfo() (*base.PluginInfoResponse, error) {
|
||||
return pluginInfo, nil
|
||||
}
|
||||
|
||||
// ConfigSchema returns the plugin configuration schema.
|
||||
func (d *HelloDriverPlugin) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
// SetConfig is called by the client to pass the configuration for the plugin.
|
||||
func (d *HelloDriverPlugin) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Save the configuration to the plugin
|
||||
d.config = &config
|
||||
|
||||
// TODO: parse and validated any configuration value if necessary.
|
||||
//
|
||||
// If your driver agent configuration requires any complex validation
|
||||
// (some dependency between attributes) or special data parsing (the
|
||||
// string "10s" into a time.Interval) you can do it here and update the
|
||||
// value in d.config.
|
||||
//
|
||||
// In the example below we check if the shell specified by the user is
|
||||
// supported by the plugin.
|
||||
shell := d.config.Shell
|
||||
if shell != "bash" && shell != "fish" {
|
||||
return fmt.Errorf("invalid shell %s", d.config.Shell)
|
||||
}
|
||||
|
||||
// Save the Nomad agent configuration
|
||||
if cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
|
||||
// TODO: initialize any extra requirements if necessary.
|
||||
//
|
||||
// Here you can use the config values to initialize any resources that are
|
||||
// shared by all tasks that use this driver, such as a daemon process.
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TaskConfigSchema returns the HCL schema for the configuration of a task.
|
||||
func (d *HelloDriverPlugin) TaskConfigSchema() (*hclspec.Spec, error) {
|
||||
return taskConfigSpec, nil
|
||||
}
|
||||
|
||||
// Capabilities returns the features supported by the driver.
|
||||
func (d *HelloDriverPlugin) Capabilities() (*drivers.Capabilities, error) {
|
||||
return capabilities, nil
|
||||
}
|
||||
|
||||
// Fingerprint returns a channel that will be used to send health information
|
||||
// and other driver specific node attributes.
|
||||
func (d *HelloDriverPlugin) Fingerprint(ctx context.Context) (<-chan *drivers.Fingerprint, error) {
|
||||
ch := make(chan *drivers.Fingerprint)
|
||||
go d.handleFingerprint(ctx, ch)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// handleFingerprint manages the channel and the flow of fingerprint data.
|
||||
func (d *HelloDriverPlugin) handleFingerprint(ctx context.Context, ch chan<- *drivers.Fingerprint) {
|
||||
defer close(ch)
|
||||
|
||||
// Nomad expects the initial fingerprint to be sent immediately
|
||||
ticker := time.NewTimer(0)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-d.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
// after the initial fingerprint we can set the proper fingerprint
|
||||
// period
|
||||
ticker.Reset(fingerprintPeriod)
|
||||
ch <- d.buildFingerprint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// buildFingerprint returns the driver's fingerprint data
|
||||
func (d *HelloDriverPlugin) buildFingerprint() *drivers.Fingerprint {
|
||||
fp := &drivers.Fingerprint{
|
||||
Attributes: map[string]*structs.Attribute{},
|
||||
Health: drivers.HealthStateHealthy,
|
||||
HealthDescription: drivers.DriverHealthy,
|
||||
}
|
||||
|
||||
// TODO: implement fingerprinting logic to populate health and driver
|
||||
// attributes.
|
||||
//
|
||||
// Fingerprinting is used by the plugin to relay two important information
|
||||
// to Nomad: health state and node attributes.
|
||||
//
|
||||
// If the plugin reports to be unhealthy, or doesn't send any fingerprint
|
||||
// data in the expected interval of time, Nomad will restart it.
|
||||
//
|
||||
// Node attributes can be used to report any relevant information about
|
||||
// the node in which the plugin is running (specific library availability,
|
||||
// installed versions of a software etc.). These attributes can then be
|
||||
// used by an operator to set job constrains.
|
||||
//
|
||||
// In the example below we check if the shell specified by the user exists
|
||||
// in the node.
|
||||
shell := d.config.Shell
|
||||
|
||||
cmd := exec.Command("which", shell)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return &drivers.Fingerprint{
|
||||
Health: drivers.HealthStateUndetected,
|
||||
HealthDescription: fmt.Sprintf("shell %s not found", shell),
|
||||
}
|
||||
}
|
||||
|
||||
// We also set the shell and its version as attributes
|
||||
cmd = exec.Command(shell, "--version")
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
d.logger.Warn("failed to find shell version: %v", err)
|
||||
} else {
|
||||
re := regexp.MustCompile("[0-9]\\.[0-9]\\.[0-9]")
|
||||
version := re.FindString(string(out))
|
||||
|
||||
fp.Attributes["driver.hello.shell_version"] = structs.NewStringAttribute(version)
|
||||
fp.Attributes["driver.hello.shell"] = structs.NewStringAttribute(shell)
|
||||
}
|
||||
|
||||
return fp
|
||||
}
|
||||
|
||||
// StartTask returns a task handle and a driver network if necessary.
|
||||
func (d *HelloDriverPlugin) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drivers.DriverNetwork, error) {
|
||||
if _, ok := d.tasks.Get(cfg.ID); ok {
|
||||
return nil, nil, fmt.Errorf("task with ID %q already started", cfg.ID)
|
||||
}
|
||||
|
||||
var driverConfig TaskConfig
|
||||
if err := cfg.DecodeDriverConfig(&driverConfig); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to decode driver config: %v", err)
|
||||
}
|
||||
|
||||
d.logger.Info("starting task", "driver_cfg", hclog.Fmt("%+v", driverConfig))
|
||||
handle := drivers.NewTaskHandle(taskHandleVersion)
|
||||
handle.Config = cfg
|
||||
|
||||
// TODO: implement driver specific mechanism to start the task.
|
||||
//
|
||||
// Once the task is started you will need to store any relevant runtime
|
||||
// information in a taskHandle and TaskState. The taskHandle will be
|
||||
// stored in-memory in the plugin and will be used to interact with the
|
||||
// task.
|
||||
//
|
||||
// The TaskState will be returned to the Nomad client inside a
|
||||
// drivers.TaskHandle instance. This TaskHandle will be sent back to plugin
|
||||
// if the task ever needs to be recovered, so the TaskState should contain
|
||||
// enough information to handle that.
|
||||
//
|
||||
// In the example below we use an executor to fork a process to run our
|
||||
// greeter. The executor is then stored in the handle so we can access it
|
||||
// later and the the plugin.Client is used to generate a reattach
|
||||
// configuration that can be used to recover communication with the task.
|
||||
executorConfig := &executor.ExecutorConfig{
|
||||
LogFile: filepath.Join(cfg.TaskDir().Dir, "executor.out"),
|
||||
LogLevel: "debug",
|
||||
}
|
||||
|
||||
exec, pluginClient, err := executor.CreateExecutor(d.logger, d.nomadConfig, executorConfig)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create executor: %v", err)
|
||||
}
|
||||
|
||||
echoCmd := fmt.Sprintf(`echo "%s"`, driverConfig.Greeting)
|
||||
execCmd := &executor.ExecCommand{
|
||||
Cmd: d.config.Shell,
|
||||
Args: []string{"-c", echoCmd},
|
||||
StdoutPath: cfg.StdoutPath,
|
||||
StderrPath: cfg.StderrPath,
|
||||
}
|
||||
|
||||
ps, err := exec.Launch(execCmd)
|
||||
if err != nil {
|
||||
pluginClient.Kill()
|
||||
return nil, nil, fmt.Errorf("failed to launch command with executor: %v", err)
|
||||
}
|
||||
|
||||
h := &taskHandle{
|
||||
exec: exec,
|
||||
pid: ps.Pid,
|
||||
pluginClient: pluginClient,
|
||||
taskConfig: cfg,
|
||||
procState: drivers.TaskStateRunning,
|
||||
startedAt: time.Now().Round(time.Millisecond),
|
||||
logger: d.logger,
|
||||
}
|
||||
|
||||
driverState := TaskState{
|
||||
ReattachConfig: structs.ReattachConfigFromGoPlugin(pluginClient.ReattachConfig()),
|
||||
Pid: ps.Pid,
|
||||
TaskConfig: cfg,
|
||||
StartedAt: h.startedAt,
|
||||
}
|
||||
|
||||
if err := handle.SetDriverState(&driverState); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to set driver state: %v", err)
|
||||
}
|
||||
|
||||
d.tasks.Set(cfg.ID, h)
|
||||
go h.run()
|
||||
return handle, nil, nil
|
||||
}
|
||||
|
||||
// RecoverTask recreates the in-memory state of a task from a TaskHandle.
|
||||
func (d *HelloDriverPlugin) RecoverTask(handle *drivers.TaskHandle) error {
|
||||
if handle == nil {
|
||||
return fmt.Errorf("error: handle cannot be nil")
|
||||
}
|
||||
|
||||
if _, ok := d.tasks.Get(handle.Config.ID); ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var taskState TaskState
|
||||
if err := handle.GetDriverState(&taskState); err != nil {
|
||||
return fmt.Errorf("failed to decode task state from handle: %v", err)
|
||||
}
|
||||
|
||||
var driverConfig TaskConfig
|
||||
if err := taskState.TaskConfig.DecodeDriverConfig(&driverConfig); err != nil {
|
||||
return fmt.Errorf("failed to decode driver config: %v", err)
|
||||
}
|
||||
|
||||
// TODO: implement driver specific logic to recover a task.
|
||||
//
|
||||
// Recovering a task involves recreating and storing a taskHandle as if the
|
||||
// task was just started.
|
||||
//
|
||||
// In the example below we use the executor to re-attach to the process
|
||||
// that was created when the task first started.
|
||||
plugRC, err := structs.ReattachConfigToGoPlugin(taskState.ReattachConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build ReattachConfig from taskConfig state: %v", err)
|
||||
}
|
||||
|
||||
execImpl, pluginClient, err := executor.ReattachToExecutor(plugRC, d.logger)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to reattach to executor: %v", err)
|
||||
}
|
||||
|
||||
h := &taskHandle{
|
||||
exec: execImpl,
|
||||
pid: taskState.Pid,
|
||||
pluginClient: pluginClient,
|
||||
taskConfig: taskState.TaskConfig,
|
||||
procState: drivers.TaskStateRunning,
|
||||
startedAt: taskState.StartedAt,
|
||||
exitResult: &drivers.ExitResult{},
|
||||
}
|
||||
|
||||
d.tasks.Set(taskState.TaskConfig.ID, h)
|
||||
|
||||
go h.run()
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitTask returns a channel used to notify Nomad when a task exits.
|
||||
func (d *HelloDriverPlugin) WaitTask(ctx context.Context, taskID string) (<-chan *drivers.ExitResult, error) {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return nil, drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
ch := make(chan *drivers.ExitResult)
|
||||
go d.handleWait(ctx, handle, ch)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (d *HelloDriverPlugin) handleWait(ctx context.Context, handle *taskHandle, ch chan *drivers.ExitResult) {
|
||||
defer close(ch)
|
||||
var result *drivers.ExitResult
|
||||
|
||||
// TODO: implement driver specific logic to notify Nomad the task has been
|
||||
// completed and what was the exit result.
|
||||
//
|
||||
// When a result is sent in the result channel Nomad will stop the task and
|
||||
// emit an event that an operator can use to get an insight on why the task
|
||||
// stopped.
|
||||
//
|
||||
// In the example below we block and wait until the executor finishes
|
||||
// running, at which point we send the exit code and signal in the result
|
||||
// channel.
|
||||
ps, err := handle.exec.Wait(ctx)
|
||||
if err != nil {
|
||||
result = &drivers.ExitResult{
|
||||
Err: fmt.Errorf("executor: error waiting on process: %v", err),
|
||||
}
|
||||
} else {
|
||||
result = &drivers.ExitResult{
|
||||
ExitCode: ps.ExitCode,
|
||||
Signal: ps.Signal,
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-d.ctx.Done():
|
||||
return
|
||||
case ch <- result:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StopTask stops a running task with the given signal and within the timeout window.
|
||||
func (d *HelloDriverPlugin) StopTask(taskID string, timeout time.Duration, signal string) error {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
// TODO: implement driver specific logic to stop a task.
|
||||
//
|
||||
// The StopTask function is expected to stop a running task by sending the
|
||||
// given signal to it. If the task does not stop during the given timeout,
|
||||
// the driver must forcefully kill the task.
|
||||
//
|
||||
// In the example below we let the executor handle the task shutdown
|
||||
// process for us, but you might need to customize this for your own
|
||||
// implementation.
|
||||
if err := handle.exec.Shutdown(signal, timeout); err != nil {
|
||||
if handle.pluginClient.Exited() {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("executor Shutdown failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DestroyTask cleans up and removes a task that has terminated.
|
||||
func (d *HelloDriverPlugin) DestroyTask(taskID string, force bool) error {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
if handle.IsRunning() && !force {
|
||||
return fmt.Errorf("cannot destroy running task")
|
||||
}
|
||||
|
||||
// TODO: implement driver specific logic to destroy a complete task.
|
||||
//
|
||||
// Destroying a task includes removing any resources used by task and any
|
||||
// local references in the plugin. If force is set to true the task should
|
||||
// be destroyed even if it's currently running.
|
||||
//
|
||||
// In the example below we use the executor to force shutdown the task
|
||||
// (timeout equals 0).
|
||||
if !handle.pluginClient.Exited() {
|
||||
if err := handle.exec.Shutdown("", 0); err != nil {
|
||||
handle.logger.Error("destroying executor failed", "err", err)
|
||||
}
|
||||
|
||||
handle.pluginClient.Kill()
|
||||
}
|
||||
|
||||
d.tasks.Delete(taskID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// InspectTask returns detailed status information for the referenced taskID.
|
||||
func (d *HelloDriverPlugin) InspectTask(taskID string) (*drivers.TaskStatus, error) {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return nil, drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
return handle.TaskStatus(), nil
|
||||
}
|
||||
|
||||
// TaskStats returns a channel which the driver should send stats to at the given interval.
|
||||
func (d *HelloDriverPlugin) TaskStats(ctx context.Context, taskID string, interval time.Duration) (<-chan *drivers.TaskResourceUsage, error) {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return nil, drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
// TODO: implement driver specific logic to send task stats.
|
||||
//
|
||||
// This function returns a channel that Nomad will use to listen for task
|
||||
// stats (e.g., CPU and memory usage) in a given interval. It should send
|
||||
// stats until the context is canceled or the task stops running.
|
||||
//
|
||||
// In the example below we use the Stats function provided by the executor,
|
||||
// but you can build a set of functions similar to the fingerprint process.
|
||||
return handle.exec.Stats(ctx, interval)
|
||||
}
|
||||
|
||||
// TaskEvents returns a channel that the plugin can use to emit task related events.
|
||||
func (d *HelloDriverPlugin) TaskEvents(ctx context.Context) (<-chan *drivers.TaskEvent, error) {
|
||||
return d.eventer.TaskEvents(ctx)
|
||||
}
|
||||
|
||||
// SignalTask forwards a signal to a task.
|
||||
// This is an optional capability.
|
||||
func (d *HelloDriverPlugin) SignalTask(taskID string, signal string) error {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
// TODO: implement driver specific signal handling logic.
|
||||
//
|
||||
// The given signal must be forwarded to the target taskID. If this plugin
|
||||
// doesn't support receiving signals (capability SendSignals is set to
|
||||
// false) you can just return nil.
|
||||
sig := os.Interrupt
|
||||
if s, ok := signals.SignalLookup[signal]; ok {
|
||||
sig = s
|
||||
} else {
|
||||
d.logger.Warn("unknown signal to send to task, using SIGINT instead", "signal", signal, "task_id", handle.taskConfig.ID)
|
||||
|
||||
}
|
||||
return handle.exec.Signal(sig)
|
||||
}
|
||||
|
||||
// ExecTask returns the result of executing the given command inside a task.
|
||||
// This is an optional capability.
|
||||
func (d *HelloDriverPlugin) ExecTask(taskID string, cmd []string, timeout time.Duration) (*drivers.ExecTaskResult, error) {
|
||||
// TODO: implement driver specific logic to execute commands in a task.
|
||||
return nil, fmt.Errorf("This driver does not support exec")
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package skeleton
|
||||
package hello
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -7,6 +7,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/nomad/drivers/shared/executor"
|
||||
"github.com/hashicorp/nomad/plugins/drivers"
|
||||
)
|
||||
|
||||
|
@ -14,17 +16,20 @@ import (
|
|||
// such as process ID if this is a local task or other meta
|
||||
// data if this driver deals with external APIs
|
||||
type taskHandle struct {
|
||||
pid int
|
||||
logger hclog.Logger
|
||||
|
||||
// stateLock syncs access to all fields below
|
||||
stateLock sync.RWMutex
|
||||
|
||||
logger hclog.Logger
|
||||
exec executor.Executor
|
||||
pluginClient *plugin.Client
|
||||
taskConfig *drivers.TaskConfig
|
||||
procState drivers.TaskState
|
||||
startedAt time.Time
|
||||
completedAt time.Time
|
||||
exitResult *drivers.ExitResult
|
||||
|
||||
// TODO: add any extra relevant information about the task.
|
||||
pid int
|
||||
}
|
||||
|
||||
func (h *taskHandle) TaskStatus() *drivers.TaskStatus {
|
||||
|
@ -57,23 +62,19 @@ func (h *taskHandle) run() {
|
|||
}
|
||||
h.stateLock.Unlock()
|
||||
|
||||
// TODO: wait for your task to complete and upate its state.
|
||||
ps, err := h.exec.Wait(context.Background())
|
||||
h.stateLock.Lock()
|
||||
defer h.stateLock.Unlock()
|
||||
|
||||
// Implement running the task here, this is driver specific
|
||||
}
|
||||
|
||||
func (h *taskHandle) stats(ctx context.Context, interval time.Duration) (<-chan *drivers.TaskResourceUsage, error) {
|
||||
ch := make(chan *drivers.TaskResourceUsage)
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// shutdown shuts down the container, with `timeout` grace period
|
||||
// before killing the container with SIGKILL.
|
||||
func (h *taskHandle) shutdown(timeout time.Duration) error {
|
||||
// Implement shutdown of the task. Shutdown should be tried
|
||||
// gracefully first. If its past the timeout, then this method
|
||||
// should do a hard shutdown and return
|
||||
return nil
|
||||
if err != nil {
|
||||
h.exitResult.Err = err
|
||||
h.procState = drivers.TaskStateUnknown
|
||||
h.completedAt = time.Now()
|
||||
return
|
||||
}
|
||||
h.procState = drivers.TaskStateExited
|
||||
h.exitResult.ExitCode = ps.ExitCode
|
||||
h.exitResult.Signal = ps.Signal
|
||||
h.completedAt = ps.Time
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package skeleton
|
||||
package hello
|
||||
|
||||
import (
|
||||
"sync"
|
|
@ -1,12 +1,10 @@
|
|||
// +build linux
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/nomad-runtime-driver-skeleton/hello"
|
||||
|
||||
"github.com/hashicorp/nomad/plugins"
|
||||
"github.com/hashicorp/nomad-driver-skeleton/pkg/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -16,6 +14,5 @@ func main() {
|
|||
|
||||
// factory returns a new instance of a nomad driver plugin
|
||||
func factory(log log.Logger) interface{} {
|
||||
return skeleton.NewSkeletonDriver(log)
|
||||
return hello.NewPlugin(log)
|
||||
}
|
||||
|
|
@ -1,330 +0,0 @@
|
|||
package skeleton
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/nomad/drivers/shared/eventer"
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
"github.com/hashicorp/nomad/plugins/drivers"
|
||||
"github.com/hashicorp/nomad/plugins/shared/hclspec"
|
||||
structs "github.com/hashicorp/nomad/plugins/shared/structs"
|
||||
)
|
||||
|
||||
const (
|
||||
// pluginName is the name of the plugin
|
||||
pluginName = "test-plugin"
|
||||
|
||||
// fingerprintPeriod is the interval at which the driver will send fingerprint responses
|
||||
fingerprintPeriod = 30 * time.Second
|
||||
|
||||
// taskHandleVersion is the version of task handle which this driver sets
|
||||
// and understands how to decode driver state
|
||||
taskHandleVersion = 1
|
||||
)
|
||||
|
||||
var (
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{"0.1.0"},
|
||||
PluginVersion: "0.0.1",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
configSpec = hclspec.NewObject(map[string]*hclspec.Spec{
|
||||
"enabled": hclspec.NewDefault(
|
||||
hclspec.NewAttr("enabled", "bool", false),
|
||||
hclspec.NewLiteral("true"),
|
||||
),
|
||||
})
|
||||
|
||||
// taskConfigSpec is the hcl specification for the driver config section of
|
||||
// a taskConfig within a job. It is returned in the TaskConfigSchema RPC
|
||||
taskConfigSpec = hclspec.NewObject(map[string]*hclspec.Spec{
|
||||
"strconfig": hclspec.NewAttr("strconfig", "string", true),
|
||||
"boolcfg": hclspec.NewAttr("boolcfg", "bool", false),
|
||||
})
|
||||
|
||||
// capabilities is returned by the Capabilities RPC and indicates what
|
||||
// optional features this driver supports. This should be set according
|
||||
// to the target run time
|
||||
capabilities = &drivers.Capabilities{
|
||||
SendSignals: true,
|
||||
Exec: false,
|
||||
}
|
||||
)
|
||||
|
||||
// Driver is a skeleton driver implementation. The fields in this struct
|
||||
// are to help plugin authors get started writing their runtime plugins.
|
||||
type Driver struct {
|
||||
// eventer is used to handle multiplexing of TaskEvents calls such that an
|
||||
// event can be broadcast to all callers
|
||||
eventer *eventer.Eventer
|
||||
|
||||
// config is the driver configuration set by the SetConfig RPC
|
||||
config *Config
|
||||
|
||||
// nomadConfig is the client config from nomad
|
||||
nomadConfig *base.ClientDriverConfig
|
||||
|
||||
// tasks is the in memory datastore mapping taskIDs to rawExecDriverHandles
|
||||
tasks *taskStore
|
||||
|
||||
// ctx is the context for the driver. It is passed to other subsystems to
|
||||
// coordinate shutdown
|
||||
ctx context.Context
|
||||
|
||||
// signalShutdown is called when the driver is shutting down and cancels the
|
||||
// ctx passed to any subsystems
|
||||
signalShutdown context.CancelFunc
|
||||
|
||||
// logger will log to the Nomad agent
|
||||
logger hclog.Logger
|
||||
}
|
||||
|
||||
// Config is the driver configuration set by the SetConfig RPC call
|
||||
type Config struct {
|
||||
// Enabled is set to true to enable this driver
|
||||
Enabled bool `codec:"enabled"`
|
||||
}
|
||||
|
||||
// TaskConfig is the driver configuration of a task within a job
|
||||
type TaskConfig struct {
|
||||
StrConfig string `codec:"strconfig"`
|
||||
BoolConfig bool `codec:"boolconfig"`
|
||||
}
|
||||
|
||||
// TaskState is the state which is encoded in the handle returned in
|
||||
// StartTask. This information is needed to rebuild the task state and handler
|
||||
// during recovery.
|
||||
type TaskState struct {
|
||||
TaskConfig *drivers.TaskConfig
|
||||
ContainerName string
|
||||
StartedAt time.Time
|
||||
PID int
|
||||
}
|
||||
|
||||
// NewSkeletonDriver returns a new DriverPlugin implementation
|
||||
func NewSkeletonDriver(logger hclog.Logger) drivers.DriverPlugin {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
logger = logger.Named(pluginName)
|
||||
|
||||
return &Driver{
|
||||
eventer: eventer.NewEventer(ctx, logger),
|
||||
config: &Config{},
|
||||
tasks: newTaskStore(),
|
||||
ctx: ctx,
|
||||
signalShutdown: cancel,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) PluginInfo() (*base.PluginInfoResponse, error) {
|
||||
return pluginInfo, nil
|
||||
}
|
||||
|
||||
func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.config = &config
|
||||
if cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Shutdown(ctx context.Context) error {
|
||||
d.signalShutdown()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) TaskConfigSchema() (*hclspec.Spec, error) {
|
||||
return taskConfigSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) Capabilities() (*drivers.Capabilities, error) {
|
||||
return capabilities, nil
|
||||
}
|
||||
|
||||
func (d *Driver) Fingerprint(ctx context.Context) (<-chan *drivers.Fingerprint, error) {
|
||||
ch := make(chan *drivers.Fingerprint)
|
||||
go d.handleFingerprint(ctx, ch)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (d *Driver) handleFingerprint(ctx context.Context, ch chan<- *drivers.Fingerprint) {
|
||||
defer close(ch)
|
||||
ticker := time.NewTimer(0)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-d.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
ticker.Reset(fingerprintPeriod)
|
||||
ch <- d.buildFingerprint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) buildFingerprint() *drivers.Fingerprint {
|
||||
var health drivers.HealthState
|
||||
var desc string
|
||||
attrs := map[string]*structs.Attribute{}
|
||||
|
||||
// Implement finger printing logic here to populate health and driver attributes
|
||||
|
||||
return &drivers.Fingerprint{
|
||||
Attributes: attrs,
|
||||
Health: health,
|
||||
HealthDescription: desc,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) RecoverTask(handle *drivers.TaskHandle) error {
|
||||
if handle == nil {
|
||||
return fmt.Errorf("error: handle cannot be nil")
|
||||
}
|
||||
|
||||
if _, ok := d.tasks.Get(handle.Config.ID); ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var taskState TaskState
|
||||
if err := handle.GetDriverState(&taskState); err != nil {
|
||||
return fmt.Errorf("failed to decode task state from handle: %v", err)
|
||||
}
|
||||
|
||||
var driverConfig TaskConfig
|
||||
if err := taskState.TaskConfig.DecodeDriverConfig(&driverConfig); err != nil {
|
||||
return fmt.Errorf("failed to decode driver config: %v", err)
|
||||
}
|
||||
|
||||
// Implement driver specific way to reattach to a running task or restart
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartTask setup the task exec and calls the container excecutor
|
||||
func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drivers.DriverNetwork, error) {
|
||||
if _, ok := d.tasks.Get(cfg.ID); ok {
|
||||
return nil, nil, fmt.Errorf("task with ID %q already started", cfg.ID)
|
||||
}
|
||||
|
||||
var driverConfig TaskConfig
|
||||
if err := cfg.DecodeDriverConfig(&driverConfig); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to decode driver config: %v", err)
|
||||
}
|
||||
|
||||
handle := drivers.NewTaskHandle(taskHandleVersion)
|
||||
handle.Config = cfg
|
||||
|
||||
// Implement driver specific mechanism to start the task here
|
||||
|
||||
return nil, nil, nil
|
||||
|
||||
}
|
||||
|
||||
func (d *Driver) WaitTask(ctx context.Context, taskID string) (<-chan *drivers.ExitResult, error) {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return nil, drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
ch := make(chan *drivers.ExitResult)
|
||||
go d.handleWait(ctx, handle, ch)
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (d *Driver) handleWait(ctx context.Context, handle *taskHandle, ch chan *drivers.ExitResult) {
|
||||
defer close(ch)
|
||||
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-d.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
s := handle.TaskStatus()
|
||||
if s.State == drivers.TaskStateExited {
|
||||
ch <- handle.exitResult
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) StopTask(taskID string, timeout time.Duration, signal string) error {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
if err := handle.shutdown(timeout); err != nil {
|
||||
return fmt.Errorf("executor Shutdown failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) DestroyTask(taskID string, force bool) error {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
if handle.IsRunning() && !force {
|
||||
return fmt.Errorf("cannot destroy running task")
|
||||
}
|
||||
|
||||
d.tasks.Delete(taskID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) InspectTask(taskID string) (*drivers.TaskStatus, error) {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return nil, drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
return handle.TaskStatus(), nil
|
||||
}
|
||||
|
||||
func (d *Driver) TaskStats(ctx context.Context, taskID string, interval time.Duration) (<-chan *drivers.TaskResourceUsage, error) {
|
||||
handle, ok := d.tasks.Get(taskID)
|
||||
if !ok {
|
||||
return nil, drivers.ErrTaskNotFound
|
||||
}
|
||||
|
||||
return handle.stats(ctx, interval)
|
||||
}
|
||||
|
||||
func (d *Driver) TaskEvents(ctx context.Context) (<-chan *drivers.TaskEvent, error) {
|
||||
return d.eventer.TaskEvents(ctx)
|
||||
}
|
||||
|
||||
func (d *Driver) SignalTask(taskID string, signal string) error {
|
||||
return fmt.Errorf("This driver does not support signals")
|
||||
}
|
||||
|
||||
func (d *Driver) ExecTask(taskID string, cmd []string, timeout time.Duration) (*drivers.ExecTaskResult, error) {
|
||||
return nil, fmt.Errorf("This driver does not support exec") //TODO
|
||||
}
|
Loading…
Reference in a new issue