diff --git a/cmd/rove-server/Dockerfile b/Dockerfile similarity index 57% rename from cmd/rove-server/Dockerfile rename to Dockerfile index 7ca6727..adedc9b 100644 --- a/cmd/rove-server/Dockerfile +++ b/Dockerfile @@ -6,9 +6,11 @@ COPY . . RUN go mod download # For /usr/share/dict/words -RUN apt-get update && apt-get install -y wamerican +RUN apt-get -q update && apt-get -qy install wamerican +# Build both executables RUN go build -o rove-server -ldflags="-X 'github.com/mdiluz/rove/pkg/version.Version=$(git describe --always --long --dirty --tags)'" cmd/rove-server/main.go +RUN go build -o rove-accountant -ldflags="-X 'github.com/mdiluz/rove/pkg/version.Version=$(git describe --always --long --dirty --tags)'" cmd/rove-accountant/main.go CMD [ "./rove-server" ] diff --git a/Makefile b/Makefile index 1a4514c..5c56b8e 100644 --- a/Makefile +++ b/Makefile @@ -12,22 +12,9 @@ gen: protoc --proto_path pkg/accounts --go_out=plugins=grpc:pkg/accounts/ --go_opt=paths=source_relative pkg/accounts/accounts.proto test: - go mod download - go build ./... + docker-compose up --build --exit-code-from=rove-tests --abort-on-container-exit - # Run the server and shut it down again to ensure our docker-compose works - ROVE_ARGS="--quit 1" docker-compose up --build --exit-code-from=rove-server --abort-on-container-exit + # TODO: Collect and convert the coverage data to html + # go tool cover -html=/tmp/c.out -o /tmp/coverage.html - # Run the server and shut it down again to ensure our docker-compose works - docker-compose up -d - - # Run tests with coverage and integration tags - go test -v ./... --tags=integration -cover -coverprofile=/tmp/c.out -count 1 - - # - docker-compose down - - # Convert the coverage data to html - go tool cover -html=/tmp/c.out -o /tmp/coverage.html - -.PHONY: install test \ No newline at end of file +.PHONY: install test diff --git a/cmd/rove-accountant/Dockerfile b/cmd/rove-accountant/Dockerfile deleted file mode 100644 index cb8ca13..0000000 --- a/cmd/rove-accountant/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM golang:latest -LABEL maintainer="Marc Di Luzio " - -WORKDIR /app -COPY . . -RUN go mod download - -RUN go build -o rove-accountant -ldflags="-X 'github.com/mdiluz/rove/pkg/version.Version=$(git describe --always --long --dirty --tags)'" cmd/rove-accountant/main.go - -CMD [ "./rove-accountant" ] - diff --git a/cmd/rove-accountant/main.go b/cmd/rove-accountant/main.go index bf6539b..0d204cd 100644 --- a/cmd/rove-accountant/main.go +++ b/cmd/rove-accountant/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "flag" "fmt" "log" "net" @@ -17,8 +16,8 @@ import ( "google.golang.org/grpc" ) -var address = flag.String("address", "", "port to server the accountant on") -var data = flag.String("data", os.TempDir(), "path to persistent data") +var address = os.Getenv("HOST_ADDRESS") +var data = os.Getenv("DATA_PATH") // accountantServer is the internal object to manage the requests type accountantServer struct { @@ -83,14 +82,12 @@ func (a *accountantServer) GetValue(_ context.Context, in *accounts.DataKey) (*a // main func main() { - flag.Parse() - // Verify the input - if len(*address) == 0 { - log.Fatal("No address set with --address") + if len(address) == 0 { + log.Fatal("No address set with $HOST_ADDRESS") } - persistence.SetPath(*data) + persistence.SetPath(data) // Initialise and load the accountant accountant := &internal.Accountant{} @@ -99,7 +96,7 @@ func main() { } // Set up the RPC server and register - lis, err := net.Listen("tcp", *address) + lis, err := net.Listen("tcp", address) if err != nil { log.Fatalf("failed to listen: %v", err) } @@ -118,7 +115,7 @@ func main() { }() // Serve the RPC server - fmt.Printf("Serving accountant on %s\n", *address) + fmt.Printf("Serving accountant on %s\n", address) if err := grpcServer.Serve(lis); err != nil { log.Fatalf("failed to server gRPC: %s", err) } diff --git a/cmd/rove-server/internal/api_test.go b/cmd/rove-server/internal/api_test.go index 3e6a0c1..8a0c0c7 100644 --- a/cmd/rove-server/internal/api_test.go +++ b/cmd/rove-server/internal/api_test.go @@ -1,7 +1,8 @@ +// +build integration + package internal import ( - "fmt" "os" "testing" @@ -11,30 +12,17 @@ import ( "github.com/stretchr/testify/assert" ) -// To be set by the main function -var serv rove.Server +const ( + defaultAddress = "localhost:80" +) -func TestMain(m *testing.M) { - s := NewServer() - if err := s.Initialise(true); err != nil { - fmt.Println(err) - os.Exit(1) +var serv = func() rove.Server { + var address = os.Getenv("ROVE_SERVER_ADDRESS") + if len(address) == 0 { + address = defaultAddress } - - serv = rove.Server(s.Addr()) - - go s.Run() - - fmt.Printf("Test server hosted on %s", serv) - code := m.Run() - - if err := s.StopAndClose(); err != nil { - fmt.Println(err) - os.Exit(1) - } - - os.Exit(code) -} + return rove.Server(address) +}() func TestServer_Status(t *testing.T) { status, err := serv.Status() diff --git a/cmd/rove-server/internal/routes.go b/cmd/rove-server/internal/routes.go index b56b31c..30e30cb 100644 --- a/cmd/rove-server/internal/routes.go +++ b/cmd/rove-server/internal/routes.go @@ -6,11 +6,13 @@ import ( "fmt" "io" "net/http" + "time" "github.com/google/uuid" "github.com/mdiluz/rove/pkg/accounts" "github.com/mdiluz/rove/pkg/rove" "github.com/mdiluz/rove/pkg/version" + "google.golang.org/grpc" ) // Handler describes a function that handles any incoming request and can respond @@ -87,8 +89,10 @@ func HandleRegister(s *Server, vars map[string]string, b io.ReadCloser, w io.Wri response.Error = "Cannot register empty name" } + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() reg := accounts.RegisterInfo{Name: data.Name} - if acc, err := s.accountant.Register(context.Background(), ®); err != nil { + if acc, err := s.accountant.Register(ctx, ®, grpc.WaitForReady(true)); err != nil { response.Error = err.Error() } else if !acc.Success { @@ -125,11 +129,13 @@ func HandleCommand(s *Server, vars map[string]string, b io.ReadCloser, w io.Writ } + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() key := accounts.DataKey{Account: id, Key: "rover"} if len(id) == 0 { response.Error = "No account ID provided" - } else if resp, err := s.accountant.GetValue(context.Background(), &key); err != nil { + } else if resp, err := s.accountant.GetValue(ctx, &key); err != nil { response.Error = fmt.Sprintf("Provided account has no rover: %s", err) } else if !resp.Success { @@ -155,12 +161,14 @@ func HandleRadar(s *Server, vars map[string]string, b io.ReadCloser, w io.Writer Success: false, } + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() id := vars["account"] key := accounts.DataKey{Account: id, Key: "rover"} if len(id) == 0 { response.Error = "No account ID provided" - } else if resp, err := s.accountant.GetValue(context.Background(), &key); err != nil { + } else if resp, err := s.accountant.GetValue(ctx, &key); err != nil { response.Error = fmt.Sprintf("Provided account has no rover: %s", err) } else if !resp.Success { @@ -191,12 +199,14 @@ func HandleRover(s *Server, vars map[string]string, b io.ReadCloser, w io.Writer Success: false, } + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() id := vars["account"] key := accounts.DataKey{Account: id, Key: "rover"} if len(id) == 0 { response.Error = "No account ID provided" - } else if resp, err := s.accountant.GetValue(context.Background(), &key); err != nil { + } else if resp, err := s.accountant.GetValue(ctx, &key); err != nil { response.Error = fmt.Sprintf("Provided account has no rover: %s", err) } else if !resp.Success { diff --git a/cmd/rove-server/internal/routes_test.go b/cmd/rove-server/internal/routes_test.go index 78fd4bd..dd0f2fe 100644 --- a/cmd/rove-server/internal/routes_test.go +++ b/cmd/rove-server/internal/routes_test.go @@ -1,3 +1,5 @@ +// +build integration + package internal import ( @@ -9,6 +11,7 @@ import ( "path" "testing" + "github.com/google/uuid" "github.com/mdiluz/rove/pkg/accounts" "github.com/mdiluz/rove/pkg/game" "github.com/mdiluz/rove/pkg/rove" @@ -39,7 +42,7 @@ func TestHandleStatus(t *testing.T) { } func TestHandleRegister(t *testing.T) { - data := rove.RegisterData{Name: "one"} + data := rove.RegisterData{Name: uuid.New().String()} b, err := json.Marshal(data) if err != nil { t.Error(err) @@ -57,22 +60,24 @@ func TestHandleRegister(t *testing.T) { json.NewDecoder(response.Body).Decode(&status) if status.Success != true { - t.Errorf("got false for /register") + t.Errorf("got false for /register: %s", status.Error) } } func TestHandleCommand(t *testing.T) { + name := uuid.New().String() s := NewServer() s.Initialise(false) // Leave the world empty with no obstacles - reg := accounts.RegisterInfo{Name: "test"} + reg := accounts.RegisterInfo{Name: name} acc, err := s.accountant.Register(context.Background(), ®) assert.NoError(t, err) - assert.True(t, acc.Success) + assert.NotNil(t, acc) + assert.True(t, acc.Success, acc.Error) assert.NoError(t, err, "Error registering account") // Spawn the rover rover for the account - _, inst, err := s.SpawnRoverForAccount("test") + _, inst, err := s.SpawnRoverForAccount(name) assert.NoError(t, s.world.WarpRover(inst, vector.Vector{})) attribs, err := s.world.RoverAttributes(inst) @@ -91,7 +96,7 @@ func TestHandleCommand(t *testing.T) { b, err := json.Marshal(data) assert.NoError(t, err, "Error marshalling data") - request, _ := http.NewRequest(http.MethodPost, path.Join("/", "test", "/command"), bytes.NewReader(b)) + request, _ := http.NewRequest(http.MethodPost, path.Join("/", name, "/command"), bytes.NewReader(b)) response := httptest.NewRecorder() s.router.ServeHTTP(response, request) @@ -118,16 +123,17 @@ func TestHandleCommand(t *testing.T) { } func TestHandleRadar(t *testing.T) { + name := uuid.New().String() s := NewServer() s.Initialise(false) // Spawn a clean world - reg := accounts.RegisterInfo{Name: "test"} + reg := accounts.RegisterInfo{Name: name} acc, err := s.accountant.Register(context.Background(), ®) assert.NoError(t, err) - assert.True(t, acc.Success) + assert.True(t, acc.Success, acc.Error) assert.NoError(t, err, "Error registering account") // Spawn the rover rover for the account - attrib, id, err := s.SpawnRoverForAccount("test") + attrib, id, err := s.SpawnRoverForAccount(name) assert.NoError(t, err) // Warp this rover to 0,0 @@ -143,7 +149,7 @@ func TestHandleRadar(t *testing.T) { assert.NoError(t, s.world.Atlas.SetTile(rockPos, game.TileRock)) assert.NoError(t, s.world.Atlas.SetTile(emptyPos, game.TileEmpty)) - request, _ := http.NewRequest(http.MethodGet, path.Join("/", "test", "/radar"), nil) + request, _ := http.NewRequest(http.MethodGet, path.Join("/", name, "/radar"), nil) response := httptest.NewRecorder() s.router.ServeHTTP(response, request) @@ -175,18 +181,19 @@ func TestHandleRadar(t *testing.T) { } func TestHandleRover(t *testing.T) { + name := uuid.New().String() s := NewServer() s.Initialise(true) - reg := accounts.RegisterInfo{Name: "test"} + reg := accounts.RegisterInfo{Name: name} acc, err := s.accountant.Register(context.Background(), ®) assert.NoError(t, err) - assert.True(t, acc.Success) + assert.True(t, acc.Success, acc.Error) // Spawn one rover for the account - attribs, _, err := s.SpawnRoverForAccount("test") + attribs, _, err := s.SpawnRoverForAccount(name) assert.NoError(t, err) - request, _ := http.NewRequest(http.MethodGet, path.Join("/", "test", "/rover"), nil) + request, _ := http.NewRequest(http.MethodGet, path.Join("/", name, "/rover"), nil) response := httptest.NewRecorder() s.router.ServeHTTP(response, request) diff --git a/cmd/rove-server/internal/server.go b/cmd/rove-server/internal/server.go index e6f79a7..706a188 100644 --- a/cmd/rove-server/internal/server.go +++ b/cmd/rove-server/internal/server.go @@ -3,11 +3,11 @@ package internal import ( "context" "encoding/json" - "flag" "fmt" "log" "net" "net/http" + "os" "sync" "time" @@ -20,7 +20,7 @@ import ( "google.golang.org/grpc" ) -var accountantAddress = flag.String("accountant", "", "address of the accountant to connect to") +var accountantAddress = os.Getenv("ACCOUNTANT_ADDRESS") const ( // PersistentData will allow the server to load and save it's state @@ -116,12 +116,12 @@ func (s *Server) Initialise(fillWorld bool) (err error) { s.sync.Add(1) // Connect to the accountant - fmt.Printf("Dialing accountant on %s\n", *accountantAddress) - clientConn, err := grpc.Dial(*accountantAddress, grpc.WithInsecure()) + fmt.Printf("Dialing accountant on %s\n", accountantAddress) + s.clientConn, err = grpc.Dial(accountantAddress, grpc.WithInsecure()) if err != nil { return err } - s.accountant = accounts.NewAccountantClient(clientConn) + s.accountant = accounts.NewAccountantClient(s.clientConn) // Spawn a border on the default world if err := s.world.SpawnWorld(fillWorld); err != nil { @@ -139,6 +139,7 @@ func (s *Server) Initialise(fillWorld bool) (err error) { } // Start the listen + fmt.Printf("Listening on %s\n", s.server.Addr) if s.listener, err = net.Listen("tcp", s.server.Addr); err != nil { return err } diff --git a/cmd/rove-server/main.go b/cmd/rove-server/main.go index 49ac614..c98ec9b 100644 --- a/cmd/rove-server/main.go +++ b/cmd/rove-server/main.go @@ -3,8 +3,10 @@ package main import ( "flag" "fmt" + "log" "os" "os/signal" + "strconv" "syscall" "time" @@ -15,9 +17,15 @@ import ( var ver = flag.Bool("version", false, "Display version number") var quit = flag.Int("quit", 0, "Quit after n seconds, useful for testing") -var address = flag.String("address", "", "The address to host on, automatically selected if empty") -var data = flag.String("data", "", "Directory to store persistant data, no storage if empty") -var tick = flag.Int("tick", 5, "Number of minutes per server tick (0 for no tick)") + +// Address to host the server on, automatically selected if empty +var address = os.Getenv("HOST_ADDRESS") + +// Path for persistent storage +var data = os.Getenv("DATA_PATH") + +// The tick rate of the server in seconds +var tick = os.Getenv("TICK_RATE") func InnerMain() { flag.Parse() @@ -31,13 +39,23 @@ func InnerMain() { fmt.Printf("Initialising version %s...\n", version.Version) // Set the persistence path - persistence.SetPath(*data) + persistence.SetPath(data) + + // Convert the tick rate + tickRate := 5 + if len(tick) > 0 { + var err error + tickRate, err = strconv.Atoi(tick) + if err != nil { + log.Fatalf("TICK_RATE not set to valid int: %s", err) + } + } // Create the server data s := internal.NewServer( - internal.OptionAddress(*address), + internal.OptionAddress(address), internal.OptionPersistentData(), - internal.OptionTick(*tick)) + internal.OptionTick(tickRate)) // Initialise the server if err := s.Initialise(true); err != nil { @@ -74,6 +92,5 @@ func InnerMain() { } func main() { - flag.Parse() InnerMain() } diff --git a/cmd/rove/main_test.go b/cmd/rove/main_test.go index 2fd0a65..48d32be 100644 --- a/cmd/rove/main_test.go +++ b/cmd/rove/main_test.go @@ -12,9 +12,17 @@ import ( "github.com/stretchr/testify/assert" ) -var address = "localhost:80" +const ( + defaultAddress = "localhost:80" +) func Test_InnerMain(t *testing.T) { + + var address = os.Getenv("ROVE_SERVER_ADDRESS") + if len(address) == 0 { + address = defaultAddress + } + // Set up the flags to act locally and use a temporary file flag.Set("data", path.Join(os.TempDir(), uuid.New().String())) diff --git a/docker-compose.yml b/docker-compose.yml index f76a0a2..f99139a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,24 +4,45 @@ volumes: persistent-data: services: - rove-server: - build: - context: . - dockerfile: cmd/rove-server/Dockerfile - image: rove-server:latest - ports: - - "80:80" - command: ./rove-server --address ":80" --data=/mnt/rove-server ${ROVE_ARGS} --accountant "rove-accountant:8081" - volumes: - - persistent-data:/mnt/rove-server:rw - rove-accountant: build: context: . - dockerfile: cmd/rove-accountant/Dockerfile - image: rove-accountant:latest + dockerfile: Dockerfile + image: rove:latest ports: - "8081:8081" - command: ./rove-accountant --address ":8081" --data=/mnt/rove-server + environment: + - HOST_ADDRESS=:8081 + - DATA_PATH=/mnt/rove-server volumes: - persistent-data:/mnt/rove-server:rw + command: [ ./rove-accountant ] + + rove-server: + depends_on: [ rove-accountant ] + build: + context: . + dockerfile: Dockerfile + image: rove:latest + ports: + - "80:80" + environment: + - HOST_ADDRESS=:80 + - DATA_PATH=/mnt/rove-server + - ACCOUNTANT_ADDRESS=rove-accountant:8081 + volumes: + - persistent-data:/mnt/rove-server:rw + + rove-tests: + depends_on: [ rove-server ] + build: + context: . + dockerfile: Dockerfile + image: rove:latest + environment: + - ACCOUNTANT_ADDRESS=rove-accountant:8081 + - ROVE_SERVER_ADDRESS=rove-server:80 + command: [ "go", "test", "-v", "./...", "--tags=integration", "-cover", "-coverprofile=/tmp/c.out", "-count", "1" ] + + + diff --git a/go.mod b/go.mod index e77c0d4..973e0a5 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/golang/protobuf v1.4.2 github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.4 + github.com/onsi/ginkgo v1.12.3 // indirect github.com/robfig/cron v1.2.0 github.com/stretchr/testify v1.6.0 github.com/tjarratt/babble v0.0.0-20191209142150-eecdf8c2339d diff --git a/go.sum b/go.sum index ecf232d..499b4f0 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -23,11 +26,22 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.12.3 h1:+RYp9QczoWz9zfUyLP/5SLXQVhfr6gZOoKGfQqHuLZQ= +github.com/onsi/ginkgo v1.12.3/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -45,22 +59,37 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/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.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +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-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -79,7 +108,14 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=