2019-05-16 18:43:48 -04:00
|
|
|
package service // import "github.com/docker/docker/integration/service"
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/api/types/filters"
|
|
|
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
|
|
|
"github.com/docker/docker/api/types/versions"
|
|
|
|
"github.com/docker/docker/integration/internal/swarm"
|
2020-02-07 08:39:24 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
is "gotest.tools/v3/assert/cmp"
|
|
|
|
"gotest.tools/v3/poll"
|
|
|
|
"gotest.tools/v3/skip"
|
2019-05-16 18:43:48 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// TestServiceListWithStatuses tests that performing a ServiceList operation
|
|
|
|
// correctly uses the Status parameter, and that the resulting response
|
|
|
|
// contains correct service statuses.
|
|
|
|
//
|
|
|
|
// NOTE(dperny): because it's a pain to elicit the behavior of an unconverged
|
|
|
|
// service reliably, I'm not testing that an unconverged service returns X
|
|
|
|
// running and Y desired tasks. Instead, I'm just going to trust that I can
|
|
|
|
// successfully assign a value to another value without screwing it up. The
|
|
|
|
// logic for computing service statuses is in swarmkit anyway, not in the
|
|
|
|
// engine, and is well-tested there, so this test just needs to make sure that
|
|
|
|
// statuses get correctly associated with the right services.
|
|
|
|
func TestServiceListWithStatuses(t *testing.T) {
|
|
|
|
skip.If(t, testEnv.IsRemoteDaemon)
|
|
|
|
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
|
|
|
|
// statuses were added in API version 1.41
|
|
|
|
skip.If(t, versions.LessThan(testEnv.DaemonInfo.ServerVersion, "1.41"))
|
|
|
|
defer setupTest(t)()
|
|
|
|
d := swarm.NewSwarm(t, testEnv)
|
|
|
|
defer d.Stop(t)
|
|
|
|
client := d.NewClientT(t)
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
serviceCount := 3
|
|
|
|
// create some services.
|
|
|
|
for i := 0; i < serviceCount; i++ {
|
|
|
|
spec := fullSwarmServiceSpec(fmt.Sprintf("test-list-%d", i), uint64(i+1))
|
|
|
|
// for whatever reason, the args "-u root", when included, cause these
|
|
|
|
// tasks to fail and exit. instead, we'll just pass no args, which
|
|
|
|
// works.
|
|
|
|
spec.TaskTemplate.ContainerSpec.Args = []string{}
|
|
|
|
resp, err := client.ServiceCreate(ctx, spec, types.ServiceCreateOptions{
|
|
|
|
QueryRegistry: false,
|
|
|
|
})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
id := resp.ID
|
|
|
|
// we need to wait specifically for the tasks to be running, which the
|
|
|
|
// serviceContainerCount function does not do. instead, we'll use a
|
|
|
|
// bespoke closure right here.
|
|
|
|
poll.WaitOn(t, func(log poll.LogT) poll.Result {
|
|
|
|
filter := filters.NewArgs()
|
|
|
|
filter.Add("service", id)
|
|
|
|
tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
|
|
|
|
Filters: filter,
|
|
|
|
})
|
|
|
|
|
|
|
|
running := 0
|
|
|
|
for _, task := range tasks {
|
|
|
|
if task.Status.State == swarmtypes.TaskStateRunning {
|
|
|
|
running++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case err != nil:
|
|
|
|
return poll.Error(err)
|
|
|
|
case running == i+1:
|
|
|
|
return poll.Success()
|
|
|
|
default:
|
|
|
|
return poll.Continue(
|
|
|
|
"running task count %d (%d total), waiting for %d",
|
|
|
|
running, len(tasks), i+1,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// now, let's do the list operation with no status arg set.
|
|
|
|
resp, err := client.ServiceList(ctx, types.ServiceListOptions{})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Check(t, is.Len(resp, serviceCount))
|
|
|
|
for _, service := range resp {
|
|
|
|
assert.Check(t, is.Nil(service.ServiceStatus))
|
|
|
|
}
|
|
|
|
|
|
|
|
// now try again, but with Status: true. This time, we should have statuses
|
|
|
|
resp, err = client.ServiceList(ctx, types.ServiceListOptions{Status: true})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Check(t, is.Len(resp, serviceCount))
|
|
|
|
for _, service := range resp {
|
|
|
|
replicas := *service.Spec.Mode.Replicated.Replicas
|
|
|
|
|
|
|
|
assert.Assert(t, service.ServiceStatus != nil)
|
|
|
|
// Use assert.Check to not fail out of the test if this fails
|
|
|
|
assert.Check(t, is.Equal(service.ServiceStatus.DesiredTasks, replicas))
|
|
|
|
assert.Check(t, is.Equal(service.ServiceStatus.RunningTasks, replicas))
|
|
|
|
}
|
|
|
|
}
|