mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
5b69ff466e
Adds functionality to parse and return network attachment spec information. Network attachment tasks are phony tasks created in swarmkit to deal with unmanaged containers attached to swarmkit. Before this change, attempting `docker inspect` on the task id of a network attachment task would result in an empty task object. After this change, a full task object is returned Fixes #26548 the correct way. Signed-off-by: Drew Erny <drew.erny@docker.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
308 lines
8.2 KiB
Go
308 lines
8.2 KiB
Go
package convert // import "github.com/docker/docker/daemon/cluster/convert"
|
|
|
|
import (
|
|
"testing"
|
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
|
"github.com/docker/docker/api/types/swarm/runtime"
|
|
swarmapi "github.com/docker/swarmkit/api"
|
|
google_protobuf3 "github.com/gogo/protobuf/types"
|
|
"github.com/gotestyourself/gotestyourself/assert"
|
|
)
|
|
|
|
func TestServiceConvertFromGRPCRuntimeContainer(t *testing.T) {
|
|
gs := swarmapi.Service{
|
|
Meta: swarmapi.Meta{
|
|
Version: swarmapi.Version{
|
|
Index: 1,
|
|
},
|
|
CreatedAt: nil,
|
|
UpdatedAt: nil,
|
|
},
|
|
SpecVersion: &swarmapi.Version{
|
|
Index: 1,
|
|
},
|
|
Spec: swarmapi.ServiceSpec{
|
|
Task: swarmapi.TaskSpec{
|
|
Runtime: &swarmapi.TaskSpec_Container{
|
|
Container: &swarmapi.ContainerSpec{
|
|
Image: "alpine:latest",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
svc, err := ServiceFromGRPC(gs)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if svc.Spec.TaskTemplate.Runtime != swarmtypes.RuntimeContainer {
|
|
t.Fatalf("expected type %s; received %T", swarmtypes.RuntimeContainer, svc.Spec.TaskTemplate.Runtime)
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertFromGRPCGenericRuntimePlugin(t *testing.T) {
|
|
kind := string(swarmtypes.RuntimePlugin)
|
|
url := swarmtypes.RuntimeURLPlugin
|
|
gs := swarmapi.Service{
|
|
Meta: swarmapi.Meta{
|
|
Version: swarmapi.Version{
|
|
Index: 1,
|
|
},
|
|
CreatedAt: nil,
|
|
UpdatedAt: nil,
|
|
},
|
|
SpecVersion: &swarmapi.Version{
|
|
Index: 1,
|
|
},
|
|
Spec: swarmapi.ServiceSpec{
|
|
Task: swarmapi.TaskSpec{
|
|
Runtime: &swarmapi.TaskSpec_Generic{
|
|
Generic: &swarmapi.GenericRuntimeSpec{
|
|
Kind: kind,
|
|
Payload: &google_protobuf3.Any{
|
|
TypeUrl: string(url),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
svc, err := ServiceFromGRPC(gs)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if svc.Spec.TaskTemplate.Runtime != swarmtypes.RuntimePlugin {
|
|
t.Fatalf("expected type %s; received %T", swarmtypes.RuntimePlugin, svc.Spec.TaskTemplate.Runtime)
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertToGRPCGenericRuntimePlugin(t *testing.T) {
|
|
s := swarmtypes.ServiceSpec{
|
|
TaskTemplate: swarmtypes.TaskSpec{
|
|
Runtime: swarmtypes.RuntimePlugin,
|
|
PluginSpec: &runtime.PluginSpec{},
|
|
},
|
|
Mode: swarmtypes.ServiceMode{
|
|
Global: &swarmtypes.GlobalService{},
|
|
},
|
|
}
|
|
|
|
svc, err := ServiceSpecToGRPC(s)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
v, ok := svc.Task.Runtime.(*swarmapi.TaskSpec_Generic)
|
|
if !ok {
|
|
t.Fatal("expected type swarmapi.TaskSpec_Generic")
|
|
}
|
|
|
|
if v.Generic.Payload.TypeUrl != string(swarmtypes.RuntimeURLPlugin) {
|
|
t.Fatalf("expected url %s; received %s", swarmtypes.RuntimeURLPlugin, v.Generic.Payload.TypeUrl)
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertToGRPCContainerRuntime(t *testing.T) {
|
|
image := "alpine:latest"
|
|
s := swarmtypes.ServiceSpec{
|
|
TaskTemplate: swarmtypes.TaskSpec{
|
|
ContainerSpec: &swarmtypes.ContainerSpec{
|
|
Image: image,
|
|
},
|
|
},
|
|
Mode: swarmtypes.ServiceMode{
|
|
Global: &swarmtypes.GlobalService{},
|
|
},
|
|
}
|
|
|
|
svc, err := ServiceSpecToGRPC(s)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
v, ok := svc.Task.Runtime.(*swarmapi.TaskSpec_Container)
|
|
if !ok {
|
|
t.Fatal("expected type swarmapi.TaskSpec_Container")
|
|
}
|
|
|
|
if v.Container.Image != image {
|
|
t.Fatalf("expected image %s; received %s", image, v.Container.Image)
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertToGRPCGenericRuntimeCustom(t *testing.T) {
|
|
s := swarmtypes.ServiceSpec{
|
|
TaskTemplate: swarmtypes.TaskSpec{
|
|
Runtime: "customruntime",
|
|
},
|
|
Mode: swarmtypes.ServiceMode{
|
|
Global: &swarmtypes.GlobalService{},
|
|
},
|
|
}
|
|
|
|
if _, err := ServiceSpecToGRPC(s); err != ErrUnsupportedRuntime {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertToGRPCIsolation(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
from containertypes.Isolation
|
|
to swarmapi.ContainerSpec_Isolation
|
|
}{
|
|
{name: "empty", from: containertypes.IsolationEmpty, to: swarmapi.ContainerIsolationDefault},
|
|
{name: "default", from: containertypes.IsolationDefault, to: swarmapi.ContainerIsolationDefault},
|
|
{name: "process", from: containertypes.IsolationProcess, to: swarmapi.ContainerIsolationProcess},
|
|
{name: "hyperv", from: containertypes.IsolationHyperV, to: swarmapi.ContainerIsolationHyperV},
|
|
{name: "proCess", from: containertypes.Isolation("proCess"), to: swarmapi.ContainerIsolationProcess},
|
|
{name: "hypErv", from: containertypes.Isolation("hypErv"), to: swarmapi.ContainerIsolationHyperV},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
s := swarmtypes.ServiceSpec{
|
|
TaskTemplate: swarmtypes.TaskSpec{
|
|
ContainerSpec: &swarmtypes.ContainerSpec{
|
|
Image: "alpine:latest",
|
|
Isolation: c.from,
|
|
},
|
|
},
|
|
Mode: swarmtypes.ServiceMode{
|
|
Global: &swarmtypes.GlobalService{},
|
|
},
|
|
}
|
|
res, err := ServiceSpecToGRPC(s)
|
|
assert.NilError(t, err)
|
|
v, ok := res.Task.Runtime.(*swarmapi.TaskSpec_Container)
|
|
if !ok {
|
|
t.Fatal("expected type swarmapi.TaskSpec_Container")
|
|
}
|
|
assert.Equal(t, c.to, v.Container.Isolation)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertFromGRPCIsolation(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
from swarmapi.ContainerSpec_Isolation
|
|
to containertypes.Isolation
|
|
}{
|
|
{name: "default", to: containertypes.IsolationDefault, from: swarmapi.ContainerIsolationDefault},
|
|
{name: "process", to: containertypes.IsolationProcess, from: swarmapi.ContainerIsolationProcess},
|
|
{name: "hyperv", to: containertypes.IsolationHyperV, from: swarmapi.ContainerIsolationHyperV},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
gs := swarmapi.Service{
|
|
Meta: swarmapi.Meta{
|
|
Version: swarmapi.Version{
|
|
Index: 1,
|
|
},
|
|
CreatedAt: nil,
|
|
UpdatedAt: nil,
|
|
},
|
|
SpecVersion: &swarmapi.Version{
|
|
Index: 1,
|
|
},
|
|
Spec: swarmapi.ServiceSpec{
|
|
Task: swarmapi.TaskSpec{
|
|
Runtime: &swarmapi.TaskSpec_Container{
|
|
Container: &swarmapi.ContainerSpec{
|
|
Image: "alpine:latest",
|
|
Isolation: c.from,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
svc, err := ServiceFromGRPC(gs)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
assert.Equal(t, c.to, svc.Spec.TaskTemplate.ContainerSpec.Isolation)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertToGRPCNetworkAtachmentRuntime(t *testing.T) {
|
|
someid := "asfjkl"
|
|
s := swarmtypes.ServiceSpec{
|
|
TaskTemplate: swarmtypes.TaskSpec{
|
|
Runtime: swarmtypes.RuntimeNetworkAttachment,
|
|
NetworkAttachmentSpec: &swarmtypes.NetworkAttachmentSpec{
|
|
ContainerID: someid,
|
|
},
|
|
},
|
|
}
|
|
|
|
// discard the service, which will be empty
|
|
_, err := ServiceSpecToGRPC(s)
|
|
if err == nil {
|
|
t.Fatalf("expected error %v but got no error", ErrUnsupportedRuntime)
|
|
}
|
|
if err != ErrUnsupportedRuntime {
|
|
t.Fatalf("expected error %v but got error %v", ErrUnsupportedRuntime, err)
|
|
}
|
|
}
|
|
|
|
func TestServiceConvertToGRPCMismatchedRuntime(t *testing.T) {
|
|
// NOTE(dperny): an earlier version of this test was for code that also
|
|
// converted network attachment tasks to GRPC. that conversion code was
|
|
// removed, so if this loop body seems a bit complicated, that's why.
|
|
for i, rt := range []swarmtypes.RuntimeType{
|
|
swarmtypes.RuntimeContainer,
|
|
swarmtypes.RuntimePlugin,
|
|
} {
|
|
for j, spec := range []swarmtypes.TaskSpec{
|
|
{ContainerSpec: &swarmtypes.ContainerSpec{}},
|
|
{PluginSpec: &runtime.PluginSpec{}},
|
|
} {
|
|
// skip the cases, where the indices match, which would not error
|
|
if i == j {
|
|
continue
|
|
}
|
|
// set the task spec, then change the runtime
|
|
s := swarmtypes.ServiceSpec{
|
|
TaskTemplate: spec,
|
|
}
|
|
s.TaskTemplate.Runtime = rt
|
|
|
|
if _, err := ServiceSpecToGRPC(s); err != ErrMismatchedRuntime {
|
|
t.Fatalf("expected %v got %v", ErrMismatchedRuntime, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTaskConvertFromGRPCNetworkAttachment(t *testing.T) {
|
|
containerID := "asdfjkl"
|
|
s := swarmapi.TaskSpec{
|
|
Runtime: &swarmapi.TaskSpec_Attachment{
|
|
Attachment: &swarmapi.NetworkAttachmentSpec{
|
|
ContainerID: containerID,
|
|
},
|
|
},
|
|
}
|
|
ts, err := taskSpecFromGRPC(s)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if ts.NetworkAttachmentSpec == nil {
|
|
t.Fatal("expected task spec to have network attachment spec")
|
|
}
|
|
if ts.NetworkAttachmentSpec.ContainerID != containerID {
|
|
t.Fatalf("expected network attachment spec container id to be %q, was %q", containerID, ts.NetworkAttachmentSpec.ContainerID)
|
|
}
|
|
if ts.Runtime != swarmtypes.RuntimeNetworkAttachment {
|
|
t.Fatalf("expected Runtime to be %v", swarmtypes.RuntimeNetworkAttachment)
|
|
}
|
|
}
|