From 6cd6d8646a90fa2013416bc8f11bd78d72c4180d Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Wed, 14 Jun 2017 14:32:15 -0700 Subject: [PATCH] Replace service ps cli tests with service inspect API test. Signed-off-by: Daniel Nephin --- .../docker_api_swarm_service_test.go | 4 +- integration-cli/docker_cli_swarm_test.go | 86 ----------- integration/service/inspect_test.go | 145 ++++++++++++++++++ integration/service/main_test.go | 37 +++++ 4 files changed, 183 insertions(+), 89 deletions(-) create mode 100644 integration/service/inspect_test.go create mode 100644 integration/service/main_test.go diff --git a/integration-cli/docker_api_swarm_service_test.go b/integration-cli/docker_api_swarm_service_test.go index 68b78b6453..a9563f2de1 100644 --- a/integration-cli/docker_api_swarm_service_test.go +++ b/integration-cli/docker_api_swarm_service_test.go @@ -69,9 +69,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *check.C) { c.Assert(err, checker.IsNil) defer cli.Close() - options := types.ServiceInspectOptions{ - InsertDefaults: true, - } + options := types.ServiceInspectOptions{InsertDefaults: true} // insertDefaults inserts UpdateConfig when service is fetched by ID resp, _, err := cli.ServiceInspectWithRaw(context.Background(), id, options) diff --git a/integration-cli/docker_cli_swarm_test.go b/integration-cli/docker_cli_swarm_test.go index e7dd5bfd52..5ecb010b29 100644 --- a/integration-cli/docker_cli_swarm_test.go +++ b/integration-cli/docker_cli_swarm_test.go @@ -1534,22 +1534,6 @@ func (s *DockerSwarmSuite) TestSwarmManagerAddress(c *check.C) { c.Assert(out, checker.Contains, expectedOutput) } -func (s *DockerSwarmSuite) TestSwarmServiceInspectPretty(c *check.C) { - d := s.AddDaemon(c, true, true) - - name := "top" - out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", name, "--limit-cpu=0.5", "busybox", "top") - c.Assert(err, checker.IsNil, check.Commentf(out)) - - expectedOutput := ` -Resources: - Limits: - CPU: 0.5` - out, err = d.Cmd("service", "inspect", "--pretty", name) - c.Assert(err, checker.IsNil, check.Commentf(out)) - c.Assert(out, checker.Contains, expectedOutput, check.Commentf(out)) -} - func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *check.C) { d := s.AddDaemon(c, true, true) @@ -1691,76 +1675,6 @@ func (s *DockerSwarmSuite) TestSwarmNetworkCreateDup(c *check.C) { } } -func (s *DockerSwarmSuite) TestSwarmServicePsMultipleServiceIDs(c *check.C) { - d := s.AddDaemon(c, true, true) - - name1 := "top1" - out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--name", name1, "--replicas=3", "busybox", "top") - c.Assert(err, checker.IsNil) - c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") - id1 := strings.TrimSpace(out) - - name2 := "top2" - out, err = d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--name", name2, "--replicas=3", "busybox", "top") - c.Assert(err, checker.IsNil) - c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") - id2 := strings.TrimSpace(out) - - // make sure task has been deployed. - waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 6) - - out, err = d.Cmd("service", "ps", name1) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name1+".1") - c.Assert(out, checker.Contains, name1+".2") - c.Assert(out, checker.Contains, name1+".3") - c.Assert(out, checker.Not(checker.Contains), name2+".1") - c.Assert(out, checker.Not(checker.Contains), name2+".2") - c.Assert(out, checker.Not(checker.Contains), name2+".3") - - out, err = d.Cmd("service", "ps", name1, name2) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name1+".1") - c.Assert(out, checker.Contains, name1+".2") - c.Assert(out, checker.Contains, name1+".3") - c.Assert(out, checker.Contains, name2+".1") - c.Assert(out, checker.Contains, name2+".2") - c.Assert(out, checker.Contains, name2+".3") - - // Name Prefix - out, err = d.Cmd("service", "ps", "to") - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name1+".1") - c.Assert(out, checker.Contains, name1+".2") - c.Assert(out, checker.Contains, name1+".3") - c.Assert(out, checker.Contains, name2+".1") - c.Assert(out, checker.Contains, name2+".2") - c.Assert(out, checker.Contains, name2+".3") - - // Name Prefix (no hit) - out, err = d.Cmd("service", "ps", "noname") - c.Assert(err, checker.NotNil) - c.Assert(out, checker.Contains, "no such services: noname") - - out, err = d.Cmd("service", "ps", id1) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name1+".1") - c.Assert(out, checker.Contains, name1+".2") - c.Assert(out, checker.Contains, name1+".3") - c.Assert(out, checker.Not(checker.Contains), name2+".1") - c.Assert(out, checker.Not(checker.Contains), name2+".2") - c.Assert(out, checker.Not(checker.Contains), name2+".3") - - out, err = d.Cmd("service", "ps", id1, id2) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name1+".1") - c.Assert(out, checker.Contains, name1+".2") - c.Assert(out, checker.Contains, name1+".3") - c.Assert(out, checker.Contains, name2+".1") - c.Assert(out, checker.Contains, name2+".2") - c.Assert(out, checker.Contains, name2+".3") -} - func (s *DockerSwarmSuite) TestSwarmPublishDuplicatePorts(c *check.C) { d := s.AddDaemon(c, true, true) diff --git a/integration/service/inspect_test.go b/integration/service/inspect_test.go new file mode 100644 index 0000000000..601e16cd8f --- /dev/null +++ b/integration/service/inspect_test.go @@ -0,0 +1,145 @@ +package service + +import ( + "fmt" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" + "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/integration-cli/request" + "github.com/gotestyourself/gotestyourself/poll" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/net/context" +) + +func TestInspect(t *testing.T) { + d := newSwarm(t) + defer d.Stop(t) + client, err := request.NewClientForHost(d.Sock()) + require.NoError(t, err) + + var before = time.Now() + var instances uint64 = 2 + serviceSpec := fullSwarmServiceSpec("test-service-inspect", instances) + + ctx := context.Background() + resp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{ + QueryRegistry: false, + }) + require.NoError(t, err) + + id := resp.ID + poll.WaitOn(t, serviceContainerCount(client, id, instances)) + + service, _, err := client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{}) + require.NoError(t, err) + assert.Equal(t, serviceSpec, service.Spec) + assert.Equal(t, uint64(11), service.Meta.Version.Index) + assert.Equal(t, id, service.ID) + assert.WithinDuration(t, before, service.CreatedAt, 30*time.Second) + assert.WithinDuration(t, before, service.UpdatedAt, 30*time.Second) +} + +func fullSwarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec { + restartDelay := 100 * time.Millisecond + maxAttempts := uint64(4) + + return swarm.ServiceSpec{ + Annotations: swarm.Annotations{ + Name: name, + Labels: map[string]string{ + "service-label": "service-label-value", + }, + }, + TaskTemplate: swarm.TaskSpec{ + ContainerSpec: &swarm.ContainerSpec{ + Image: "busybox:latest", + Labels: map[string]string{"container-label": "container-value"}, + Command: []string{"/bin/top"}, + Args: []string{"-u", "root"}, + Hostname: "hostname", + Env: []string{"envvar=envvalue"}, + Dir: "/work", + User: "root", + StopSignal: "SIGINT", + StopGracePeriod: &restartDelay, + Hosts: []string{"8.8.8.8 google"}, + DNSConfig: &swarm.DNSConfig{ + Nameservers: []string{"8.8.8.8"}, + Search: []string{"somedomain"}, + }, + }, + RestartPolicy: &swarm.RestartPolicy{ + Delay: &restartDelay, + Condition: swarm.RestartPolicyConditionOnFailure, + MaxAttempts: &maxAttempts, + }, + Runtime: swarm.RuntimeContainer, + }, + Mode: swarm.ServiceMode{ + Replicated: &swarm.ReplicatedService{ + Replicas: &replicas, + }, + }, + UpdateConfig: &swarm.UpdateConfig{ + Parallelism: 2, + Delay: 200 * time.Second, + FailureAction: swarm.UpdateFailureActionContinue, + Monitor: 2 * time.Second, + MaxFailureRatio: 0.2, + Order: swarm.UpdateOrderStopFirst, + }, + RollbackConfig: &swarm.UpdateConfig{ + Parallelism: 3, + Delay: 300 * time.Second, + FailureAction: swarm.UpdateFailureActionPause, + Monitor: 3 * time.Second, + MaxFailureRatio: 0.3, + Order: swarm.UpdateOrderStartFirst, + }, + } +} + +const defaultSwarmPort = 2477 + +func newSwarm(t *testing.T) *daemon.Swarm { + d := &daemon.Swarm{ + Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{ + Experimental: testEnv.ExperimentalDaemon(), + }), + // TODO: better method of finding an unused port + Port: defaultSwarmPort, + } + // TODO: move to a NewSwarm constructor + d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port) + + // avoid networking conflicts + args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"} + d.StartWithBusybox(t, args...) + + require.NoError(t, d.Init(swarm.InitRequest{})) + return d +} + +func serviceContainerCount(client client.ServiceAPIClient, id string, count uint64) func(log poll.LogT) poll.Result { + return func(log poll.LogT) poll.Result { + filter := filters.NewArgs() + filter.Add("service", id) + tasks, err := client.TaskList(context.Background(), types.TaskListOptions{ + Filters: filter, + }) + switch { + case err != nil: + return poll.Error(err) + case len(tasks) == int(count): + return poll.Success() + default: + return poll.Continue("task count at %d waiting for %d", len(tasks), count) + } + } +} diff --git a/integration/service/main_test.go b/integration/service/main_test.go new file mode 100644 index 0000000000..fac7427819 --- /dev/null +++ b/integration/service/main_test.go @@ -0,0 +1,37 @@ +package service + +import ( + "fmt" + "os" + "testing" + + "github.com/docker/docker/integration-cli/environment" +) + +var testEnv *environment.Execution + +const dockerdBinary = "dockerd" + +func TestMain(m *testing.M) { + var err error + testEnv, err = environment.New() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // TODO: replace this with `testEnv.Print()` to print the full env + if testEnv.LocalDaemon() { + fmt.Println("INFO: Testing against a local daemon") + } else { + fmt.Println("INFO: Testing against a remote daemon") + } + + res := m.Run() + os.Exit(res) +} + +func setupTest(t *testing.T) func() { + environment.ProtectImages(t, testEnv) + return func() { testEnv.Clean(t, testEnv.DockerBinary()) } +}