diff --git a/.circleci/config.yml b/.circleci/config.yml index 55a7dcd6e2..7ab18ff408 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,9 +11,9 @@ jobs: # Needed to install go OS: linux ARCH: amd64 - GOVERSION: 1.10.3 + GOVERSION: 1.12 # Needed to install protoc - PROTOC: https://github.com/google/protobuf/releases/download/v3.5.0/protoc-3.5.0-linux-x86_64.zip + PROTOC_VERSION: 3.6.1 # Note(cyli): We create a tmpfs mount to be used for temporary files created by tests # to mitigate the excessive I/O latencies that sometimes cause the tests to fail. @@ -61,12 +61,11 @@ jobs: - run: name: Install protoc command: | - curl -fsSL -o "$HOME/$(basename $PROTOC)" "$PROTOC" - unzip -o "$HOME/$(basename $PROTOC)" -d "$HOME" - sudo cp -R "$HOME/include/google" /usr/local/include - sudo chmod 777 -R /usr/local/include/google - sudo cp -R "$HOME/bin/protoc" /usr/local/bin - sudo chmod 777 /usr/local/bin/protoc + curl --silent --show-error --location --output protoc.zip \ + https://github.com/google/protobuf/releases/download/v$PROTOC_VERSION/protoc-$PROTOC_VERSION-linux-x86_64.zip \ + && sudo unzip -d /usr/local protoc.zip include/\* bin\/* \ + && sudo chmod -R a+r /usr/local/include/google/protobuf/ + rm -f protoc.zip - run: name: Install test/lint dependencies diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000000..694ae5c372 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,14 @@ +run: + tests: false +linters: + disable-all: true + enable: + - misspell + - gofmt + - goimports + - golint + - ineffassign + - deadcode + - unconvert + - govet + diff --git a/Dockerfile b/Dockerfile index 4a951ecc69..6d795a468b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,15 @@ # NOTE(dperny): for some reason, alpine was giving me trouble -FROM golang:1.10.3-stretch +FROM golang:1.12.9-stretch RUN apt-get update && apt-get install -y make git unzip -# should stay consistent with the version we use in Circle builds -ARG PROTOC_VERSION=3.5.0 -# make a directory to do these operations in -RUN export PROTOC_TMP_DIR=protoc && mkdir -p $PROTOC_TMP_DIR && cd $PROTOC_TMP_DIR \ - # download the pre-built protoc binary - && curl --silent --show-error --location --output protoc.zip \ - https://github.com/google/protobuf/releases/download/v$PROTOC_VERSION/protoc-$PROTOC_VERSION-linux-x86_64.zip \ - # move the binary to /bin. move the well-known types ot /usr/local/include - && unzip protoc.zip && mv bin/protoc /bin/protoc && mv include/* /usr/local/include \ - # remove all of the installation files - && cd .. && rm -rf $PROTOC_TMP_DIR +# should stay consistent with the version in .circleci/config.yml +ARG PROTOC_VERSION=3.6.1 +# download and install protoc binary and .proto files +RUN curl --silent --show-error --location --output protoc.zip \ + https://github.com/google/protobuf/releases/download/v$PROTOC_VERSION/protoc-$PROTOC_VERSION-linux-x86_64.zip \ + && unzip -d /usr/local protoc.zip include/\* bin/\* \ + && rm -f protoc.zip WORKDIR /go/src/github.com/docker/swarmkit/ diff --git a/agent/agent.go b/agent/agent.go index 4d8f99cfcd..58ebff5934 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -2,6 +2,7 @@ package agent import ( "bytes" + "context" "math/rand" "reflect" "sync" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "github.com/pkg/errors" - "golang.org/x/net/context" ) const ( @@ -575,7 +575,7 @@ func (a *Agent) nodeDescriptionWithHostname(ctx context.Context, tlsInfo *api.No // Override hostname and TLS info if desc != nil { - if a.config.Hostname != "" && desc != nil { + if a.config.Hostname != "" { desc.Hostname = a.config.Hostname } desc.TLSInfo = tlsInfo diff --git a/agent/agent_test.go b/agent/agent_test.go index 8b84e957b2..0522b5bb88 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -1,6 +1,7 @@ package agent import ( + "context" "crypto/tls" "errors" "fmt" @@ -25,7 +26,6 @@ import ( "github.com/docker/swarmkit/xnet" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) var localDispatcher = false @@ -90,7 +90,8 @@ func TestAgentStartStop(t *testing.T) { require.NoError(t, err) assert.NotNil(t, agent) - ctx, _ := context.WithTimeout(tc.Context, 5000*time.Millisecond) + ctx, cancel := context.WithTimeout(tc.Context, 5000*time.Millisecond) + defer cancel() assert.Equal(t, errAgentNotStarted, agent.Stop(ctx)) assert.NoError(t, agent.Start(ctx)) @@ -354,7 +355,7 @@ func TestSessionReconnectsIfDispatcherErrors(t *testing.T) { return fmt.Errorf("expecting 2 closed sessions, got %d", len(closedSessions)) } return nil - }, 5*time.Second)) + }, 10*time.Second)) } type testSessionTracker struct { diff --git a/agent/errors.go b/agent/errors.go index 29f8ff1c9f..f5514d8311 100644 --- a/agent/errors.go +++ b/agent/errors.go @@ -13,10 +13,5 @@ var ( errAgentStarted = errors.New("agent: already started") errAgentNotStarted = errors.New("agent: not started") - errTaskNoController = errors.New("agent: no task controller") - errTaskNotAssigned = errors.New("agent: task not assigned") - errTaskStatusUpdateNoChange = errors.New("agent: no change in task status") - errTaskUnknown = errors.New("agent: task unknown") - - errTaskInvalid = errors.New("task: invalid") + errTaskUnknown = errors.New("agent: task unknown") ) diff --git a/agent/exec/controller.go b/agent/exec/controller.go index c9e9343fd7..b617d37ca3 100644 --- a/agent/exec/controller.go +++ b/agent/exec/controller.go @@ -1,6 +1,7 @@ package exec import ( + "context" "fmt" "time" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/protobuf/ptypes" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" ) // Controller controls execution of a task. diff --git a/agent/exec/controller_stub.go b/agent/exec/controller_stub.go index 076955ff80..dd16ce457d 100644 --- a/agent/exec/controller_stub.go +++ b/agent/exec/controller_stub.go @@ -1,10 +1,11 @@ package exec import ( - "github.com/docker/swarmkit/api" - "golang.org/x/net/context" + "context" "runtime" "strings" + + "github.com/docker/swarmkit/api" ) // StubController implements the Controller interface, diff --git a/agent/exec/controller_test.go b/agent/exec/controller_test.go index 2de4f436f3..76634056a2 100644 --- a/agent/exec/controller_test.go +++ b/agent/exec/controller_test.go @@ -1,6 +1,7 @@ package exec import ( + "context" "errors" "fmt" "runtime" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/log" gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) func TestResolve(t *testing.T) { diff --git a/agent/exec/dockerapi/adapter.go b/agent/exec/dockerapi/adapter.go index 45943dd9ea..fd3cab4b31 100644 --- a/agent/exec/dockerapi/adapter.go +++ b/agent/exec/dockerapi/adapter.go @@ -1,6 +1,7 @@ package dockerapi import ( + "context" "encoding/json" "fmt" "io" @@ -16,7 +17,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "golang.org/x/time/rate" ) @@ -144,15 +144,13 @@ func (c *containerAdapter) removeNetworks(ctx context.Context) error { } func (c *containerAdapter) create(ctx context.Context) error { - if _, err := c.client.ContainerCreate(ctx, + _, err := c.client.ContainerCreate(ctx, c.container.config(), c.container.hostConfig(), c.container.networkingConfig(), - c.container.name()); err != nil { - return err - } + c.container.name()) - return nil + return err } func (c *containerAdapter) start(ctx context.Context) error { diff --git a/agent/exec/dockerapi/controller.go b/agent/exec/dockerapi/controller.go index 12bac6ec63..abb2e15e90 100644 --- a/agent/exec/dockerapi/controller.go +++ b/agent/exec/dockerapi/controller.go @@ -3,6 +3,7 @@ package dockerapi import ( "bufio" "bytes" + "context" "encoding/binary" "fmt" "io" @@ -19,7 +20,6 @@ import ( "github.com/docker/swarmkit/log" gogotypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" - "golang.org/x/net/context" "golang.org/x/time/rate" ) @@ -654,7 +654,7 @@ func parsePortMap(portMap nat.PortMap) ([]*api.PortConfig, error) { return nil, err } - protocol := api.ProtocolTCP + var protocol api.PortConfig_Protocol switch strings.ToLower(parts[1]) { case "tcp": protocol = api.ProtocolTCP diff --git a/agent/exec/dockerapi/controller_integration_test.go b/agent/exec/dockerapi/controller_integration_test.go index 3c4d6866d5..7e766e051a 100644 --- a/agent/exec/dockerapi/controller_integration_test.go +++ b/agent/exec/dockerapi/controller_integration_test.go @@ -1,6 +1,7 @@ package dockerapi import ( + "context" "flag" "testing" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api/genericresource" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) var ( diff --git a/agent/exec/dockerapi/controller_test.go b/agent/exec/dockerapi/controller_test.go index 7c95fabbe4..2ec2e8af52 100644 --- a/agent/exec/dockerapi/controller_test.go +++ b/agent/exec/dockerapi/controller_test.go @@ -2,6 +2,7 @@ package dockerapi import ( "bytes" + "context" "fmt" "io" "io/ioutil" @@ -20,7 +21,6 @@ import ( "github.com/docker/swarmkit/log" gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) var tenSecond = 10 * time.Second diff --git a/agent/exec/dockerapi/docker_client_stub.go b/agent/exec/dockerapi/docker_client_stub.go index 653f3df1a8..41ee3ee89c 100644 --- a/agent/exec/dockerapi/docker_client_stub.go +++ b/agent/exec/dockerapi/docker_client_stub.go @@ -1,16 +1,17 @@ package dockerapi import ( + "context" + "io" + "runtime" + "strings" + "time" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" - "golang.org/x/net/context" - "io" - "runtime" - "strings" - "time" ) // StubAPIClient implements the client.APIClient interface, but allows diff --git a/agent/exec/dockerapi/executor.go b/agent/exec/dockerapi/executor.go index 6601ce224b..011164596c 100644 --- a/agent/exec/dockerapi/executor.go +++ b/agent/exec/dockerapi/executor.go @@ -1,8 +1,10 @@ package dockerapi import ( + "context" "sort" "strings" + "sync" "github.com/docker/docker/api/types/filters" engineapi "github.com/docker/docker/client" @@ -10,8 +12,6 @@ import ( "github.com/docker/swarmkit/agent/secrets" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" - "golang.org/x/net/context" - "sync" ) type executor struct { diff --git a/agent/exec/executor.go b/agent/exec/executor.go index 8c3fd03506..26c1bfcba7 100644 --- a/agent/exec/executor.go +++ b/agent/exec/executor.go @@ -1,8 +1,9 @@ package exec import ( + "context" + "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) // Executor provides controllers for tasks. diff --git a/agent/helpers.go b/agent/helpers.go index 5fdf166059..5e95d93297 100644 --- a/agent/helpers.go +++ b/agent/helpers.go @@ -1,6 +1,6 @@ package agent -import "golang.org/x/net/context" +import "context" // runctx blocks until the function exits, closed is closed, or the context is // cancelled. Call as part of go statement. diff --git a/agent/reporter.go b/agent/reporter.go index 73e6ab3fd9..2afb75795f 100644 --- a/agent/reporter.go +++ b/agent/reporter.go @@ -1,12 +1,12 @@ package agent import ( + "context" "reflect" "sync" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" - "golang.org/x/net/context" ) // StatusReporter receives updates to task status. Method may be called diff --git a/agent/reporter_test.go b/agent/reporter_test.go index d0b5dc6d8e..fcafec5a8c 100644 --- a/agent/reporter_test.go +++ b/agent/reporter_test.go @@ -1,6 +1,7 @@ package agent import ( + "context" "errors" "fmt" "math/rand" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) type uniqueStatus struct { diff --git a/agent/resource.go b/agent/resource.go index 8e88d2cd65..32be069c11 100644 --- a/agent/resource.go +++ b/agent/resource.go @@ -1,8 +1,9 @@ package agent import ( + "context" + "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) type resourceAllocator struct { diff --git a/agent/session.go b/agent/session.go index 8c01d08fdd..2e7f1b6a37 100644 --- a/agent/session.go +++ b/agent/session.go @@ -1,7 +1,9 @@ package agent import ( + "context" "errors" + "math" "sync" "time" @@ -9,7 +11,6 @@ import ( "github.com/docker/swarmkit/connectionbroker" "github.com/docker/swarmkit/log" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -17,7 +18,6 @@ import ( var ( dispatcherRPCTimeout = 5 * time.Second - errSessionDisconnect = errors.New("agent: session disconnect") // instructed to disconnect errSessionClosed = errors.New("agent: session closed") ) @@ -65,6 +65,7 @@ func newSession(ctx context.Context, agent *Agent, delay time.Duration, sessionI cc, err := agent.config.ConnBroker.Select( grpc.WithTransportCredentials(agent.config.Credentials), grpc.WithTimeout(dispatcherRPCTimeout), + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)), ) if err != nil { @@ -137,7 +138,7 @@ func (s *session) start(ctx context.Context, description *api.NodeDescription) e // `ctx` is done and hence fail to propagate the timeout error to the agent. // If the error is not propogated to the agent, the agent will not close // the session or rebuild a new session. - sessionCtx, cancelSession := context.WithCancel(ctx) + sessionCtx, cancelSession := context.WithCancel(ctx) //nolint:govet // Need to run Session in a goroutine since there's no way to set a // timeout for an individual Recv call in a stream. @@ -160,7 +161,7 @@ func (s *session) start(ctx context.Context, description *api.NodeDescription) e select { case err := <-errChan: if err != nil { - return err + return err //nolint:govet } case <-time.After(dispatcherRPCTimeout): cancelSession() diff --git a/agent/task.go b/agent/task.go index 95fe93179b..17c713c092 100644 --- a/agent/task.go +++ b/agent/task.go @@ -1,6 +1,7 @@ package agent import ( + "context" "sync" "time" @@ -8,7 +9,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api/equality" "github.com/docker/swarmkit/log" - "golang.org/x/net/context" ) // taskManager manages all aspects of task execution and reporting for an agent diff --git a/agent/task_test.go b/agent/task_test.go index 3a6afce51b..85b83ddba2 100644 --- a/agent/task_test.go +++ b/agent/task_test.go @@ -1,6 +1,7 @@ package agent import ( + "context" "testing" "time" @@ -8,7 +9,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) func init() { diff --git a/agent/testutils/fakes.go b/agent/testutils/fakes.go index b2e5c81150..150d06935f 100644 --- a/agent/testutils/fakes.go +++ b/agent/testutils/fakes.go @@ -1,6 +1,7 @@ package testutils import ( + "context" "io/ioutil" "net" "os" @@ -17,7 +18,6 @@ import ( "github.com/docker/swarmkit/identity" "github.com/docker/swarmkit/log" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) // TestExecutor is executor for integration tests @@ -140,17 +140,13 @@ func (m *MockDispatcher) UpdateTaskStatus(context.Context, *api.UpdateTaskStatus // Tasks keeps an open stream until canceled func (m *MockDispatcher) Tasks(_ *api.TasksRequest, stream api.Dispatcher_TasksServer) error { - select { - case <-stream.Context().Done(): - } + <-stream.Context().Done() return nil } // Assignments keeps an open stream until canceled func (m *MockDispatcher) Assignments(_ *api.AssignmentsRequest, stream api.Dispatcher_AssignmentsServer) error { - select { - case <-stream.Context().Done(): - } + <-stream.Context().Done() return nil } diff --git a/agent/worker.go b/agent/worker.go index 8125145d21..212aa1e12f 100644 --- a/agent/worker.go +++ b/agent/worker.go @@ -1,6 +1,7 @@ package agent import ( + "context" "sync" "github.com/docker/swarmkit/agent/exec" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/watch" "github.com/sirupsen/logrus" bolt "go.etcd.io/bbolt" - "golang.org/x/net/context" ) // Worker implements the core task management logic and persistence. It @@ -257,13 +257,11 @@ func reconcileTaskState(ctx context.Context, w *worker, assignments []*api.Assig } closeManager := func(tm *taskManager) { - go func(tm *taskManager) { - defer w.closers.Done() - // when a task is no longer assigned, we shutdown the task manager - if err := tm.Close(); err != nil { - log.G(ctx).WithError(err).Error("error closing task manager") - } - }(tm) + defer w.closers.Done() + // when a task is no longer assigned, we shutdown the task manager + if err := tm.Close(); err != nil { + log.G(ctx).WithError(err).Error("error closing task manager") + } // make an attempt at removing. this is best effort. any errors will be // retried by the reaper later. diff --git a/agent/worker_test.go b/agent/worker_test.go index f75335f8bf..b5af5cc6e2 100644 --- a/agent/worker_test.go +++ b/agent/worker_test.go @@ -1,6 +1,7 @@ package agent import ( + "context" "testing" "github.com/docker/swarmkit/agent/exec" @@ -9,7 +10,6 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" bolt "go.etcd.io/bbolt" - "golang.org/x/net/context" ) type testPublisherProvider struct { diff --git a/api/api.pb.txt b/api/api.pb.txt index 27aa683b42..7c94371b8b 100755 --- a/api/api.pb.txt +++ b/api/api.pb.txt @@ -2491,8 +2491,8 @@ file { label: LABEL_OPTIONAL type: TYPE_UINT32 options { - 65003: "os.FileMode" 65001: 0 + 65003: "os.FileMode" } json_name: "mode" } @@ -2646,8 +2646,8 @@ file { type: TYPE_MESSAGE type_name: ".google.protobuf.Duration" options { - 65011: 1 65001: 0 + 65011: 1 } json_name: "delay" } @@ -3090,8 +3090,8 @@ file { } } options { - 62023: "PublishMode" 62001: 0 + 62023: "PublishMode" } } } @@ -3790,8 +3790,8 @@ file { label: LABEL_OPTIONAL type: TYPE_UINT32 options { - 65003: "os.FileMode" 65001: 0 + 65003: "os.FileMode" } json_name: "mode" } @@ -4207,8 +4207,8 @@ file { } } options { - 62023: "NodeRole" 62001: 0 + 62023: "NodeRole" } } syntax: "proto3" @@ -8058,8 +8058,8 @@ file { type: TYPE_MESSAGE type_name: ".google.protobuf.Duration" options { - 65011: 1 65001: 0 + 65011: 1 } json_name: "period" } @@ -9106,11 +9106,11 @@ file { } } options { - 63017: 1 - 63020: 1 - 63018: 1 63001: 0 63002: 0 + 63017: 1 + 63018: 1 + 63020: 1 } } file { diff --git a/api/dispatcher.pb.go b/api/dispatcher.pb.go index cc443848de..f72d3d9995 100644 --- a/api/dispatcher.pb.go +++ b/api/dispatcher.pb.go @@ -1664,7 +1664,7 @@ func (p *raftProxyDispatcherServer) Session(r *SessionRequest, stream Dispatcher } streamWrapper := Dispatcher_SessionServerWrapper{ Dispatcher_SessionServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.Session(r, streamWrapper) } @@ -1785,7 +1785,7 @@ func (p *raftProxyDispatcherServer) Tasks(r *TasksRequest, stream Dispatcher_Tas } streamWrapper := Dispatcher_TasksServerWrapper{ Dispatcher_TasksServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.Tasks(r, streamWrapper) } @@ -1836,7 +1836,7 @@ func (p *raftProxyDispatcherServer) Assignments(r *AssignmentsRequest, stream Di } streamWrapper := Dispatcher_AssignmentsServerWrapper{ Dispatcher_AssignmentsServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.Assignments(r, streamWrapper) } diff --git a/api/genericresource/resource_management.go b/api/genericresource/resource_management.go index a89a118d62..506257ab97 100644 --- a/api/genericresource/resource_management.go +++ b/api/genericresource/resource_management.go @@ -2,6 +2,7 @@ package genericresource import ( "fmt" + "github.com/docker/swarmkit/api" ) diff --git a/api/genericresource/validate.go b/api/genericresource/validate.go index eee3706c74..0ad49ff75f 100644 --- a/api/genericresource/validate.go +++ b/api/genericresource/validate.go @@ -2,6 +2,7 @@ package genericresource import ( "fmt" + "github.com/docker/swarmkit/api" ) diff --git a/api/logbroker.pb.go b/api/logbroker.pb.go index b6231e941c..5456c85816 100644 --- a/api/logbroker.pb.go +++ b/api/logbroker.pb.go @@ -1335,7 +1335,7 @@ func (p *raftProxyLogsServer) SubscribeLogs(r *SubscribeLogsRequest, stream Logs } streamWrapper := Logs_SubscribeLogsServerWrapper{ Logs_SubscribeLogsServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.SubscribeLogs(r, streamWrapper) } @@ -1458,7 +1458,7 @@ func (p *raftProxyLogBrokerServer) ListenSubscriptions(r *ListenSubscriptionsReq } streamWrapper := LogBroker_ListenSubscriptionsServerWrapper{ LogBroker_ListenSubscriptionsServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.ListenSubscriptions(r, streamWrapper) } @@ -1509,7 +1509,7 @@ func (p *raftProxyLogBrokerServer) PublishLogs(stream LogBroker_PublishLogsServe } streamWrapper := LogBroker_PublishLogsServerWrapper{ LogBroker_PublishLogsServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.PublishLogs(streamWrapper) } diff --git a/api/raft.pb.go b/api/raft.pb.go index 058b29450c..a32a6001b9 100644 --- a/api/raft.pb.go +++ b/api/raft.pb.go @@ -1746,7 +1746,7 @@ func (p *raftProxyRaftServer) StreamRaftMessage(stream Raft_StreamRaftMessageSer } streamWrapper := Raft_StreamRaftMessageServerWrapper{ Raft_StreamRaftMessageServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.StreamRaftMessage(streamWrapper) } diff --git a/api/types.pb.go b/api/types.pb.go index f41d5e2033..f5843467cb 100644 --- a/api/types.pb.go +++ b/api/types.pb.go @@ -594,7 +594,7 @@ var MaybeEncryptedRecord_Algorithm_name = map[int32]string{ 2: "FERNET_AES_128_CBC", } var MaybeEncryptedRecord_Algorithm_value = map[string]int32{ - "NONE": 0, + "NONE": 0, "SECRETBOX_SALSA20_POLY1305": 1, "FERNET_AES_128_CBC": 2, } diff --git a/ca/auth.go b/ca/auth.go index df4547fb13..e0ff898c19 100644 --- a/ca/auth.go +++ b/ca/auth.go @@ -1,6 +1,7 @@ package ca import ( + "context" "crypto/tls" "crypto/x509/pkix" "strings" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" diff --git a/ca/certificates.go b/ca/certificates.go index ad2be2c571..dd0297ab4f 100644 --- a/ca/certificates.go +++ b/ca/certificates.go @@ -2,6 +2,7 @@ package ca import ( "bytes" + "context" "crypto" "crypto/ecdsa" "crypto/elliptic" @@ -31,7 +32,6 @@ import ( "github.com/docker/swarmkit/ioutils" "github.com/opencontainers/go-digest" "github.com/pkg/errors" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" diff --git a/ca/certificates_test.go b/ca/certificates_test.go index 55435889cd..9feb479bff 100644 --- a/ca/certificates_test.go +++ b/ca/certificates_test.go @@ -1,6 +1,7 @@ package ca_test import ( + "context" "crypto/ecdsa" "crypto/elliptic" cryptorand "crypto/rand" @@ -38,7 +39,6 @@ import ( "github.com/phayes/permbits" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "google.golang.org/grpc/status" ) @@ -706,12 +706,10 @@ func TestGetRemoteSignedCertificateWithPending(t *testing.T) { var node *api.Node // wait for a new node to show up for node == nil { - select { - case event := <-updates: // we want to skip the first node, which is the test CA - n := event.(api.EventCreateNode).Node.Copy() - if n.Certificate.Status.State == api.IssuanceStatePending { - node = n - } + event := <-updates // we want to skip the first node, which is the test CA + n := event.(api.EventCreateNode).Node.Copy() + if n.Certificate.Status.State == api.IssuanceStatePending { + node = n } } @@ -748,7 +746,8 @@ func TestGetRemoteSignedCertificateWithPending(t *testing.T) { // make sure if we time out the GetRemoteSignedCertificate call, it cancels immediately and doesn't keep // polling the status go func() { - ctx, _ := context.WithTimeout(tc.Context, 1*time.Second) + ctx, cancel := context.WithTimeout(tc.Context, 1*time.Second) + defer cancel() _, err := ca.GetRemoteSignedCertificate(ctx, csr, tc.RootCA.Pool, ca.CertificateRequestConfig{ Token: tc.WorkerToken, diff --git a/ca/config.go b/ca/config.go index 4a7230ac2f..4befee5bcc 100644 --- a/ca/config.go +++ b/ca/config.go @@ -1,6 +1,7 @@ package ca import ( + "context" cryptorand "crypto/rand" "crypto/tls" "crypto/x509" @@ -23,8 +24,6 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "google.golang.org/grpc/credentials" - - "golang.org/x/net/context" ) const ( @@ -32,7 +31,6 @@ const ( rootCAKeyFilename = "swarm-root-ca.key" nodeTLSCertFilename = "swarm-node.crt" nodeTLSKeyFilename = "swarm-node.key" - nodeCSRFilename = "swarm-node.csr" // DefaultRootCN represents the root CN that we should create roots CAs with by default DefaultRootCN = "swarm-ca" @@ -626,10 +624,10 @@ func calculateRandomExpiry(validFrom, validUntil time.Time) time.Duration { if maxValidity-minValidity < 1 { randomExpiry = minValidity } else { - randomExpiry = rand.Intn(maxValidity-minValidity) + int(minValidity) + randomExpiry = rand.Intn(maxValidity-minValidity) + minValidity } - expiry := validFrom.Add(time.Duration(randomExpiry) * time.Minute).Sub(time.Now()) + expiry := time.Until(validFrom.Add(time.Duration(randomExpiry) * time.Minute)) if expiry < 0 { return 0 } diff --git a/ca/config_test.go b/ca/config_test.go index 98f6755a45..804b96dbb3 100644 --- a/ca/config_test.go +++ b/ca/config_test.go @@ -2,6 +2,7 @@ package ca_test import ( "bytes" + "context" "crypto/tls" "crypto/x509" "fmt" @@ -16,8 +17,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" - "golang.org/x/net/context" - cfconfig "github.com/cloudflare/cfssl/config" "github.com/cloudflare/cfssl/helpers" "github.com/docker/swarmkit/api" @@ -788,24 +787,22 @@ func TestRenewTLSConfigUpdatesRootNonUnknownAuthError(t *testing.T) { go func() { updates, cancel := state.Watch(tc.MemoryStore.WatchQueue(), api.EventCreateNode{}) defer cancel() - select { - case event := <-updates: // we want to skip the first node, which is the test CA - n := event.(api.EventCreateNode).Node - if n.Certificate.Status.State == api.IssuanceStatePending { - signErr <- tc.MemoryStore.Update(func(tx store.Tx) error { - node := store.GetNode(tx, n.ID) - certChain, err := rootCA.ParseValidateAndSignCSR(node.Certificate.CSR, node.Certificate.CN, ca.WorkerRole, tc.Organization) - if err != nil { - return err - } - node.Certificate.Certificate = cautils.ReDateCert(t, certChain, cert, key, time.Now().Add(-5*time.Hour), time.Now().Add(-4*time.Hour)) - node.Certificate.Status = api.IssuanceStatus{ - State: api.IssuanceStateIssued, - } - return store.UpdateNode(tx, node) - }) - return - } + event := <-updates // we want to skip the first node, which is the test CA + n := event.(api.EventCreateNode).Node + if n.Certificate.Status.State == api.IssuanceStatePending { + signErr <- tc.MemoryStore.Update(func(tx store.Tx) error { + node := store.GetNode(tx, n.ID) + certChain, err := rootCA.ParseValidateAndSignCSR(node.Certificate.CSR, node.Certificate.CN, ca.WorkerRole, tc.Organization) + if err != nil { + return err + } + node.Certificate.Certificate = cautils.ReDateCert(t, certChain, cert, key, time.Now().Add(-5*time.Hour), time.Now().Add(-4*time.Hour)) + node.Certificate.Status = api.IssuanceStatus{ + State: api.IssuanceStateIssued, + } + return store.UpdateNode(tx, node) + }) + return } }() diff --git a/ca/external.go b/ca/external.go index 789361eb61..6b81204595 100644 --- a/ca/external.go +++ b/ca/external.go @@ -2,6 +2,7 @@ package ca import ( "bytes" + "context" cryptorand "crypto/rand" "crypto/tls" "crypto/x509" @@ -21,7 +22,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "golang.org/x/net/context/ctxhttp" ) diff --git a/ca/external_test.go b/ca/external_test.go index 7018ba1f95..17272dfbd5 100644 --- a/ca/external_test.go +++ b/ca/external_test.go @@ -113,9 +113,7 @@ func TestExternalCASignRequestTimesOut(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("/", func(http.ResponseWriter, *http.Request) { // hang forever - select { - case <-allDone: - } + <-allDone }) server := httptest.NewServer(mux) diff --git a/ca/forward.go b/ca/forward.go index a05cf53aaf..7ad7c7dd0b 100644 --- a/ca/forward.go +++ b/ca/forward.go @@ -1,7 +1,8 @@ package ca import ( - "golang.org/x/net/context" + "context" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" ) diff --git a/ca/renewer.go b/ca/renewer.go index 2a2fae7808..e5d165f6a8 100644 --- a/ca/renewer.go +++ b/ca/renewer.go @@ -1,6 +1,7 @@ package ca import ( + "context" "sync" "time" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" ) // RenewTLSExponentialBackoff sets the exponential backoff when trying to renew TLS certificates that have expired diff --git a/ca/renewer_test.go b/ca/renewer_test.go index b8ce3f81be..a0f3cd3258 100644 --- a/ca/renewer_test.go +++ b/ca/renewer_test.go @@ -1,6 +1,7 @@ package ca_test import ( + "context" "testing" "time" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestForceRenewTLSConfig(t *testing.T) { diff --git a/ca/server.go b/ca/server.go index a456df7900..c3e8999f89 100644 --- a/ca/server.go +++ b/ca/server.go @@ -2,6 +2,7 @@ package ca import ( "bytes" + "context" "crypto/subtle" "crypto/x509" "sync" @@ -15,7 +16,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/ca/server_test.go b/ca/server_test.go index d70b1cd0f3..4b74d29a32 100644 --- a/ca/server_test.go +++ b/ca/server_test.go @@ -2,6 +2,7 @@ package ca_test import ( "bytes" + "context" "crypto/tls" "crypto/x509" "fmt" @@ -25,7 +26,6 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "google.golang.org/grpc/codes" ) diff --git a/ca/testutils/cautils.go b/ca/testutils/cautils.go index c3b086ed76..eb8ca882c1 100644 --- a/ca/testutils/cautils.go +++ b/ca/testutils/cautils.go @@ -1,6 +1,7 @@ package testutils import ( + "context" "crypto" cryptorand "crypto/rand" "crypto/tls" @@ -29,7 +30,6 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) diff --git a/ca/transport.go b/ca/transport.go index 35943afbcb..69c4379b36 100644 --- a/ca/transport.go +++ b/ca/transport.go @@ -1,6 +1,7 @@ package ca import ( + "context" "crypto/tls" "crypto/x509" "crypto/x509/pkix" @@ -9,7 +10,6 @@ import ( "sync" "github.com/pkg/errors" - "golang.org/x/net/context" "google.golang.org/grpc/credentials" ) @@ -18,12 +18,6 @@ var ( alpnProtoStr = []string{"h2"} ) -type timeoutError struct{} - -func (timeoutError) Error() string { return "mutablecredentials: Dial timed out" } -func (timeoutError) Timeout() bool { return true } -func (timeoutError) Temporary() bool { return true } - // MutableTLSCreds is the credentials required for authenticating a connection using TLS. type MutableTLSCreds struct { // Mutex for the tls config diff --git a/cmd/swarm-bench/benchmark.go b/cmd/swarm-bench/benchmark.go index fe2b61f276..312649e502 100644 --- a/cmd/swarm-bench/benchmark.go +++ b/cmd/swarm-bench/benchmark.go @@ -1,13 +1,13 @@ package main import ( + "context" "fmt" "os" "strconv" "time" "github.com/docker/swarmkit/api" - "golang.org/x/net/context" "google.golang.org/grpc" ) diff --git a/cmd/swarm-bench/collector.go b/cmd/swarm-bench/collector.go index 62d5022868..7c886bbec9 100644 --- a/cmd/swarm-bench/collector.go +++ b/cmd/swarm-bench/collector.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "io" "net" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/rcrowley/go-metrics" - "golang.org/x/net/context" ) // Collector waits for tasks to phone home while collecting statistics. @@ -23,10 +23,7 @@ type Collector struct { func (c *Collector) Listen(port int) error { var err error c.ln, err = net.Listen("tcp", ":"+strconv.Itoa(port)) - if err != nil { - return err - } - return nil + return err } // Collect blocks until `count` tasks phoned home. diff --git a/cmd/swarm-bench/main.go b/cmd/swarm-bench/main.go index 8dab2244d8..445c7cace3 100644 --- a/cmd/swarm-bench/main.go +++ b/cmd/swarm-bench/main.go @@ -1,12 +1,12 @@ package main import ( + "context" "errors" "os" "time" "github.com/spf13/cobra" - "golang.org/x/net/context" ) var ( diff --git a/cmd/swarm-rafttool/common.go b/cmd/swarm-rafttool/common.go index a169b9af6e..dddb6e2428 100644 --- a/cmd/swarm-rafttool/common.go +++ b/cmd/swarm-rafttool/common.go @@ -1,13 +1,12 @@ package main import ( + "context" "errors" "io/ioutil" "os" "path/filepath" - "golang.org/x/net/context" - "github.com/coreos/etcd/pkg/fileutil" "github.com/coreos/etcd/wal/walpb" "github.com/docker/swarmkit/ca" diff --git a/cmd/swarmctl/cluster/common.go b/cmd/swarmctl/cluster/common.go index 0f9a922d1d..a667d05fbd 100644 --- a/cmd/swarmctl/cluster/common.go +++ b/cmd/swarmctl/cluster/common.go @@ -1,10 +1,9 @@ package cluster import ( + "context" "fmt" - "golang.org/x/net/context" - "github.com/docker/swarmkit/api" ) diff --git a/cmd/swarmctl/common/common.go b/cmd/swarmctl/common/common.go index 5872a77258..4f27e1a670 100644 --- a/cmd/swarmctl/common/common.go +++ b/cmd/swarmctl/common/common.go @@ -1,6 +1,7 @@ package common import ( + "context" "crypto/tls" "net" "strings" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/xnet" "github.com/spf13/cobra" "github.com/spf13/pflag" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) diff --git a/cmd/swarmctl/common/resolver.go b/cmd/swarmctl/common/resolver.go index 28d79ee70f..b4a9d416a1 100644 --- a/cmd/swarmctl/common/resolver.go +++ b/cmd/swarmctl/common/resolver.go @@ -1,11 +1,11 @@ package common import ( + "context" "fmt" "github.com/docker/swarmkit/api" "github.com/spf13/cobra" - "golang.org/x/net/context" ) // Resolver provides ID to Name resolution. diff --git a/cmd/swarmctl/config/common.go b/cmd/swarmctl/config/common.go index 247c3e5969..bbdc1d5c29 100644 --- a/cmd/swarmctl/config/common.go +++ b/cmd/swarmctl/config/common.go @@ -1,10 +1,10 @@ package config import ( + "context" "fmt" "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) func getConfig(ctx context.Context, c api.ControlClient, input string) (*api.Config, error) { diff --git a/cmd/swarmctl/network/common.go b/cmd/swarmctl/network/common.go index f4d4dc76d2..ad2c68bd73 100644 --- a/cmd/swarmctl/network/common.go +++ b/cmd/swarmctl/network/common.go @@ -1,10 +1,10 @@ package network import ( + "context" "fmt" "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) // GetNetwork tries to query for a network as an ID and if it can't be diff --git a/cmd/swarmctl/node/common.go b/cmd/swarmctl/node/common.go index 2d0beb9ad3..c70384817a 100644 --- a/cmd/swarmctl/node/common.go +++ b/cmd/swarmctl/node/common.go @@ -1,13 +1,12 @@ package node import ( + "context" "errors" "fmt" "reflect" "strings" - "golang.org/x/net/context" - "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/cmd/swarmctl/common" "github.com/spf13/cobra" @@ -49,49 +48,7 @@ func changeNodeAvailability(cmd *cobra.Command, args []string, availability api. Spec: spec, }) - if err != nil { - return err - } - - return nil -} - -func changeNodeMembership(cmd *cobra.Command, args []string, membership api.NodeSpec_Membership) error { - if len(args) == 0 { - return errors.New("missing node ID") - } - - if len(args) > 1 { - return errors.New("command takes exactly 1 argument") - } - - c, err := common.Dial(cmd) - if err != nil { - return err - } - node, err := getNode(common.Context(cmd), c, args[0]) - if err != nil { - return err - } - spec := &node.Spec - - if spec.Membership == membership { - return errNoChange - } - - spec.Membership = membership - - _, err = c.UpdateNode(common.Context(cmd), &api.UpdateNodeRequest{ - NodeID: node.ID, - NodeVersion: &node.Meta.Version, - Spec: spec, - }) - - if err != nil { - return err - } - - return nil + return err } func changeNodeRole(cmd *cobra.Command, args []string, role api.NodeRole) error { @@ -125,11 +82,7 @@ func changeNodeRole(cmd *cobra.Command, args []string, role api.NodeRole) error Spec: spec, }) - if err != nil { - return err - } - - return nil + return err } func getNode(ctx context.Context, c api.ControlClient, input string) (*api.Node, error) { @@ -208,9 +161,5 @@ func updateNode(cmd *cobra.Command, args []string) error { Spec: spec, }) - if err != nil { - return err - } - - return nil + return err } diff --git a/cmd/swarmctl/secret/common.go b/cmd/swarmctl/secret/common.go index b6d5b0d4c3..5f7ca4e888 100644 --- a/cmd/swarmctl/secret/common.go +++ b/cmd/swarmctl/secret/common.go @@ -1,10 +1,10 @@ package secret import ( + "context" "fmt" "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) func getSecret(ctx context.Context, c api.ControlClient, input string) (*api.Secret, error) { diff --git a/cmd/swarmctl/service/common.go b/cmd/swarmctl/service/common.go index bab0a32d37..5d5db81fb0 100644 --- a/cmd/swarmctl/service/common.go +++ b/cmd/swarmctl/service/common.go @@ -1,10 +1,9 @@ package service import ( + "context" "fmt" - "golang.org/x/net/context" - "github.com/docker/swarmkit/api" ) diff --git a/cmd/swarmctl/service/flagparser/tmpfs.go b/cmd/swarmctl/service/flagparser/tmpfs.go index 0d7a0e276e..aab4509bb2 100644 --- a/cmd/swarmctl/service/flagparser/tmpfs.go +++ b/cmd/swarmctl/service/flagparser/tmpfs.go @@ -64,7 +64,7 @@ func parseTmpfs(flags *pflag.FlagSet, spec *api.ServiceSpec) error { // remove suffix and try again suffix := meat[len(meat)-1] meat = meat[:len(meat)-1] - var multiplier int64 = 1 + var multiplier int64 switch suffix { case 'g': multiplier = 1 << 30 diff --git a/cmd/swarmctl/service/logs.go b/cmd/swarmctl/service/logs.go index df7d0a5dcc..12ba7af664 100644 --- a/cmd/swarmctl/service/logs.go +++ b/cmd/swarmctl/service/logs.go @@ -1,6 +1,7 @@ package service import ( + "context" "fmt" "io" "os" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/cmd/swarmctl/common" "github.com/pkg/errors" "github.com/spf13/cobra" - "golang.org/x/net/context" ) var ( diff --git a/cmd/swarmd/main.go b/cmd/swarmd/main.go index 3297f1ae7a..88c4196e35 100644 --- a/cmd/swarmd/main.go +++ b/cmd/swarmd/main.go @@ -1,6 +1,7 @@ package main import ( + "context" _ "expvar" "fmt" "net" @@ -23,7 +24,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "golang.org/x/net/context" ) var externalCAOpt cli.ExternalCAOpt diff --git a/direct.mk b/direct.mk index 334d3fc81b..fd1c32038b 100644 --- a/direct.mk +++ b/direct.mk @@ -1,9 +1,6 @@ .DEFAULT_GOAL = all .PHONY: all -all: check binaries test integration-tests ## run fmt, vet, lint, build the binaries and run the tests - -.PHONY: check -check: fmt vet lint ineffassign misspell +all: check binaries test integration-tests ## run check, build the binaries and run the tests .PHONY: ci ci: check binaries checkprotos coverage coverage-integration ## to be used by the CI @@ -20,10 +17,8 @@ version/version.go: setup: ## install dependencies @echo "🐳 $@" # TODO(stevvooe): Install these from the vendor directory - @go get -u github.com/golang/lint/golint - #@go get -u github.com/kisielk/errcheck - @go get -u github.com/gordonklaus/ineffassign - @go get -u github.com/client9/misspell/cmd/misspell + # install golangci-lint version 1.17.1 to ./bin/golangci-lint + @curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.17.1 @go get -u github.com/lk4d4/vndr @go get -u github.com/stevvooe/protobuild @@ -44,42 +39,19 @@ checkprotos: generate ## check if protobufs needs to be generated again ((git diff | cat) && \ (echo "👹 please run 'make generate' when making changes to proto files" && false)) -# Depends on binaries because vet will silently fail if it can't load compiled -# imports -.PHONY: vet -vet: binaries ## run go vet - @echo "🐳 $@" - @test -z "$$(go vet ${PACKAGES} 2>&1 | grep -v 'constant [0-9]* not a string in call to Errorf' | egrep -v '(timestamp_test.go|duration_test.go|exit status 1)' | tee /dev/stderr)" - -.PHONY: misspell -misspell: +.PHONY: check +check: fmt-proto +check: ## Run various source code validation tools @echo "🐳 $@" - @test -z "$$(find . -type f | grep -v vendor/ | grep -v bin/ | grep -v .git/ | grep -v MAINTAINERS | xargs misspell | tee /dev/stderr)" + @./bin/golangci-lint run -.PHONY: fmt -fmt: ## run go fmt - @echo "🐳 $@" - @test -z "$$(gofmt -s -l . | grep -v vendor/ | grep -v ".pb.go$$" | tee /dev/stderr)" || \ - (echo "👹 please format Go code with 'gofmt -s -w'" && false) +.PHONY: fmt-proto +fmt-proto: @test -z "$$(find . -path ./vendor -prune -o ! -name timestamp.proto ! -name duration.proto -name '*.proto' -type f -exec grep -Hn -e "^ " {} \; | tee /dev/stderr)" || \ (echo "👹 please indent proto files with tabs only" && false) @test -z "$$(find . -path ./vendor -prune -o -name '*.proto' -type f -exec grep -Hn "Meta meta = " {} \; | grep -v '(gogoproto.nullable) = false' | tee /dev/stderr)" || \ (echo "👹 meta fields in proto files must have option (gogoproto.nullable) = false" && false) -.PHONY: lint -lint: ## run go lint - @echo "🐳 $@" - @test -z "$$(golint ./... | grep -v vendor/ | grep -v ".pb.go:" | tee /dev/stderr)" - -.PHONY: ineffassign -ineffassign: ## run ineffassign - @echo "🐳 $@" - @test -z "$$(ineffassign . | grep -v vendor/ | grep -v ".pb.go:" | tee /dev/stderr)" - -#errcheck: ## run go errcheck -# @echo "🐳 $@" -# @test -z "$$(errcheck ./... | grep -v vendor/ | grep -v ".pb.go:" | tee /dev/stderr)" - .PHONY: build build: ## build the go packages @echo "🐳 $@" diff --git a/integration/api.go b/integration/api.go index 0f44037887..b0042309dd 100644 --- a/integration/api.go +++ b/integration/api.go @@ -1,8 +1,9 @@ package integration import ( + "context" + "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) type dummyAPI struct { diff --git a/integration/cluster.go b/integration/cluster.go index e199d48f86..8dfe4a1dd7 100644 --- a/integration/cluster.go +++ b/integration/cluster.go @@ -1,6 +1,7 @@ package integration import ( + "context" "crypto/tls" "fmt" "math/rand" @@ -19,7 +20,6 @@ import ( "github.com/docker/swarmkit/node" "github.com/docker/swarmkit/testutils" "github.com/sirupsen/logrus" - "golang.org/x/net/context" ) const opsTimeout = 64 * time.Second @@ -39,23 +39,6 @@ type testCluster struct { var testnameKey struct{} -// NewCluster creates new cluster to which nodes can be added. -// AcceptancePolicy is set to most permissive mode on first manager node added. -func newTestCluster(testname string, fips bool) *testCluster { - ctx, cancel := context.WithCancel(context.Background()) - ctx = context.WithValue(ctx, testnameKey, testname) - c := &testCluster{ - ctx: ctx, - cancel: cancel, - nodes: make(map[string]*testNode), - nodesOrder: make(map[string]int), - errs: make(chan error, 1024), - fips: fips, - } - c.api = &dummyAPI{c: c} - return c -} - // Stop makes best effort to stop all nodes and close connections to them. func (c *testCluster) Stop() error { c.cancel() diff --git a/integration/integration_test.go b/integration/integration_test.go index 5fc6ef0efb..4c3011575c 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -2,6 +2,7 @@ package integration import ( "bytes" + "context" "flag" "fmt" "io/ioutil" @@ -14,8 +15,6 @@ import ( "github.com/docker/swarmkit/node" - "golang.org/x/net/context" - "reflect" "github.com/cloudflare/cfssl/helpers" @@ -63,6 +62,23 @@ func TestMain(m *testing.M) { os.Exit(res) } +// newTestCluster creates new cluster to which nodes can be added. +// AcceptancePolicy is set to most permissive mode on first manager node added. +func newTestCluster(testname string, fips bool) *testCluster { + ctx, cancel := context.WithCancel(context.Background()) + ctx = context.WithValue(ctx, testnameKey, testname) + c := &testCluster{ + ctx: ctx, + cancel: cancel, + nodes: make(map[string]*testNode), + nodesOrder: make(map[string]int), + errs: make(chan error, 1024), + fips: fips, + } + c.api = &dummyAPI{c: c} + return c +} + // pollClusterReady calls control api until all conditions are true: // * all nodes are ready // * all managers has membership == accepted diff --git a/integration/node.go b/integration/node.go index 6b2100bfdf..263c3b7eec 100644 --- a/integration/node.go +++ b/integration/node.go @@ -1,6 +1,7 @@ package integration import ( + "context" "fmt" "io/ioutil" "os" @@ -15,7 +16,6 @@ import ( "github.com/docker/swarmkit/ca" "github.com/docker/swarmkit/node" "github.com/docker/swarmkit/testutils" - "golang.org/x/net/context" ) // TestNode is representation of *agent.Node. It stores listeners, connections, diff --git a/ioutils/ioutils_test.go b/ioutils/ioutils_test.go index 40717a5108..56a69c4ec6 100644 --- a/ioutils/ioutils_test.go +++ b/ioutils/ioutils_test.go @@ -25,7 +25,7 @@ func TestAtomicWriteToFile(t *testing.T) { t.Fatalf("Error reading from file: %v", err) } - if bytes.Compare(actual, expected) != 0 { + if !bytes.Equal(actual, expected) { t.Fatalf("Data mismatch, expected %q, got %q", expected, actual) } } diff --git a/log/context.go b/log/context.go index ac4f848806..cc1d590f11 100644 --- a/log/context.go +++ b/log/context.go @@ -1,10 +1,10 @@ package log import ( + "context" "path" "github.com/sirupsen/logrus" - "golang.org/x/net/context" ) var ( diff --git a/log/context_test.go b/log/context_test.go index ddff398938..6c59874c0a 100644 --- a/log/context_test.go +++ b/log/context_test.go @@ -1,10 +1,10 @@ package log import ( + "context" "testing" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) func TestLoggerContext(t *testing.T) { diff --git a/log/grpc.go b/log/grpc.go index 0417c944c5..bced5cfa1b 100644 --- a/log/grpc.go +++ b/log/grpc.go @@ -1,8 +1,9 @@ package log import ( + "context" + "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/grpclog" ) diff --git a/manager/allocator/allocator.go b/manager/allocator/allocator.go index e8b7e88c47..b4cc1c9e86 100644 --- a/manager/allocator/allocator.go +++ b/manager/allocator/allocator.go @@ -1,6 +1,7 @@ package allocator import ( + "context" "sync" "github.com/docker/docker/pkg/plugingetter" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/manager/allocator/cnmallocator" "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) // Allocator controls how the allocation stage in the manager is handled. diff --git a/manager/allocator/allocator_linux_test.go b/manager/allocator/allocator_linux_test.go index b64832eba1..7ea85ebe1a 100644 --- a/manager/allocator/allocator_linux_test.go +++ b/manager/allocator/allocator_linux_test.go @@ -1,10 +1,9 @@ package allocator import ( + "context" "testing" - "golang.org/x/net/context" - "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" diff --git a/manager/allocator/allocator_test.go b/manager/allocator/allocator_test.go index 93186d8554..e233986110 100644 --- a/manager/allocator/allocator_test.go +++ b/manager/allocator/allocator_test.go @@ -1,14 +1,13 @@ package allocator import ( + "context" "net" "runtime/debug" "strconv" "testing" "time" - "golang.org/x/net/context" - "github.com/docker/go-events" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/state" @@ -1414,6 +1413,126 @@ func TestNodeAllocator(t *testing.T) { isValidNode(t, node1, node1FromStore, []string{"ingress", "overlayID1"}) } +// TestNodeAttachmentOnLeadershipChange tests that a Node which is only partly +// allocated during a leadership change is correctly allocated afterward +func TestNodeAttachmentOnLeadershipChange(t *testing.T) { + s := store.NewMemoryStore(nil) + assert.NotNil(t, s) + defer s.Close() + + a, err := New(s, nil, nil) + assert.NoError(t, err) + assert.NotNil(t, a) + + net1 := &api.Network{ + ID: "ingress", + Spec: api.NetworkSpec{ + Annotations: api.Annotations{ + Name: "ingress", + }, + Ingress: true, + }, + } + + net2 := &api.Network{ + ID: "net2", + Spec: api.NetworkSpec{ + Annotations: api.Annotations{ + Name: "net2", + }, + }, + } + + node1 := &api.Node{ + ID: "node1", + } + + task1 := &api.Task{ + ID: "task1", + NodeID: node1.ID, + DesiredState: api.TaskStateRunning, + Spec: api.TaskSpec{}, + } + + // this task is not yet assigned. we will assign it to node1 after running + // the allocator a 2nd time. we should create it now so that its network + // attachments are allocated. + task2 := &api.Task{ + ID: "task2", + DesiredState: api.TaskStateRunning, + Spec: api.TaskSpec{ + Networks: []*api.NetworkAttachmentConfig{ + { + Target: "net2", + }, + }, + }, + } + + // before starting the allocator, populate with these + assert.NoError(t, s.Update(func(tx store.Tx) error { + require.NoError(t, store.CreateNetwork(tx, net1)) + require.NoError(t, store.CreateNetwork(tx, net2)) + require.NoError(t, store.CreateNode(tx, node1)) + require.NoError(t, store.CreateTask(tx, task1)) + require.NoError(t, store.CreateTask(tx, task2)) + return nil + })) + + // now start the allocator, let it allocate all of these objects, and then + // stop it. it's easier to do this than to manually assign all of the + // values + + nodeWatch, cancel := state.Watch(s.WatchQueue(), api.EventUpdateNode{}, api.EventDeleteNode{}) + defer cancel() + netWatch, cancel := state.Watch(s.WatchQueue(), api.EventUpdateNetwork{}, api.EventDeleteNetwork{}) + defer cancel() + taskWatch, cancel := state.Watch(s.WatchQueue(), api.EventUpdateTask{}) + defer cancel() + + ctx, ctxCancel := context.WithCancel(context.Background()) + go func() { + assert.NoError(t, a.Run(ctx)) + }() + + // validate that everything gets allocated + watchNetwork(t, netWatch, false, isValidNetwork) + watchNetwork(t, netWatch, false, isValidNetwork) + watchNode(t, nodeWatch, false, isValidNode, node1, []string{"ingress"}) + watchTask(t, s, taskWatch, false, isValidTask) + + // once everything is created, go ahead and stop the allocator + a.Stop() + ctxCancel() + + // now update task2 to assign it to node1 + s.Update(func(tx store.Tx) error { + task := store.GetTask(tx, task2.ID) + require.NotNil(t, task) + // make sure it has 1 network attachment + assert.Len(t, task.Networks, 1) + task.NodeID = node1.ID + require.NoError(t, store.UpdateTask(tx, task)) + return nil + }) + + // and now we'll start a new allocator. + a2, err := New(s, nil, nil) + assert.NoError(t, err) + assert.NotNil(t, a2) + + ctx2, cancel2 := context.WithCancel(context.Background()) + go func() { + assert.NoError(t, a2.Run(ctx2)) + }() + defer a2.Stop() + defer cancel2() + + // now we should see the node get allocated + watchNode(t, nodeWatch, false, isValidNode, node1, []string{"ingress"}) + watchNode(t, nodeWatch, false, isValidNode, node1, []string{"ingress", "net2"}) +} + func isValidNode(t assert.TestingT, originalNode, updatedNode *api.Node, networks []string) bool { if !assert.Equal(t, originalNode.ID, updatedNode.ID) { diff --git a/manager/allocator/cnmallocator/networkallocator.go b/manager/allocator/cnmallocator/networkallocator.go index 7a786406e1..c1ffc06a42 100644 --- a/manager/allocator/cnmallocator/networkallocator.go +++ b/manager/allocator/cnmallocator/networkallocator.go @@ -1,6 +1,7 @@ package cnmallocator import ( + "context" "fmt" "net" "strings" @@ -16,7 +17,6 @@ import ( "github.com/docker/swarmkit/manager/allocator/networkallocator" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" ) const ( @@ -815,8 +815,7 @@ func (na *cnmNetworkAllocator) resolveDriver(n *api.Network) (*networkDriver, er d, drvcap := na.drvRegistry.Driver(dName) if d == nil { - var err error - err = na.loadDriver(dName) + err := na.loadDriver(dName) if err != nil { return nil, err } diff --git a/manager/allocator/cnmallocator/portallocator.go b/manager/allocator/cnmallocator/portallocator.go index 113f900242..81447cbdb4 100644 --- a/manager/allocator/cnmallocator/portallocator.go +++ b/manager/allocator/cnmallocator/portallocator.go @@ -407,12 +407,12 @@ func (ps *portSpace) allocate(p *api.PortConfig) (err error) { } defer func() { if err != nil { - ps.dynamicPortSpace.Release(uint64(swarmPort)) + ps.dynamicPortSpace.Release(swarmPort) } }() // Make sure we allocate the same port from the master space. - if err = ps.masterPortSpace.GetSpecificID(uint64(swarmPort)); err != nil { + if err = ps.masterPortSpace.GetSpecificID(swarmPort); err != nil { return } diff --git a/manager/allocator/network.go b/manager/allocator/network.go index e4d5b61827..f9171628f4 100644 --- a/manager/allocator/network.go +++ b/manager/allocator/network.go @@ -1,6 +1,7 @@ package allocator import ( + "context" "fmt" "time" @@ -13,7 +14,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/protobuf/ptypes" "github.com/pkg/errors" - "golang.org/x/net/context" ) const ( @@ -998,6 +998,10 @@ func (a *Allocator) allocateNode(ctx context.Context, node *api.Node, existingAd } if lbAttachment == nil { + // if we're restoring state, we should not add an attachment here. + if existingAddressesOnly { + continue + } lbAttachment = &api.NetworkAttachment{} node.Attachments = append(node.Attachments, lbAttachment) } diff --git a/manager/constraint/constraint.go b/manager/constraint/constraint.go index 9f13217ae4..6c49c07728 100644 --- a/manager/constraint/constraint.go +++ b/manager/constraint/constraint.go @@ -56,7 +56,7 @@ func Parse(env []string) ([]Constraint, error) { part0 := strings.TrimSpace(parts[0]) // validate key matched := alphaNumeric.MatchString(part0) - if matched == false { + if !matched { return nil, fmt.Errorf("key '%s' is invalid", part0) } @@ -64,7 +64,7 @@ func Parse(env []string) ([]Constraint, error) { // validate Value matched = valuePattern.MatchString(part1) - if matched == false { + if !matched { return nil, fmt.Errorf("value '%s' is invalid", part1) } // TODO(dongluochen): revisit requirements to see if globing or regex are useful diff --git a/manager/controlapi/cluster.go b/manager/controlapi/cluster.go index ad24804484..4865b81bad 100644 --- a/manager/controlapi/cluster.go +++ b/manager/controlapi/cluster.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "strings" "time" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/manager/encryption" "github.com/docker/swarmkit/manager/state/store" gogotypes "github.com/gogo/protobuf/types" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/controlapi/cluster_test.go b/manager/controlapi/cluster_test.go index 44ae9cfc2e..346b057fd1 100644 --- a/manager/controlapi/cluster_test.go +++ b/manager/controlapi/cluster_test.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "fmt" "testing" "time" @@ -14,7 +15,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "google.golang.org/grpc/codes" ) diff --git a/manager/controlapi/config.go b/manager/controlapi/config.go index ae08885b00..bc8726fb86 100644 --- a/manager/controlapi/config.go +++ b/manager/controlapi/config.go @@ -2,6 +2,7 @@ package controlapi import ( "bytes" + "context" "strings" "github.com/docker/swarmkit/api" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/state/store" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/controlapi/config_test.go b/manager/controlapi/config_test.go index e794a3be0f..2d2de5f66c 100644 --- a/manager/controlapi/config_test.go +++ b/manager/controlapi/config_test.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "fmt" "strings" "testing" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/testutils" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" "google.golang.org/grpc/codes" ) diff --git a/manager/controlapi/network.go b/manager/controlapi/network.go index 481b0cfe4b..d3047fec72 100644 --- a/manager/controlapi/network.go +++ b/manager/controlapi/network.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "net" "github.com/docker/docker/pkg/plugingetter" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/manager/allocator" "github.com/docker/swarmkit/manager/allocator/networkallocator" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/controlapi/network_test.go b/manager/controlapi/network_test.go index 632ca59110..a8e6826134 100644 --- a/manager/controlapi/network_test.go +++ b/manager/controlapi/network_test.go @@ -1,10 +1,10 @@ package controlapi import ( + "context" "testing" "github.com/docker/swarmkit/testutils" - "golang.org/x/net/context" "google.golang.org/grpc/codes" diff --git a/manager/controlapi/node.go b/manager/controlapi/node.go index b2d15df07a..6e8bdba5bd 100644 --- a/manager/controlapi/node.go +++ b/manager/controlapi/node.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "crypto/x509" "encoding/pem" @@ -8,7 +9,6 @@ import ( "github.com/docker/swarmkit/manager/state/raft/membership" "github.com/docker/swarmkit/manager/state/store" gogotypes "github.com/gogo/protobuf/types" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -254,24 +254,33 @@ func (s *Server) UpdateNode(ctx context.Context, request *api.UpdateNodeRequest) }, nil } -func removeNodeAttachments(tx store.Tx, nodeID string) error { - // orphan the node's attached containers. if we don't do this, the - // network these attachments are connected to will never be removeable +func orphanNodeTasks(tx store.Tx, nodeID string) error { + // when a node is deleted, all of its tasks are irrecoverably removed. + // additionally, the Dispatcher can no longer be relied on to update the + // task status. Therefore, when the node is removed, we must additionally + // move all of its assigned tasks to the Orphaned state, so that their + // resources can be cleaned up. tasks, err := store.FindTasks(tx, store.ByNodeID(nodeID)) if err != nil { return err } for _, task := range tasks { - // if the task is an attachment, then we just delete it. the allocator - // will do the heavy lifting. basically, GetAttachment will return the - // attachment if that's the kind of runtime, or nil if it's not. - if task.Spec.GetAttachment() != nil { - // don't delete the task. instead, update it to `ORPHANED` so that - // the taskreaper will clean it up. - task.Status.State = api.TaskStateOrphaned - if err := store.UpdateTask(tx, task); err != nil { - return err + // this operation must occur within the same transaction boundary. If + // we cannot accomplish this task orphaning in the same transaction, we + // could crash or die between transactions and not get a chance to do + // this. however, in cases were there is an exceptionally large number + // of tasks for a node, this may cause the transaction to exceed the + // max message size. + // + // therefore, we restrict updating to only tasks in a non-terminal + // state. Tasks in a terminal state do not need to be updated. + if task.Status.State < api.TaskStateCompleted { + task.Status = api.TaskStatus{ + Timestamp: gogotypes.TimestampNow(), + State: api.TaskStateOrphaned, + Message: "Task belonged to a node that has been deleted", } + store.UpdateTask(tx, task) } } return nil @@ -342,7 +351,7 @@ func (s *Server) RemoveNode(ctx context.Context, request *api.RemoveNodeRequest) return err } - if err := removeNodeAttachments(tx, request.NodeID); err != nil { + if err := orphanNodeTasks(tx, request.NodeID); err != nil { return err } diff --git a/manager/controlapi/node_test.go b/manager/controlapi/node_test.go index 7c05bab801..4e737bbb0c 100644 --- a/manager/controlapi/node_test.go +++ b/manager/controlapi/node_test.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "fmt" "io/ioutil" "testing" @@ -14,7 +15,6 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" ) @@ -942,10 +942,8 @@ func TestUpdateNodeDemote(t *testing.T) { testUpdateNodeDemote(t) } -// TestRemoveNodeAttachments tests the unexported removeNodeAttachments -// function. This avoids us having to update the TestRemoveNodes function to -// test all of this logic -func TestRemoveNodeAttachments(t *testing.T) { +// TestRemoveNodeAttachments tests the unexported orphanNodeTasks +func TestOrphanNodeTasks(t *testing.T) { // first, set up a store and all that ts := newTestServer(t) defer ts.Stop() @@ -1083,28 +1081,50 @@ func TestRemoveNodeAttachments(t *testing.T) { }, }, } - return store.CreateTask(tx, task4) + if err := store.CreateTask(tx, task4); err != nil { + return err + } + + // 5.) A regular task that's already in a terminal state on the node, + // which does not need to be updated. + task5 := &api.Task{ + ID: "task5", + NodeID: "id2", + DesiredState: api.TaskStateRunning, + Status: api.TaskStatus{ + // use TaskStateCompleted, as this is the earliest terminal + // state (this ensures we don't actually use <= instead of <) + State: api.TaskStateCompleted, + }, + Spec: api.TaskSpec{ + Runtime: &api.TaskSpec_Container{ + Container: &api.ContainerSpec{}, + }, + }, + } + return store.CreateTask(tx, task5) }) require.NoError(t, err) // Now, call the function with our nodeID. make sure it returns no error err = ts.Store.Update(func(tx store.Tx) error { - return removeNodeAttachments(tx, "id2") + return orphanNodeTasks(tx, "id2") }) require.NoError(t, err) - // Now, make sure only task1, the network-attacahed task on id2, was - // removed + // Now, make sure only tasks 1 and 3, the tasks on the node we're deleting + // removed, are removed ts.Store.View(func(tx store.ReadTx) { tasks, err := store.FindTasks(tx, store.All) require.NoError(t, err) - // should only be 3 tasks left - require.Len(t, tasks, 4) - // and the list should not contain task1 + require.Len(t, tasks, 5) + // and the list should not contain task1 or task2 for _, task := range tasks { require.NotNil(t, task) - if task.ID == "task1" { + if task.ID == "task1" || task.ID == "task3" { require.Equal(t, task.Status.State, api.TaskStateOrphaned) + } else { + require.NotEqual(t, task.Status.State, api.TaskStateOrphaned) } } }) diff --git a/manager/controlapi/secret.go b/manager/controlapi/secret.go index fdcd2c412c..f3d87d1a7c 100644 --- a/manager/controlapi/secret.go +++ b/manager/controlapi/secret.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "crypto/subtle" "strings" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/state/store" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/controlapi/secret_test.go b/manager/controlapi/secret_test.go index 25dab57856..b473318a81 100644 --- a/manager/controlapi/secret_test.go +++ b/manager/controlapi/secret_test.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "fmt" "strings" "testing" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/testutils" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" "google.golang.org/grpc/codes" ) diff --git a/manager/controlapi/server_test.go b/manager/controlapi/server_test.go index c788c796f4..3f07db8781 100644 --- a/manager/controlapi/server_test.go +++ b/manager/controlapi/server_test.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "io/ioutil" "net" "os" @@ -15,7 +16,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" stateutils "github.com/docker/swarmkit/manager/state/testutils" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) type testServer struct { diff --git a/manager/controlapi/service.go b/manager/controlapi/service.go index 3912052bf0..a3ee2c7a4a 100644 --- a/manager/controlapi/service.go +++ b/manager/controlapi/service.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "errors" "reflect" "strings" @@ -18,7 +19,6 @@ import ( "github.com/docker/swarmkit/protobuf/ptypes" "github.com/docker/swarmkit/template" gogotypes "github.com/gogo/protobuf/types" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -197,7 +197,7 @@ func validateHealthCheck(hc *api.HealthConfig) error { if err != nil { return err } - if interval != 0 && interval < time.Duration(minimumDuration) { + if interval != 0 && interval < minimumDuration { return status.Errorf(codes.InvalidArgument, "ContainerSpec: Interval in HealthConfig cannot be less than %s", minimumDuration) } } @@ -207,7 +207,7 @@ func validateHealthCheck(hc *api.HealthConfig) error { if err != nil { return err } - if timeout != 0 && timeout < time.Duration(minimumDuration) { + if timeout != 0 && timeout < minimumDuration { return status.Errorf(codes.InvalidArgument, "ContainerSpec: Timeout in HealthConfig cannot be less than %s", minimumDuration) } } @@ -217,7 +217,7 @@ func validateHealthCheck(hc *api.HealthConfig) error { if err != nil { return err } - if sp != 0 && sp < time.Duration(minimumDuration) { + if sp != 0 && sp < minimumDuration { return status.Errorf(codes.InvalidArgument, "ContainerSpec: StartPeriod in HealthConfig cannot be less than %s", minimumDuration) } } @@ -680,13 +680,17 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe return store.CreateService(tx, service) }) - if err != nil { + switch err { + case store.ErrNameConflict: + // Enhance the name-confict error to include the service name. The original + // `ErrNameConflict` error-message is included for backward-compatibility + // with older consumers of the API performing string-matching. + return nil, status.Errorf(codes.AlreadyExists, "%s: service %s already exists", err.Error(), request.Spec.Annotations.Name) + case nil: + return &api.CreateServiceResponse{Service: service}, nil + default: return nil, err } - - return &api.CreateServiceResponse{ - Service: service, - }, nil } // GetService returns a Service given a ServiceID. @@ -896,7 +900,12 @@ func (s *Server) ListServices(ctx context.Context, request *api.ListServicesRequ } }) if err != nil { - return nil, err + switch err { + case store.ErrInvalidFindBy: + return nil, status.Errorf(codes.InvalidArgument, err.Error()) + default: + return nil, err + } } if request.Filters != nil { diff --git a/manager/controlapi/service_test.go b/manager/controlapi/service_test.go index 1d8687d2e2..df34ffbaba 100644 --- a/manager/controlapi/service_test.go +++ b/manager/controlapi/service_test.go @@ -1,6 +1,7 @@ package controlapi import ( + "context" "fmt" "strings" "testing" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/testutils" gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" "google.golang.org/grpc/codes" ) @@ -615,6 +615,18 @@ func TestCreateService(t *testing.T) { _, err = ts.Client.CreateService(context.Background(), &api.CreateServiceRequest{Spec: spec}) assert.Error(t, err) assert.Equal(t, codes.InvalidArgument, testutils.ErrorCode(err)) + + spec = createSpec("notunique", "image", 1) + _, err = ts.Client.CreateService(context.Background(), &api.CreateServiceRequest{Spec: spec}) + assert.NoError(t, err) + + r, err = ts.Client.CreateService(context.Background(), &api.CreateServiceRequest{Spec: spec}) + assert.Error(t, err) + assert.Equal(t, codes.AlreadyExists, testutils.ErrorCode(err)) + + // Make sure the error contains "name conflicts with an existing object" for + // backward-compatibility with older clients doing string-matching... + assert.Contains(t, err.Error(), "name conflicts with an existing object") } func TestSecretValidation(t *testing.T) { @@ -870,6 +882,16 @@ func TestUpdateService(t *testing.T) { }) assert.Error(t, err) + // Attempt to update service name; renaming is not implemented + r.Service.Spec.Annotations.Name = "newname" + _, err = ts.Client.UpdateService(context.Background(), &api.UpdateServiceRequest{ + ServiceID: service.ID, + Spec: &r.Service.Spec, + ServiceVersion: version, + }) + assert.Error(t, err) + assert.Equal(t, codes.Unimplemented, testutils.ErrorCode(err)) + // test port conflicts spec2 := createSpec("name2", "image", 1) spec2.Endpoint = &api.EndpointSpec{Ports: []*api.PortConfig{ diff --git a/manager/controlapi/task.go b/manager/controlapi/task.go index dc56e74105..5f85f9a93c 100644 --- a/manager/controlapi/task.go +++ b/manager/controlapi/task.go @@ -1,11 +1,12 @@ package controlapi import ( + "context" + "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api/naming" "github.com/docker/swarmkit/manager/orchestrator" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/controlapi/task_test.go b/manager/controlapi/task_test.go index faafd547fd..17fe5e01cd 100644 --- a/manager/controlapi/task_test.go +++ b/manager/controlapi/task_test.go @@ -1,11 +1,11 @@ package controlapi import ( + "context" "strings" "testing" "github.com/docker/swarmkit/testutils" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "github.com/docker/swarmkit/api" diff --git a/manager/dirty_test.go b/manager/dirty_test.go index 259cedcb2f..3f6468f8b2 100644 --- a/manager/dirty_test.go +++ b/manager/dirty_test.go @@ -1,12 +1,11 @@ package manager import ( + "context" "io/ioutil" "os" "testing" - "golang.org/x/net/context" - "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/ca" "github.com/docker/swarmkit/ca/testutils" diff --git a/manager/dispatcher/dispatcher.go b/manager/dispatcher/dispatcher.go index 569ab26375..d1db2fdc83 100644 --- a/manager/dispatcher/dispatcher.go +++ b/manager/dispatcher/dispatcher.go @@ -1,6 +1,7 @@ package dispatcher import ( + "context" "fmt" "net" "strconv" @@ -21,7 +22,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -238,7 +238,7 @@ func (d *Dispatcher) Run(ctx context.Context) error { if err != nil { return err } - if err == nil && len(clusters) == 1 { + if len(clusters) == 1 { heartbeatPeriod, err := gogotypes.DurationFromProto(clusters[0].Spec.Dispatcher.HeartbeatPeriod) if err == nil && heartbeatPeriod > 0 { d.config.HeartbeatPeriod = heartbeatPeriod @@ -1090,14 +1090,10 @@ func (d *Dispatcher) moveTasksToOrphaned(nodeID string) error { task.Status.State = api.TaskStateOrphaned } - if err := batch.Update(func(tx store.Tx) error { - err := store.UpdateTask(tx, task) - if err != nil { - return err - } - - return nil - }); err != nil { + err := batch.Update(func(tx store.Tx) error { + return store.UpdateTask(tx, task) + }) + if err != nil { return err } diff --git a/manager/dispatcher/dispatcher_test.go b/manager/dispatcher/dispatcher_test.go index c4b1509b01..e62baa8052 100644 --- a/manager/dispatcher/dispatcher_test.go +++ b/manager/dispatcher/dispatcher_test.go @@ -1,6 +1,7 @@ package dispatcher import ( + "context" "crypto/tls" "encoding/json" "errors" @@ -13,8 +14,6 @@ import ( "testing" "time" - "golang.org/x/net/context" - "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" @@ -2088,7 +2087,6 @@ func (m *mockPluginGetter) GetAllManagedPluginsByCap(capability string) []plugin return nil } func (m *mockPluginGetter) Handle(capability string, callback func(string, *plugins.Client)) { - return } // MockPlugin mocks a v2 docker plugin diff --git a/manager/dispatcher/nodes.go b/manager/dispatcher/nodes.go index cf35bb869a..fae6dc5f82 100644 --- a/manager/dispatcher/nodes.go +++ b/manager/dispatcher/nodes.go @@ -156,7 +156,7 @@ func (s *nodeStore) Heartbeat(id, sid string) (time.Duration, error) { return 0, err } period := s.periodChooser.Choose() // base period for node - grace := period * time.Duration(s.gracePeriodMultiplierNormal) + grace := period * s.gracePeriodMultiplierNormal rn.mu.Lock() rn.Heartbeat.Update(grace) rn.Heartbeat.Beat() diff --git a/manager/drivers/provider.go b/manager/drivers/provider.go index 0d9be6119d..97c36fe73d 100644 --- a/manager/drivers/provider.go +++ b/manager/drivers/provider.go @@ -22,7 +22,7 @@ func (m *DriverProvider) NewSecretDriver(driver *api.Driver) (*SecretDriver, err if m.pluginGetter == nil { return nil, fmt.Errorf("plugin getter is nil") } - if driver == nil && driver.Name == "" { + if driver == nil || driver.Name == "" { return nil, fmt.Errorf("driver specification is nil") } // Search for the specified plugin diff --git a/manager/health/health.go b/manager/health/health.go index ef6658b09d..d75cbf4b60 100644 --- a/manager/health/health.go +++ b/manager/health/health.go @@ -8,10 +8,10 @@ package health import ( + "context" "sync" "github.com/docker/swarmkit/api" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/keymanager/keymanager.go b/manager/keymanager/keymanager.go index e61979cb36..7a5d7bf14d 100644 --- a/manager/keymanager/keymanager.go +++ b/manager/keymanager/keymanager.go @@ -6,6 +6,7 @@ package keymanager // which is used to exchange service discovery and overlay network control // plane information. It can also be used to encrypt overlay data traffic. import ( + "context" cryptorand "crypto/rand" "encoding/binary" "sync" @@ -15,7 +16,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/state/store" "github.com/pkg/errors" - "golang.org/x/net/context" ) const ( diff --git a/manager/keymanager/keymanager_test.go b/manager/keymanager/keymanager_test.go index fc4e06f340..6b91cbf0bd 100644 --- a/manager/keymanager/keymanager_test.go +++ b/manager/keymanager/keymanager_test.go @@ -2,13 +2,13 @@ package keymanager import ( "bytes" + "context" "testing" "time" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/state/store" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) func createClusterSpec(name string) *api.ClusterSpec { diff --git a/manager/logbroker/broker.go b/manager/logbroker/broker.go index dfc898e070..c19438a27a 100644 --- a/manager/logbroker/broker.go +++ b/manager/logbroker/broker.go @@ -1,6 +1,7 @@ package logbroker import ( + "context" "errors" "fmt" "io" @@ -14,7 +15,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/watch" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/logbroker/broker_test.go b/manager/logbroker/broker_test.go index c133f0097c..ec85921016 100644 --- a/manager/logbroker/broker_test.go +++ b/manager/logbroker/broker_test.go @@ -1,6 +1,7 @@ package logbroker import ( + "context" "fmt" "io" "net" @@ -8,7 +9,6 @@ import ( "testing" "time" - "golang.org/x/net/context" "google.golang.org/grpc" "github.com/docker/swarmkit/api" diff --git a/manager/logbroker/subscription.go b/manager/logbroker/subscription.go index b9c9c7b403..883ddce655 100644 --- a/manager/logbroker/subscription.go +++ b/manager/logbroker/subscription.go @@ -1,6 +1,7 @@ package logbroker import ( + "context" "fmt" "strings" "sync" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/watch" - "golang.org/x/net/context" ) type subscription struct { diff --git a/manager/manager.go b/manager/manager.go index 106c8e2b58..ba7b005665 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -1,8 +1,10 @@ package manager import ( + "context" "crypto/tls" "fmt" + "math" "net" "os" "path/filepath" @@ -45,7 +47,6 @@ import ( grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) @@ -758,6 +759,7 @@ func (m *Manager) updateKEK(ctx context.Context, cluster *api.Cluster) error { func(addr string, timeout time.Duration) (net.Conn, error) { return xnet.DialTimeoutLocal(addr, timeout) }), + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)), ) if err != nil { logger.WithError(err).Error("failed to connect to local manager socket after locking the cluster") @@ -1002,9 +1004,7 @@ func (m *Manager) becomeLeader(ctx context.Context) { cluster = store.GetCluster(tx, clusterID) }) if cluster.DefaultAddressPool != nil { - for _, address := range cluster.DefaultAddressPool { - m.config.NetworkConfig.DefaultAddrPool = append(m.config.NetworkConfig.DefaultAddrPool, address) - } + m.config.NetworkConfig.DefaultAddrPool = append(m.config.NetworkConfig.DefaultAddrPool, cluster.DefaultAddressPool...) m.config.NetworkConfig.SubnetSize = cluster.SubnetSize } } @@ -1204,12 +1204,8 @@ func newIngressNetwork() *api.Network { }, DriverConfig: &api.Driver{}, IPAM: &api.IPAMOptions{ - Driver: &api.Driver{}, - Configs: []*api.IPAMConfig{ - { - Subnet: "10.255.0.0/16", - }, - }, + Driver: &api.Driver{}, + Configs: []*api.IPAMConfig{}, }, }, } diff --git a/manager/manager_test.go b/manager/manager_test.go index cf306cabe0..dd921f4d7e 100644 --- a/manager/manager_test.go +++ b/manager/manager_test.go @@ -2,6 +2,7 @@ package manager import ( "bytes" + "context" "crypto/tls" "encoding/pem" "errors" @@ -12,8 +13,6 @@ import ( "testing" "time" - "golang.org/x/net/context" - "google.golang.org/grpc" "google.golang.org/grpc/credentials" diff --git a/manager/metrics/collector.go b/manager/metrics/collector.go index 384743707d..5539a898ca 100644 --- a/manager/metrics/collector.go +++ b/manager/metrics/collector.go @@ -188,7 +188,6 @@ func (c *Collector) handleNodeEvent(event events.Event) { if newNode != nil { nodesMetric.WithValues(strings.ToLower(newNode.Status.State.String())).Inc(1) } - return } func (c *Collector) handleTaskEvent(event events.Event) { @@ -218,8 +217,6 @@ func (c *Collector) handleTaskEvent(event events.Event) { strings.ToLower(newTask.Status.State.String()), ).Inc(1) } - - return } func (c *Collector) handleServiceEvent(event events.Event) { diff --git a/manager/orchestrator/global/global.go b/manager/orchestrator/global/global.go index 2b20813ce2..715781e817 100644 --- a/manager/orchestrator/global/global.go +++ b/manager/orchestrator/global/global.go @@ -1,6 +1,8 @@ package global import ( + "context" + "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/constraint" @@ -9,7 +11,6 @@ import ( "github.com/docker/swarmkit/manager/orchestrator/taskinit" "github.com/docker/swarmkit/manager/orchestrator/update" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) type globalService struct { @@ -585,11 +586,3 @@ func (g *Orchestrator) SlotTuple(t *api.Task) orchestrator.SlotTuple { NodeID: t.NodeID, } } - -func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartCondition) bool { - if t == nil || t.DesiredState <= api.TaskStateRunning { - return false - } - return restartPolicy == api.RestartOnNone || - (restartPolicy == api.RestartOnFailure && t.Status.State == api.TaskStateCompleted) -} diff --git a/manager/orchestrator/global/global_test.go b/manager/orchestrator/global/global_test.go index 4a88f763c9..abb24fc307 100644 --- a/manager/orchestrator/global/global_test.go +++ b/manager/orchestrator/global/global_test.go @@ -1,6 +1,7 @@ package global import ( + "context" "testing" "time" @@ -13,7 +14,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) var ( @@ -115,9 +115,9 @@ func setup(t *testing.T, store *store.MemoryStore, watch chan events.Event) *Orc ctx := context.Background() // Start the global orchestrator. global := NewGlobalOrchestrator(store) - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, global.Run(ctx)) - }() + }) addService(t, store, service1) testutils.Expect(t, watch, api.EventCreateService{}) @@ -579,9 +579,9 @@ func TestInitializationRejectedTasks(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) observedTask1 := testutils.WatchTaskUpdate(t, watch) assert.Equal(t, observedTask1.ID, "task1") @@ -642,9 +642,9 @@ func TestInitializationFailedTasks(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) observedTask1 := testutils.WatchTaskUpdate(t, watch) assert.Equal(t, observedTask1.ID, "task1") @@ -734,9 +734,9 @@ func TestInitializationExtraTask(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) observedTask1 := testutils.WatchTaskUpdate(t, watch) assert.True(t, observedTask1.ID == "task1" || observedTask1.ID == "task2") @@ -814,9 +814,9 @@ func TestInitializationMultipleServices(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) // Nothing should happen because both tasks are up to date. select { @@ -955,9 +955,9 @@ func TestInitializationTaskWithoutService(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) observedTask1 := testutils.WatchTaskDelete(t, watch) assert.Equal(t, observedTask1.ID, "task2") @@ -1013,9 +1013,9 @@ func TestInitializationTaskOnDrainedNode(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) observedTask1 := testutils.WatchTaskUpdate(t, watch) assert.Equal(t, observedTask1.ID, "task1") @@ -1085,9 +1085,9 @@ func TestInitializationTaskOnNonexistentNode(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) observedTask1 := testutils.WatchTaskUpdate(t, watch) assert.Equal(t, observedTask1.ID, "task1") @@ -1254,9 +1254,9 @@ func TestInitializationRestartHistory(t *testing.T) { orchestrator := NewGlobalOrchestrator(s) defer orchestrator.Stop() - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() + }) // Fail the running task s.Update(func(tx store.Tx) error { diff --git a/manager/orchestrator/replicated/drain_test.go b/manager/orchestrator/replicated/drain_test.go index 58a76c4a7f..690cc09aa8 100644 --- a/manager/orchestrator/replicated/drain_test.go +++ b/manager/orchestrator/replicated/drain_test.go @@ -1,6 +1,7 @@ package replicated import ( + "context" "testing" "github.com/docker/swarmkit/api" @@ -8,7 +9,6 @@ import ( "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" ) func TestDrain(t *testing.T) { diff --git a/manager/orchestrator/replicated/replicated.go b/manager/orchestrator/replicated/replicated.go index 18b8e24aba..dc45528682 100644 --- a/manager/orchestrator/replicated/replicated.go +++ b/manager/orchestrator/replicated/replicated.go @@ -1,12 +1,13 @@ package replicated import ( + "context" + "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/orchestrator/restart" "github.com/docker/swarmkit/manager/orchestrator/update" "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) // An Orchestrator runs a reconciliation loop to create and destroy diff --git a/manager/orchestrator/replicated/replicated_test.go b/manager/orchestrator/replicated/replicated_test.go index 3b1e9133fe..6484b0ba50 100644 --- a/manager/orchestrator/replicated/replicated_test.go +++ b/manager/orchestrator/replicated/replicated_test.go @@ -1,6 +1,7 @@ package replicated import ( + "context" "testing" "time" @@ -12,7 +13,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestReplicatedOrchestrator(t *testing.T) { diff --git a/manager/orchestrator/replicated/restart_test.go b/manager/orchestrator/replicated/restart_test.go index b90268db94..2105b84a95 100644 --- a/manager/orchestrator/replicated/restart_test.go +++ b/manager/orchestrator/replicated/restart_test.go @@ -1,6 +1,7 @@ package replicated import ( + "context" "testing" "time" @@ -12,7 +13,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestOrchestratorRestartOnAny(t *testing.T) { diff --git a/manager/orchestrator/replicated/services.go b/manager/orchestrator/replicated/services.go index 04aea8795a..b5e6bb12e8 100644 --- a/manager/orchestrator/replicated/services.go +++ b/manager/orchestrator/replicated/services.go @@ -1,6 +1,7 @@ package replicated import ( + "context" "sort" "github.com/docker/go-events" @@ -8,7 +9,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/orchestrator" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) // This file provices service-level orchestration. It observes changes to diff --git a/manager/orchestrator/replicated/slot.go b/manager/orchestrator/replicated/slot.go index cee9fe10a0..1160d4c96c 100644 --- a/manager/orchestrator/replicated/slot.go +++ b/manager/orchestrator/replicated/slot.go @@ -1,10 +1,11 @@ package replicated import ( + "context" + "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/orchestrator" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) type slotsByRunningState []orchestrator.Slot diff --git a/manager/orchestrator/replicated/tasks.go b/manager/orchestrator/replicated/tasks.go index 66000e5d86..b6336aa88a 100644 --- a/manager/orchestrator/replicated/tasks.go +++ b/manager/orchestrator/replicated/tasks.go @@ -1,13 +1,14 @@ package replicated import ( + "context" + "github.com/docker/go-events" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/orchestrator" "github.com/docker/swarmkit/manager/orchestrator/taskinit" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) // This file provides task-level orchestration. It observes changes to task diff --git a/manager/orchestrator/replicated/update_test.go b/manager/orchestrator/replicated/update_test.go index 1599256fe8..53d6da728e 100644 --- a/manager/orchestrator/replicated/update_test.go +++ b/manager/orchestrator/replicated/update_test.go @@ -1,10 +1,12 @@ package replicated import ( - "sync/atomic" + "context" + "sync" "testing" "time" + "github.com/docker/go-events" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/orchestrator/testutils" "github.com/docker/swarmkit/manager/state" @@ -12,7 +14,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestUpdaterRollback(t *testing.T) { @@ -26,19 +27,25 @@ func TestUpdaterRollback(t *testing.T) { } func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_FailureAction, setMonitor bool, useSpecVersion bool) { - ctx := context.Background() + // this test should complete within 30 seconds. if not, bail out + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + s := store.NewMemoryStore(nil) assert.NotNil(t, s) defer s.Close() orchestrator := NewReplicatedOrchestrator(s) - defer orchestrator.Stop() + // These variables will be used to signal that The Fail Loop should start + // failing these tasks. Once they're closed, The Failing Can Begin. var ( - failImage1 uint32 - failImage2 uint32 + failMu sync.Mutex + failImage1 bool ) + // create a watch for task creates, which we will use to verify that the + // updater works correctly. watchCreate, cancelCreate := state.Watch(s.WatchQueue(), api.EventCreateTask{}) defer cancelCreate() @@ -48,44 +55,63 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa // Fail new tasks the updater tries to run watchUpdate, cancelUpdate := state.Watch(s.WatchQueue(), api.EventUpdateTask{}) defer cancelUpdate() - go func() { + + // We're gonna call this big chunk here "The Fail Loop". its job is to put + // tasks into a Failed state in certain conditions. + testutils.EnsureRuns(func() { failedLast := false + // typical go pattern: infinite for loop in a goroutine, exits on + // ctx.Done for { + var e events.Event select { - case e := <-watchUpdate: - task := e.(api.EventUpdateTask).Task - if task.DesiredState == task.Status.State { - continue - } - if task.DesiredState == api.TaskStateRunning && task.Status.State != api.TaskStateFailed && task.Status.State != api.TaskStateRunning { - err := s.Update(func(tx store.Tx) error { - task = store.GetTask(tx, task.ID) + case e = <-watchUpdate: + case <-ctx.Done(): + return + } + task := e.(api.EventUpdateTask).Task + if task.DesiredState == task.Status.State { + continue + } + // This used to have a 3rd clause, + // "&& task.Status.State != api.TaskStateRunning" + // however, this is unneeded. If DesiredState is Running, then + // actual state cannot be Running, because that would get caught + // in the condition about (DesiredState == State) + if task.DesiredState == api.TaskStateRunning && task.Status.State != api.TaskStateFailed { + err := s.Update(func(tx store.Tx) error { + task = store.GetTask(tx, task.ID) + // lock mutex governing access to failImage1. + failMu.Lock() + defer failMu.Unlock() + // we should start failing tasks with image1 only after1 + if task.Spec.GetContainer().Image == "image1" && failImage1 { + // only fail the task if we can read from failImage1 + // (which will only be true if it's closed) + task.Status.State = api.TaskStateFailed + failedLast = true + } else if task.Spec.GetContainer().Image == "image2" && !failedLast { // Never fail two image2 tasks in a row, so there's a mix of // failed and successful tasks for the rollback. - if task.Spec.GetContainer().Image == "image1" && atomic.LoadUint32(&failImage1) == 1 { - task.Status.State = api.TaskStateFailed - failedLast = true - } else if task.Spec.GetContainer().Image == "image2" && atomic.LoadUint32(&failImage2) == 1 && !failedLast { - task.Status.State = api.TaskStateFailed - failedLast = true - } else { - task.Status.State = task.DesiredState - failedLast = false - } - return store.UpdateTask(tx, task) - }) - assert.NoError(t, err) - } else if task.DesiredState > api.TaskStateRunning { - err := s.Update(func(tx store.Tx) error { - task = store.GetTask(tx, task.ID) + task.Status.State = api.TaskStateFailed + failedLast = true + } else { task.Status.State = task.DesiredState - return store.UpdateTask(tx, task) - }) - assert.NoError(t, err) - } + failedLast = false + } + return store.UpdateTask(tx, task) + }) + assert.NoError(t, err) + } else if task.DesiredState > api.TaskStateRunning { + err := s.Update(func(tx store.Tx) error { + task = store.GetTask(tx, task.ID) + task.Status.State = task.DesiredState + return store.UpdateTask(tx, task) + }) + assert.NoError(t, err) } } - }() + }) // Create a service with four replicas specified before the orchestrator // is started. This should result in two tasks when the orchestrator @@ -143,8 +169,18 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa assert.NoError(t, err) // Start the orchestrator. - go func() { - assert.NoError(t, orchestrator.Run(ctx)) + var orchestratorError error + orchestratorDone := testutils.EnsureRuns(func() { + orchestratorError = orchestrator.Run(ctx) + }) + + defer func() { + orchestrator.Stop() + select { + case <-ctx.Done(): + case <-orchestratorDone: + assert.NoError(t, orchestratorError) + } }() observedTask := testutils.WatchTaskCreate(t, watchCreate) @@ -163,8 +199,6 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa assert.Equal(t, observedTask.Status.State, api.TaskStateNew) assert.Equal(t, observedTask.Spec.GetContainer().Image, "image1") - atomic.StoreUint32(&failImage2, 1) - // Start a rolling update err = s.Update(func(tx store.Tx) error { s1 := store.GetService(tx, "id1") @@ -197,7 +231,13 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa // Should get to the ROLLBACK_STARTED state for { - e := <-watchServiceUpdate + var e events.Event + select { + case e = <-watchServiceUpdate: + case <-ctx.Done(): + t.Error("test timed out before watchServiceUpdate provided an event") + return + } if e.(api.EventUpdateService).Service.UpdateStatus == nil { continue } @@ -226,16 +266,26 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa // Should end up in ROLLBACK_COMPLETED state for { - e := <-watchServiceUpdate + var e events.Event + select { + case e = <-watchServiceUpdate: + t.Log("service was updated") + case <-ctx.Done(): + t.Error("test timed out before watchServiceUpdate provided an event") + return + } + if e.(api.EventUpdateService).Service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_COMPLETED { break } } - atomic.StoreUint32(&failImage1, 1) - // Repeat the rolling update but this time fail the tasks that the // rollback creates. + failMu.Lock() + failImage1 = true + failMu.Unlock() + err = s.Update(func(tx store.Tx) error { s1 := store.GetService(tx, "id1") require.NotNil(t, s1) @@ -267,7 +317,13 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa // Should get to the ROLLBACK_STARTED state for { - e := <-watchServiceUpdate + var e events.Event + select { + case e = <-watchServiceUpdate: + case <-ctx.Done(): + t.Error("test timed out before watchServiceUpdate provided an event") + return + } if e.(api.EventUpdateService).Service.UpdateStatus == nil { continue } @@ -292,7 +348,13 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa case api.UpdateConfig_PAUSE: // Should end up in ROLLBACK_PAUSED state for { - e := <-watchServiceUpdate + var e events.Event + select { + case e = <-watchServiceUpdate: + case <-ctx.Done(): + t.Error("test timed out before watchServiceUpdate provided an event") + return + } if e.(api.EventUpdateService).Service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_PAUSED { return } @@ -300,7 +362,13 @@ func testUpdaterRollback(t *testing.T, rollbackFailureAction api.UpdateConfig_Fa case api.UpdateConfig_CONTINUE: // Should end up in ROLLBACK_COMPLETE state for { - e := <-watchServiceUpdate + var e events.Event + select { + case e = <-watchServiceUpdate: + case <-ctx.Done(): + t.Error("test timed out before watchServiceUpdate provided an event") + return + } if e.(api.EventUpdateService).Service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_COMPLETED { return } diff --git a/manager/orchestrator/restart/restart.go b/manager/orchestrator/restart/restart.go index 6af44b734c..c79d02d98f 100644 --- a/manager/orchestrator/restart/restart.go +++ b/manager/orchestrator/restart/restart.go @@ -2,6 +2,7 @@ package restart import ( "container/list" + "context" "errors" "sync" "time" @@ -14,7 +15,6 @@ import ( "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" gogotypes "github.com/gogo/protobuf/types" - "golang.org/x/net/context" ) const defaultOldTaskTimeout = time.Minute @@ -508,20 +508,13 @@ func (r *Supervisor) Cancel(taskID string) { <-delay.doneCh } -// CancelAll aborts all pending restarts and waits for any instances of -// StartNow that have already triggered to complete. +// CancelAll aborts all pending restarts func (r *Supervisor) CancelAll() { - var cancelled []delayedStart - r.mu.Lock() for _, delay := range r.delays { delay.cancel() } r.mu.Unlock() - - for _, delay := range cancelled { - <-delay.doneCh - } } // ClearServiceHistory forgets restart history related to a given service ID. diff --git a/manager/orchestrator/service.go b/manager/orchestrator/service.go index 7356c38cd5..c5d298c516 100644 --- a/manager/orchestrator/service.go +++ b/manager/orchestrator/service.go @@ -1,10 +1,11 @@ package orchestrator import ( + "context" + "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) // IsReplicatedService checks if a service is a replicated service. @@ -46,22 +47,27 @@ func SetServiceTasksRemove(ctx context.Context, s *store.MemoryStore, service *a err = s.Batch(func(batch *store.Batch) error { for _, t := range tasks { err := batch.Update(func(tx store.Tx) error { + // the task may have changed for some reason in the meantime + // since we read it out, so we need to get from the store again + // within the boundaries of a transaction + latestTask := store.GetTask(tx, t.ID) + // time travel is not allowed. if the current desired state is // above the one we're trying to go to we can't go backwards. // we have nothing to do and we should skip to the next task - if t.DesiredState > api.TaskStateRemove { + if latestTask.DesiredState > api.TaskStateRemove { // log a warning, though. we shouln't be trying to rewrite // a state to an earlier state log.G(ctx).Warnf( "cannot update task %v in desired state %v to an earlier desired state %v", - t.ID, t.DesiredState, api.TaskStateRemove, + latestTask.ID, latestTask.DesiredState, api.TaskStateRemove, ) return nil } // update desired state to REMOVE - t.DesiredState = api.TaskStateRemove + latestTask.DesiredState = api.TaskStateRemove - if err := store.UpdateTask(tx, t); err != nil { + if err := store.UpdateTask(tx, latestTask); err != nil { log.G(ctx).WithError(err).Errorf("failed transaction: update task desired state to REMOVE") } return nil diff --git a/manager/orchestrator/task_test.go b/manager/orchestrator/task_test.go index 6ac210b1c2..ec7f379f7a 100644 --- a/manager/orchestrator/task_test.go +++ b/manager/orchestrator/task_test.go @@ -1,12 +1,13 @@ package orchestrator import ( - google_protobuf "github.com/gogo/protobuf/types" - "github.com/stretchr/testify/assert" "sort" "strconv" "testing" + google_protobuf "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/assert" + "github.com/docker/swarmkit/api" ) diff --git a/manager/orchestrator/taskinit/init.go b/manager/orchestrator/taskinit/init.go index b893428d51..be319cc25d 100644 --- a/manager/orchestrator/taskinit/init.go +++ b/manager/orchestrator/taskinit/init.go @@ -1,6 +1,7 @@ package taskinit import ( + "context" "sort" "time" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/manager/orchestrator/restart" "github.com/docker/swarmkit/manager/state/store" gogotypes "github.com/gogo/protobuf/types" - "golang.org/x/net/context" ) // InitHandler defines orchestrator's action to fix tasks at start. @@ -80,7 +80,7 @@ func CheckTasks(ctx context.Context, s *store.MemoryStore, readTx store.ReadTx, } if err == nil { restartTime := timestamp.Add(restartDelay) - calculatedRestartDelay := restartTime.Sub(time.Now()) + calculatedRestartDelay := time.Until(restartTime) if calculatedRestartDelay < restartDelay { restartDelay = calculatedRestartDelay } diff --git a/manager/orchestrator/taskreaper/task_reaper.go b/manager/orchestrator/taskreaper/task_reaper.go index cbeb321de9..5d2d2c7490 100644 --- a/manager/orchestrator/taskreaper/task_reaper.go +++ b/manager/orchestrator/taskreaper/task_reaper.go @@ -1,6 +1,7 @@ package taskreaper import ( + "context" "sort" "sync" "time" @@ -10,7 +11,6 @@ import ( "github.com/docker/swarmkit/manager/orchestrator" "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) const ( diff --git a/manager/orchestrator/taskreaper/task_reaper_test.go b/manager/orchestrator/taskreaper/task_reaper_test.go index e347ec709c..0c6b9a9849 100644 --- a/manager/orchestrator/taskreaper/task_reaper_test.go +++ b/manager/orchestrator/taskreaper/task_reaper_test.go @@ -173,7 +173,7 @@ func TestTaskReaperInit(t *testing.T) { reaper := New(s) // Now, start the reaper - go reaper.Run(ctx) + testutils.EnsureRuns(func() { reaper.Run(ctx) }) // And then stop the reaper. This will cause the reaper to run through its // whole init phase and then immediately enter the loop body, get the stop @@ -259,10 +259,10 @@ func TestTaskHistory(t *testing.T) { assert.NoError(t, err) // Start the orchestrator. - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run(ctx) + }) + testutils.EnsureRuns(func() { taskReaper.Run(ctx) }) observedTask1 := testutils.WatchTaskCreate(t, watch) assert.Equal(t, observedTask1.Status.State, api.TaskStateNew) @@ -394,10 +394,8 @@ func TestTaskStateRemoveOnScaledown(t *testing.T) { assert.NoError(t, err) // Start the orchestrator. - go func() { - assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run(ctx) + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) }) + testutils.EnsureRuns(func() { taskReaper.Run(ctx) }) observedTask1 := testutils.WatchTaskCreate(t, watch) assert.Equal(t, observedTask1.Status.State, api.TaskStateNew) @@ -526,10 +524,10 @@ func TestTaskStateRemoveOnServiceRemoval(t *testing.T) { assert.NoError(t, err) // Start the orchestrator. - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run(ctx) + }) + testutils.EnsureRuns(func() { taskReaper.Run(ctx) }) observedTask1 := testutils.WatchTaskCreate(t, watch) assert.Equal(t, observedTask1.Status.State, api.TaskStateNew) @@ -664,10 +662,10 @@ func TestServiceRemoveDeadTasks(t *testing.T) { assert.NoError(t, err) // Start the orchestrator and the reaper. - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run(ctx) + }) + testutils.EnsureRuns(func() { taskReaper.Run(ctx) }) observedTask1 := testutils.WatchTaskCreate(t, watch) assert.Equal(t, api.TaskStateNew, observedTask1.Status.State) @@ -843,7 +841,7 @@ func TestTaskReaperBatching(t *testing.T) { taskReaper := New(s) taskReaper.tickSignal = make(chan struct{}, 1) defer taskReaper.Stop() - go taskReaper.Run(ctx) + testutils.EnsureRuns(func() { taskReaper.Run(ctx) }) // None of the tasks we've created are eligible for deletion. We should // see no task delete events. Wait for a tick signal, or 500ms to pass, to @@ -1010,10 +1008,10 @@ func TestServiceRemoveUnassignedTasks(t *testing.T) { assert.NoError(t, err) // Start the orchestrator. - go func() { + testutils.EnsureRuns(func() { assert.NoError(t, orchestrator.Run(ctx)) - }() - go taskReaper.Run(ctx) + }) + testutils.EnsureRuns(func() { taskReaper.Run(ctx) }) observedTask1 := testutils.WatchTaskCreate(t, watch) assert.Equal(t, api.TaskStateNew, observedTask1.Status.State) diff --git a/manager/orchestrator/testutils/testutils.go b/manager/orchestrator/testutils/testutils.go index 5c6fe2de43..09602ec256 100644 --- a/manager/orchestrator/testutils/testutils.go +++ b/manager/orchestrator/testutils/testutils.go @@ -11,6 +11,22 @@ import ( "github.com/stretchr/testify/assert" ) +// EnsureRuns takes a closure and runs it in a goroutine, blocking until the +// goroutine has had an opportunity to run. It returns a channel which will be +// closed when the provided closure exits. +func EnsureRuns(closure func()) <-chan struct{} { + started := make(chan struct{}) + stopped := make(chan struct{}) + go func() { + close(started) + closure() + close(stopped) + }() + + <-started + return stopped +} + // WatchTaskCreate waits for a task to be created. func WatchTaskCreate(t *testing.T, watch chan events.Event) *api.Task { for { @@ -22,7 +38,7 @@ func WatchTaskCreate(t *testing.T, watch chan events.Event) *api.Task { if _, ok := event.(api.EventUpdateTask); ok { assert.FailNow(t, "got EventUpdateTask when expecting EventCreateTask", fmt.Sprint(event)) } - case <-time.After(time.Second): + case <-time.After(3 * time.Second): assert.FailNow(t, "no task creation") } } @@ -39,7 +55,7 @@ func WatchTaskUpdate(t *testing.T, watch chan events.Event) *api.Task { if _, ok := event.(api.EventCreateTask); ok { assert.FailNow(t, "got EventCreateTask when expecting EventUpdateTask", fmt.Sprint(event)) } - case <-time.After(time.Second): + case <-time.After(2 * time.Second): assert.FailNow(t, "no task update") } } diff --git a/manager/orchestrator/update/updater.go b/manager/orchestrator/update/updater.go index 5a7d61231c..4e6a2cc0bd 100644 --- a/manager/orchestrator/update/updater.go +++ b/manager/orchestrator/update/updater.go @@ -1,14 +1,13 @@ package update import ( + "context" "errors" "fmt" "reflect" "sync" "time" - "golang.org/x/net/context" - "github.com/docker/go-events" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api/defaults" @@ -502,7 +501,10 @@ func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, remove return fmt.Errorf("task %s not found while trying to shut it down", original.ID) } if t.DesiredState > api.TaskStateRunning { - return fmt.Errorf("task %s was already shut down when reached by updater", original.ID) + return fmt.Errorf( + "task %s was already shut down when reached by updater (state: %v)", + original.ID, t.DesiredState, + ) } t.DesiredState = api.TaskStateShutdown return store.UpdateTask(tx, t) diff --git a/manager/orchestrator/update/updater_test.go b/manager/orchestrator/update/updater_test.go index 1eca0f24eb..d54086d529 100644 --- a/manager/orchestrator/update/updater_test.go +++ b/manager/orchestrator/update/updater_test.go @@ -1,6 +1,7 @@ package update import ( + "context" "testing" "time" @@ -12,7 +13,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func getRunnableSlotSlice(t *testing.T, s *store.MemoryStore, service *api.Service) []orchestrator.Slot { diff --git a/manager/raftselector/raftselector.go b/manager/raftselector/raftselector.go index 89e7918a3d..47adcf0fd9 100644 --- a/manager/raftselector/raftselector.go +++ b/manager/raftselector/raftselector.go @@ -1,10 +1,9 @@ package raftselector import ( + "context" "errors" - "golang.org/x/net/context" - "google.golang.org/grpc" ) diff --git a/manager/resourceapi/allocator.go b/manager/resourceapi/allocator.go index ec19fba850..545e4ded99 100644 --- a/manager/resourceapi/allocator.go +++ b/manager/resourceapi/allocator.go @@ -1,6 +1,7 @@ package resourceapi import ( + "context" "errors" "time" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/identity" "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/protobuf/ptypes" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) diff --git a/manager/role_manager.go b/manager/role_manager.go index e5cf27b62f..a68bc3fc3b 100644 --- a/manager/role_manager.go +++ b/manager/role_manager.go @@ -1,6 +1,7 @@ package manager import ( + "context" "time" "github.com/docker/swarmkit/api" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/manager/state/raft/membership" "github.com/docker/swarmkit/manager/state/store" "github.com/pivotal-golang/clock" - "golang.org/x/net/context" ) const ( diff --git a/manager/scheduler/constraint_test.go b/manager/scheduler/constraint_test.go index 7bd378139e..04097c8d34 100644 --- a/manager/scheduler/constraint_test.go +++ b/manager/scheduler/constraint_test.go @@ -54,7 +54,7 @@ func setupEnv() { Addr: "186.17.9.41", }, }, - Tasks: make(map[string]*api.Task), + Tasks: make(map[string]*api.Task), ActiveTasksCountByService: make(map[string]int), } } diff --git a/manager/scheduler/nodeinfo.go b/manager/scheduler/nodeinfo.go index 78fa630ca3..8f1ad331b5 100644 --- a/manager/scheduler/nodeinfo.go +++ b/manager/scheduler/nodeinfo.go @@ -1,12 +1,12 @@ package scheduler import ( + "context" "time" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api/genericresource" "github.com/docker/swarmkit/log" - "golang.org/x/net/context" ) // hostPortSpec specifies a used host port. @@ -45,8 +45,8 @@ type NodeInfo struct { func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api.Resources) NodeInfo { nodeInfo := NodeInfo{ - Node: n, - Tasks: make(map[string]*api.Task), + Node: n, + Tasks: make(map[string]*api.Task), ActiveTasksCountByService: make(map[string]int), AvailableResources: availableResources.Copy(), usedHostPorts: make(map[hostPortSpec]struct{}), diff --git a/manager/scheduler/scheduler.go b/manager/scheduler/scheduler.go index 9e708ed1b6..939fc6f96d 100644 --- a/manager/scheduler/scheduler.go +++ b/manager/scheduler/scheduler.go @@ -1,6 +1,7 @@ package scheduler import ( + "context" "time" "github.com/docker/swarmkit/api" @@ -9,7 +10,6 @@ import ( "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/protobuf/ptypes" - "golang.org/x/net/context" ) const ( diff --git a/manager/scheduler/scheduler_test.go b/manager/scheduler/scheduler_test.go index d387dc4a01..da59acd72d 100644 --- a/manager/scheduler/scheduler_test.go +++ b/manager/scheduler/scheduler_test.go @@ -1,6 +1,7 @@ package scheduler import ( + "context" "fmt" "runtime" "strconv" @@ -16,7 +17,6 @@ import ( "github.com/docker/swarmkit/manager/state/store" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestScheduler(t *testing.T) { diff --git a/manager/state/proposer.go b/manager/state/proposer.go index 4967f98a1e..8d53f5772f 100644 --- a/manager/state/proposer.go +++ b/manager/state/proposer.go @@ -1,8 +1,9 @@ package state import ( + "context" + "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) // A Change includes a version number and a set of store actions from a diff --git a/manager/state/raft/membership/cluster_test.go b/manager/state/raft/membership/cluster_test.go index 9a2c253368..0781fc8677 100644 --- a/manager/state/raft/membership/cluster_test.go +++ b/manager/state/raft/membership/cluster_test.go @@ -1,6 +1,7 @@ package membership_test import ( + "context" "errors" "fmt" "io/ioutil" @@ -8,8 +9,6 @@ import ( "testing" "time" - "golang.org/x/net/context" - "google.golang.org/grpc/grpclog" "github.com/coreos/etcd/raft/raftpb" @@ -279,7 +278,8 @@ func TestCanRemoveMember(t *testing.T) { // Removing nodes at this point fails because we lost quorum for i := 1; i <= 3; i++ { - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() err := nodes[1].RemoveMember(ctx, uint64(i)) assert.Error(t, err) members := nodes[1].GetMemberlist() @@ -341,15 +341,17 @@ func TestCanRemoveMember(t *testing.T) { })) // Removing node 2 should fail (this would break the quorum) - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) err := nodes[leader].RemoveMember(ctx, nodes[2].Config.ID) + cancel() assert.EqualError(t, err, raft.ErrCannotRemoveMember.Error()) members := nodes[leader].GetMemberlist() assert.Equal(t, len(members), 3) // Removing node 3 works fine because it is already unreachable - ctx, _ = context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) err = nodes[leader].RemoveMember(ctx, nodes[3].Config.ID) + cancel() assert.NoError(t, err) members = nodes[leader].GetMemberlist() assert.Nil(t, members[nodes[3].Config.ID]) @@ -380,16 +382,18 @@ func TestCanRemoveMember(t *testing.T) { })) // Removing node 3 should succeed - ctx, _ = context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) err = nodes[leader].RemoveMember(ctx, nodes[3].Config.ID) + cancel() assert.NoError(t, err) members = nodes[leader].GetMemberlist() assert.Nil(t, members[nodes[3].Config.ID]) assert.Equal(t, len(members), 2) // Removing node 2 should succeed - ctx, _ = context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) err = nodes[leader].RemoveMember(ctx, nodes[2].Config.ID) + cancel() assert.NoError(t, err) members = nodes[leader].GetMemberlist() assert.Nil(t, members[nodes[2].Config.ID]) diff --git a/manager/state/raft/raft.go b/manager/state/raft/raft.go index 38c61c7bd2..a1193b71ce 100644 --- a/manager/state/raft/raft.go +++ b/manager/state/raft/raft.go @@ -1,6 +1,7 @@ package raft import ( + "context" "fmt" "io" "math" @@ -30,7 +31,6 @@ import ( "github.com/pivotal-golang/clock" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "golang.org/x/time/rate" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -1182,11 +1182,8 @@ func (n *Node) CanRemoveMember(id uint64) bool { } nquorum := (len(members)-1)/2 + 1 - if nreachable < nquorum { - return false - } - return true + return nreachable >= nquorum } func (n *Node) removeMember(ctx context.Context, id uint64) error { @@ -1591,10 +1588,7 @@ func (n *Node) ProposeValue(ctx context.Context, storeAction []api.StoreAction, defer cancel() _, err := n.processInternalRaftRequest(ctx, &api.InternalRaftRequest{Action: storeAction}, cb) - if err != nil { - return err - } - return nil + return err } // GetVersion returns the sequence information for the current raft round. diff --git a/manager/state/raft/raft_test.go b/manager/state/raft/raft_test.go index 952b3605bb..563ff0ebc9 100644 --- a/manager/state/raft/raft_test.go +++ b/manager/state/raft/raft_test.go @@ -1,6 +1,7 @@ package raft_test import ( + "context" "errors" "fmt" "io/ioutil" @@ -17,8 +18,6 @@ import ( "google.golang.org/grpc/grpclog" "google.golang.org/grpc/status" - "golang.org/x/net/context" - "github.com/coreos/etcd/raft/raftpb" "github.com/coreos/etcd/wal" "github.com/docker/swarmkit/api" @@ -110,8 +109,9 @@ func TestRaftJoinTwice(t *testing.T) { assert.NoError(t, err) raftClient := api.NewRaftMembershipClient(cc) defer cc.Close() - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) _, err = raftClient.Join(ctx, &api.JoinRequest{Addr: l.Addr().String()}) + cancel() assert.NoError(t, err) // Propose a value and wait for it to propagate @@ -367,8 +367,9 @@ func TestRaftFollowerLeave(t *testing.T) { assert.NoError(t, err) raftClient := api.NewRaftMembershipClient(cc) defer cc.Close() - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) resp, err := raftClient.Leave(ctx, &api.LeaveRequest{Node: &api.RaftMember{RaftID: nodes[5].Config.ID}}) + cancel() assert.NoError(t, err, "error sending message to leave the raft") assert.NotNil(t, resp, "leave response message is nil") @@ -412,8 +413,8 @@ func TestRaftLeaderLeave(t *testing.T) { raftClient := api.NewRaftMembershipClient(cc) defer cc.Close() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() resp, err := raftClient.Leave(ctx, &api.LeaveRequest{Node: &api.RaftMember{RaftID: nodes[1].Config.ID}}) + cancel() assert.NoError(t, err, "error sending message to leave the raft") assert.NotNil(t, resp, "leave response message is nil") diff --git a/manager/state/raft/storage.go b/manager/state/raft/storage.go index 547b775645..915cc3f241 100644 --- a/manager/state/raft/storage.go +++ b/manager/state/raft/storage.go @@ -1,6 +1,7 @@ package raft import ( + "context" "fmt" "github.com/coreos/etcd/raft" @@ -13,7 +14,6 @@ import ( "github.com/docker/swarmkit/manager/state/raft/storage" "github.com/docker/swarmkit/manager/state/store" "github.com/pkg/errors" - "golang.org/x/net/context" ) var ( diff --git a/manager/state/raft/storage/storage.go b/manager/state/raft/storage/storage.go index bbd262f37c..64d821894e 100644 --- a/manager/state/raft/storage/storage.go +++ b/manager/state/raft/storage/storage.go @@ -1,13 +1,12 @@ package storage import ( + "context" "fmt" "os" "path/filepath" "sync" - "golang.org/x/net/context" - "github.com/coreos/etcd/pkg/fileutil" "github.com/coreos/etcd/raft/raftpb" "github.com/coreos/etcd/snap" diff --git a/manager/state/raft/storage/storage_test.go b/manager/state/raft/storage/storage_test.go index f192eb48c2..2811f6e7d4 100644 --- a/manager/state/raft/storage/storage_test.go +++ b/manager/state/raft/storage/storage_test.go @@ -1,6 +1,7 @@ package storage import ( + "context" "io/ioutil" "os" "path/filepath" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/manager/encryption" "github.com/pkg/errors" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestBootstrapFromDisk(t *testing.T) { diff --git a/manager/state/raft/storage/walwrap.go b/manager/state/raft/storage/walwrap.go index 3c1208cdd0..d1155975bf 100644 --- a/manager/state/raft/storage/walwrap.go +++ b/manager/state/raft/storage/walwrap.go @@ -1,6 +1,7 @@ package storage import ( + "context" "io" "io/ioutil" "os" @@ -14,7 +15,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/encryption" "github.com/pkg/errors" - "golang.org/x/net/context" ) // This package wraps the github.com/coreos/etcd/wal package, and encrypts diff --git a/manager/state/raft/storage/walwrap_test.go b/manager/state/raft/storage/walwrap_test.go index 18fa5b77ea..ffe4d39107 100644 --- a/manager/state/raft/storage/walwrap_test.go +++ b/manager/state/raft/storage/walwrap_test.go @@ -2,6 +2,7 @@ package storage import ( "bytes" + "context" "fmt" "io/ioutil" "os" @@ -13,7 +14,6 @@ import ( "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/encryption" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) var _ WALFactory = walCryptor{} diff --git a/manager/state/raft/storage_test.go b/manager/state/raft/storage_test.go index 2fcbcd18c1..9b49c6bd59 100644 --- a/manager/state/raft/storage_test.go +++ b/manager/state/raft/storage_test.go @@ -1,6 +1,7 @@ package raft_test import ( + "context" "fmt" "io/ioutil" "os" @@ -18,7 +19,6 @@ import ( "github.com/pivotal-golang/clock/fakeclock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestRaftSnapshot(t *testing.T) { @@ -276,8 +276,9 @@ func TestRaftSnapshotForceNewCluster(t *testing.T) { assert.NoError(t, err) raftClient := api.NewRaftMembershipClient(cc) defer cc.Close() - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) resp, err := raftClient.Leave(ctx, &api.LeaveRequest{Node: &api.RaftMember{RaftID: nodes[2].Config.ID}}) + cancel() assert.NoError(t, err, "error sending message to leave the raft") assert.NotNil(t, resp, "leave response message is nil") @@ -502,12 +503,13 @@ func proposeLargeValue(t *testing.T, raftNode *raftutils.TestNode, time time.Dur }, } - ctx, _ := context.WithTimeout(context.Background(), time) + ctx, cancel := context.WithTimeout(context.Background(), time) err := raftNode.ProposeValue(ctx, storeActions, func() { err := raftNode.MemoryStore().ApplyStoreActions(storeActions) assert.NoError(t, err, "error applying actions") }) + cancel() if err != nil { return nil, err } diff --git a/manager/state/raft/testutils/testutils.go b/manager/state/raft/testutils/testutils.go index b6874119a0..de247e4b6a 100644 --- a/manager/state/raft/testutils/testutils.go +++ b/manager/state/raft/testutils/testutils.go @@ -1,6 +1,7 @@ package testutils import ( + "context" "io/ioutil" "net" "os" @@ -9,8 +10,6 @@ import ( "testing" "time" - "golang.org/x/net/context" - "google.golang.org/grpc" etcdraft "github.com/coreos/etcd/raft" @@ -61,13 +60,15 @@ func AdvanceTicks(clockSource *fakeclock.FakeClock, ticks int) { func WaitForCluster(t *testing.T, clockSource *fakeclock.FakeClock, nodes map[uint64]*TestNode) { err := testutils.PollFunc(clockSource, func() error { var prev *etcdraft.Status + var leadNode *TestNode nodeLoop: for _, n := range nodes { if prev == nil { prev = new(etcdraft.Status) *prev = n.Status() for _, n2 := range nodes { - if n2.Config.ID == prev.Lead && n2.ReadyForProposals() { + if n2.Config.ID == prev.Lead { + leadNode = n2 continue nodeLoop } } @@ -85,7 +86,14 @@ func WaitForCluster(t *testing.T, clockSource *fakeclock.FakeClock, nodes map[ui } return errors.New("did not find leader in member list") } - return nil + // Don't raise error just because test machine is running slowly + for i := 0; i < 5; i++ { + if leadNode.ReadyForProposals() { + return nil + } + time.Sleep(2 * time.Second) + } + return errors.New("leader is not ready") }) require.NoError(t, err) } @@ -520,12 +528,13 @@ func ProposeValue(t *testing.T, raftNode *TestNode, time time.Duration, nodeID . }, } - ctx, _ := context.WithTimeout(context.Background(), time) + ctx, cancel := context.WithTimeout(context.Background(), time) err := raftNode.ProposeValue(ctx, storeActions, func() { err := raftNode.MemoryStore().ApplyStoreActions(storeActions) assert.NoError(t, err, "error applying actions") }) + cancel() if err != nil { return nil, err } diff --git a/manager/state/raft/transport/mock_raft_test.go b/manager/state/raft/transport/mock_raft_test.go index bf4cc10ef2..9b6b2c6e8c 100644 --- a/manager/state/raft/transport/mock_raft_test.go +++ b/manager/state/raft/transport/mock_raft_test.go @@ -1,6 +1,7 @@ package transport import ( + "context" "io" "net" "time" @@ -11,7 +12,6 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/health" "github.com/docker/swarmkit/manager/state/raft/membership" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/manager/state/raft/transport/peer.go b/manager/state/raft/transport/peer.go index 644e295214..6fb39523ca 100644 --- a/manager/state/raft/transport/peer.go +++ b/manager/state/raft/transport/peer.go @@ -1,12 +1,11 @@ package transport import ( + "context" "fmt" "sync" "time" - "golang.org/x/net/context" - "google.golang.org/grpc" "google.golang.org/grpc/codes" diff --git a/manager/state/raft/transport/peer_test.go b/manager/state/raft/transport/peer_test.go index 1b04e1b72a..21089eba98 100644 --- a/manager/state/raft/transport/peer_test.go +++ b/manager/state/raft/transport/peer_test.go @@ -1,11 +1,10 @@ package transport import ( + "context" "math" "testing" - "golang.org/x/net/context" - "github.com/coreos/etcd/raft/raftpb" "github.com/stretchr/testify/assert" ) diff --git a/manager/state/raft/transport/transport.go b/manager/state/raft/transport/transport.go index b741c4aa67..6bd0bc32ef 100644 --- a/manager/state/raft/transport/transport.go +++ b/manager/state/raft/transport/transport.go @@ -3,12 +3,12 @@ package transport import ( + "context" + "math" "net" "sync" "time" - "golang.org/x/net/context" - grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -355,6 +355,15 @@ func (t *Transport) dial(addr string) (*grpc.ClientConn, error) { return net.DialTimeout("tcp", addr, timeout) })) + // TODO(dperny): this changes the max received message size for outgoing + // client connections. this means if the server sends a message larger than + // this, we will still accept and unmarshal it. i'm unsure what the + // potential consequences are of setting this to be effectively unbounded, + // so after docker/swarmkit#2774 is fixed, we should remove this option + grpcOptions = append(grpcOptions, grpc.WithDefaultCallOptions( + grpc.MaxCallRecvMsgSize(math.MaxInt32), + )) + cc, err := grpc.Dial(addr, grpcOptions...) if err != nil { return nil, err diff --git a/manager/state/raft/transport/transport_test.go b/manager/state/raft/transport/transport_test.go index c203e7447b..b631958ea5 100644 --- a/manager/state/raft/transport/transport_test.go +++ b/manager/state/raft/transport/transport_test.go @@ -1,11 +1,10 @@ package transport import ( + "context" "testing" "time" - "golang.org/x/net/context" - "github.com/coreos/etcd/raft" "github.com/coreos/etcd/raft/raftpb" "github.com/stretchr/testify/assert" diff --git a/manager/state/raft/util.go b/manager/state/raft/util.go index da44dca6a5..1a49f76cb4 100644 --- a/manager/state/raft/util.go +++ b/manager/state/raft/util.go @@ -1,10 +1,10 @@ package raft import ( + "context" + "net" "time" - "golang.org/x/net/context" - "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" @@ -15,11 +15,15 @@ import ( // dial returns a grpc client connection func dial(addr string, protocol string, creds credentials.TransportCredentials, timeout time.Duration) (*grpc.ClientConn, error) { + // gRPC dialer connects to proxy first. Provide a custom dialer here avoid that. grpcOptions := []grpc.DialOption{ grpc.WithBackoffMaxDelay(2 * time.Second), grpc.WithTransportCredentials(creds), grpc.WithUnaryInterceptor(grpc_prometheus.UnaryClientInterceptor), grpc.WithStreamInterceptor(grpc_prometheus.StreamClientInterceptor), + grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { + return net.DialTimeout("tcp", addr, timeout) + }), } if timeout != 0 { diff --git a/manager/state/store/memory.go b/manager/state/store/memory.go index 423f04cad3..d0319c7f65 100644 --- a/manager/state/store/memory.go +++ b/manager/state/store/memory.go @@ -1,6 +1,7 @@ package store import ( + "context" "errors" "fmt" "runtime" @@ -18,7 +19,6 @@ import ( "github.com/docker/swarmkit/watch" gogotypes "github.com/gogo/protobuf/types" memdb "github.com/hashicorp/go-memdb" - "golang.org/x/net/context" ) const ( @@ -689,7 +689,7 @@ func (tx readTx) findIterators(table string, by By, checkType func(By) error) ([ } return []memdb.ResultIterator{it}, nil case bySlot: - it, err := tx.memDBTx.Get(table, indexSlot, v.serviceID+"\x00"+strconv.FormatUint(uint64(v.slot), 10)) + it, err := tx.memDBTx.Get(table, indexSlot, v.serviceID+"\x00"+strconv.FormatUint(v.slot, 10)) if err != nil { return nil, err } diff --git a/manager/state/testutils/mock_proposer.go b/manager/state/testutils/mock_proposer.go index caf8ebaf55..38b0662b3e 100644 --- a/manager/state/testutils/mock_proposer.go +++ b/manager/state/testutils/mock_proposer.go @@ -1,11 +1,11 @@ package testutils import ( + "context" "errors" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/state" - "golang.org/x/net/context" ) // MockProposer is a simple proposer implementation for use in tests. diff --git a/manager/watchapi/server.go b/manager/watchapi/server.go index 6d49dca715..eb086b8ac0 100644 --- a/manager/watchapi/server.go +++ b/manager/watchapi/server.go @@ -1,11 +1,11 @@ package watchapi import ( + "context" "errors" "sync" "github.com/docker/swarmkit/manager/state/store" - "golang.org/x/net/context" ) var ( diff --git a/manager/watchapi/server_test.go b/manager/watchapi/server_test.go index 0df252993f..ceb2ce1576 100644 --- a/manager/watchapi/server_test.go +++ b/manager/watchapi/server_test.go @@ -1,6 +1,7 @@ package watchapi import ( + "context" "io/ioutil" "net" "os" @@ -14,7 +15,6 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" ) diff --git a/manager/watchapi/watch_test.go b/manager/watchapi/watch_test.go index 3d908c1766..41aa7a0e97 100644 --- a/manager/watchapi/watch_test.go +++ b/manager/watchapi/watch_test.go @@ -1,13 +1,13 @@ package watchapi import ( + "context" "testing" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/manager/state/store" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func TestWatch(t *testing.T) { diff --git a/node/node.go b/node/node.go index 6cbf265c5d..1d3e6c4f50 100644 --- a/node/node.go +++ b/node/node.go @@ -2,9 +2,11 @@ package node import ( "bytes" + "context" "crypto/tls" "encoding/json" "io/ioutil" + "math" "net" "os" "path/filepath" @@ -35,7 +37,6 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" bolt "go.etcd.io/bbolt" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/status" @@ -896,6 +897,7 @@ func (n *Node) initManagerConnection(ctx context.Context, ready chan<- struct{}) opts := []grpc.DialOption{ grpc.WithUnaryInterceptor(grpc_prometheus.UnaryClientInterceptor), grpc.WithStreamInterceptor(grpc_prometheus.StreamClientInterceptor), + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)), } insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) opts = append(opts, grpc.WithTransportCredentials(insecureCreds)) @@ -1204,19 +1206,16 @@ func (s *persistentRemotes) Observe(peer api.Peer, weight int) { s.c.Broadcast() if err := s.save(); err != nil { logrus.Errorf("error writing cluster state file: %v", err) - return } - return } + func (s *persistentRemotes) Remove(peers ...api.Peer) { s.Lock() defer s.Unlock() s.Remotes.Remove(peers...) if err := s.save(); err != nil { logrus.Errorf("error writing cluster state file: %v", err) - return } - return } func (s *persistentRemotes) save() error { diff --git a/node/node_test.go b/node/node_test.go index ebd44b03e8..6f6bd25c67 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -2,6 +2,7 @@ package node import ( "bytes" + "context" "crypto/x509" "encoding/pem" "fmt" @@ -25,7 +26,6 @@ import ( "github.com/docker/swarmkit/testutils" "github.com/pkg/errors" "github.com/stretchr/testify/require" - "golang.org/x/net/context" ) func getLoggingContext(t *testing.T) context.Context { diff --git a/protobuf/plugin/raftproxy/test/raftproxy_test.go b/protobuf/plugin/raftproxy/test/raftproxy_test.go index bdefb65311..e0dfc9c22a 100644 --- a/protobuf/plugin/raftproxy/test/raftproxy_test.go +++ b/protobuf/plugin/raftproxy/test/raftproxy_test.go @@ -1,6 +1,7 @@ package test import ( + "context" "net" "testing" "time" @@ -9,8 +10,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" - "google.golang.org/grpc" "google.golang.org/grpc/codes" ) diff --git a/protobuf/plugin/raftproxy/test/service.pb.go b/protobuf/plugin/raftproxy/test/service.pb.go index a2e36b343c..61ca52768e 100644 --- a/protobuf/plugin/raftproxy/test/service.pb.go +++ b/protobuf/plugin/raftproxy/test/service.pb.go @@ -1070,7 +1070,7 @@ func (p *raftProxyRouteGuideServer) ListFeatures(r *Rectangle, stream RouteGuide } streamWrapper := RouteGuide_ListFeaturesServerWrapper{ RouteGuide_ListFeaturesServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.ListFeatures(r, streamWrapper) } @@ -1121,7 +1121,7 @@ func (p *raftProxyRouteGuideServer) RecordRoute(stream RouteGuide_RecordRouteSer } streamWrapper := RouteGuide_RecordRouteServerWrapper{ RouteGuide_RecordRouteServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.RecordRoute(streamWrapper) } @@ -1178,7 +1178,7 @@ func (p *raftProxyRouteGuideServer) RouteChat(stream RouteGuide_RouteChatServer) } streamWrapper := RouteGuide_RouteChatServerWrapper{ RouteGuide_RouteChatServer: stream, - ctx: ctx, + ctx: ctx, } return p.local.RouteChat(streamWrapper) } diff --git a/template/getter_test.go b/template/getter_test.go index a24fbfaa84..c2c1be0b22 100644 --- a/template/getter_test.go +++ b/template/getter_test.go @@ -160,7 +160,7 @@ func TestTemplatedSecret(t *testing.T) { Data: []byte("SECRET_VAL={{secret \"unknowntarget\"}}\n"), Templating: &api.Driver{Name: "golang"}, }, - expectedErr: `failed to expand templated secret templatedsecret: template: expansion:1:13: executing "expansion" at : error calling secret: secret target unknowntarget not found`, + expectedErr: `failed to expand templated secret templatedsecret: template: expansion:1:13: executing "expansion" at : error calling secret: secret target unknowntarget not found`, task: modifyTask(func(t *api.Task) { t.Spec = api.TaskSpec{ Runtime: &api.TaskSpec_Container{ @@ -185,7 +185,7 @@ func TestTemplatedSecret(t *testing.T) { Data: []byte("CONFIG_VAL={{config \"unknowntarget\"}}\n"), Templating: &api.Driver{Name: "golang"}, }, - expectedErr: `failed to expand templated secret templatedsecret: template: expansion:1:13: executing "expansion" at : error calling config: config target unknowntarget not found`, + expectedErr: `failed to expand templated secret templatedsecret: template: expansion:1:13: executing "expansion" at : error calling config: config target unknowntarget not found`, task: modifyTask(func(t *api.Task) { t.Spec = api.TaskSpec{ Runtime: &api.TaskSpec_Container{ @@ -440,7 +440,7 @@ func TestTemplatedConfig(t *testing.T) { Data: []byte("SECRET_VAL={{secret \"unknowntarget\"}}\n"), Templating: &api.Driver{Name: "golang"}, }, - expectedErr: `failed to expand templated config templatedconfig: template: expansion:1:13: executing "expansion" at : error calling secret: secret target unknowntarget not found`, + expectedErr: `failed to expand templated config templatedconfig: template: expansion:1:13: executing "expansion" at : error calling secret: secret target unknowntarget not found`, task: modifyTask(func(t *api.Task) { t.Spec = api.TaskSpec{ Runtime: &api.TaskSpec_Container{ @@ -465,7 +465,7 @@ func TestTemplatedConfig(t *testing.T) { Data: []byte("CONFIG_VAL={{config \"unknowntarget\"}}\n"), Templating: &api.Driver{Name: "golang"}, }, - expectedErr: `failed to expand templated config templatedconfig: template: expansion:1:13: executing "expansion" at : error calling config: config target unknowntarget not found`, + expectedErr: `failed to expand templated config templatedconfig: template: expansion:1:13: executing "expansion" at : error calling config: config target unknowntarget not found`, task: modifyTask(func(t *api.Task) { t.Spec = api.TaskSpec{ Runtime: &api.TaskSpec_Container{ diff --git a/watch/sinks_test.go b/watch/sinks_test.go index 867b2f7c42..69593885eb 100644 --- a/watch/sinks_test.go +++ b/watch/sinks_test.go @@ -39,8 +39,7 @@ func TestTimeoutDropErrSinkGen(t *testing.T) { <-ch2.Done() // Make sure that closing a sink closes the channel - var errClose error - errClose = sink.Close() + errClose := sink.Close() <-ch.Done() require.NoError(errClose)