2017-04-15 16:46:44 +02:00
package docker
import (
2018-02-27 14:07:07 +01:00
"context"
2017-04-15 16:46:44 +02:00
"strconv"
"testing"
2017-12-01 14:34:03 +01:00
"time"
2017-04-15 16:46:44 +02:00
"github.com/davecgh/go-spew/spew"
2017-07-06 16:28:13 +02:00
docker "github.com/docker/docker/api/types"
dockertypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
dockerclient "github.com/docker/docker/client"
2017-12-01 14:34:03 +01:00
"github.com/stretchr/testify/assert"
2019-01-18 15:18:04 +01:00
"github.com/stretchr/testify/require"
2017-04-15 16:46:44 +02:00
)
type fakeTasksClient struct {
dockerclient . APIClient
2018-02-12 17:50:05 +01:00
tasks [ ] swarm . Task
container dockertypes . ContainerJSON
err error
2017-04-15 16:46:44 +02:00
}
func ( c * fakeTasksClient ) TaskList ( ctx context . Context , options dockertypes . TaskListOptions ) ( [ ] swarm . Task , error ) {
return c . tasks , c . err
}
2018-02-12 17:50:05 +01:00
func ( c * fakeTasksClient ) ContainerInspect ( ctx context . Context , container string ) ( dockertypes . ContainerJSON , error ) {
return c . container , c . err
}
2017-04-15 16:46:44 +02:00
func TestListTasks ( t * testing . T ) {
2017-11-28 11:16:03 +01:00
testCases := [ ] struct {
2017-04-15 16:46:44 +02:00
service swarm . Service
tasks [ ] swarm . Task
isGlobalSVC bool
expectedTasks [ ] string
networks map [ string ] * docker . NetworkResource
} {
{
service : swarmService ( serviceName ( "container" ) ) ,
tasks : [ ] swarm . Task {
2018-02-12 17:50:05 +01:00
swarmTask ( "id1" ,
taskSlot ( 1 ) ,
taskNetworkAttachment ( "1" , "network1" , "overlay" , [ ] string { "127.0.0.1" } ) ,
taskStatus ( taskState ( swarm . TaskStateRunning ) ) ,
) ,
swarmTask ( "id2" ,
taskSlot ( 2 ) ,
taskNetworkAttachment ( "1" , "network1" , "overlay" , [ ] string { "127.0.0.2" } ) ,
taskStatus ( taskState ( swarm . TaskStatePending ) ) ,
) ,
swarmTask ( "id3" ,
taskSlot ( 3 ) ,
taskNetworkAttachment ( "1" , "network1" , "overlay" , [ ] string { "127.0.0.3" } ) ,
) ,
swarmTask ( "id4" ,
taskSlot ( 4 ) ,
taskNetworkAttachment ( "1" , "network1" , "overlay" , [ ] string { "127.0.0.4" } ) ,
taskStatus ( taskState ( swarm . TaskStateRunning ) ) ,
) ,
swarmTask ( "id5" ,
taskSlot ( 5 ) ,
taskNetworkAttachment ( "1" , "network1" , "overlay" , [ ] string { "127.0.0.5" } ) ,
taskStatus ( taskState ( swarm . TaskStateFailed ) ) ,
) ,
2017-04-15 16:46:44 +02:00
} ,
isGlobalSVC : false ,
expectedTasks : [ ] string {
"container.1" ,
"container.4" ,
} ,
networks : map [ string ] * docker . NetworkResource {
"1" : {
Name : "foo" ,
} ,
} ,
} ,
}
2017-11-28 11:16:03 +01:00
for caseID , test := range testCases {
test := test
2017-04-15 16:46:44 +02:00
t . Run ( strconv . Itoa ( caseID ) , func ( t * testing . T ) {
t . Parallel ( )
2019-01-18 15:18:04 +01:00
p := Provider { }
dockerData , err := p . parseService ( context . Background ( ) , test . service , test . networks )
require . NoError ( t , err )
2017-11-28 11:16:03 +01:00
dockerClient := & fakeTasksClient { tasks : test . tasks }
2018-02-12 17:50:05 +01:00
taskDockerData , _ := listTasks ( context . Background ( ) , dockerClient , test . service . ID , dockerData , test . networks , test . isGlobalSVC )
2017-04-15 16:46:44 +02:00
2017-11-28 11:16:03 +01:00
if len ( test . expectedTasks ) != len ( taskDockerData ) {
t . Errorf ( "expected tasks %v, got %v" , spew . Sdump ( test . expectedTasks ) , spew . Sdump ( taskDockerData ) )
2017-04-15 16:46:44 +02:00
}
2017-11-28 11:16:03 +01:00
for i , taskID := range test . expectedTasks {
2017-04-15 16:46:44 +02:00
if taskDockerData [ i ] . Name != taskID {
t . Errorf ( "expect task id %v, got %v" , taskID , taskDockerData [ i ] . Name )
}
}
} )
}
}
2017-12-01 14:34:03 +01:00
type fakeServicesClient struct {
dockerclient . APIClient
dockerVersion string
networks [ ] dockertypes . NetworkResource
services [ ] swarm . Service
2018-02-05 11:34:03 +01:00
tasks [ ] swarm . Task
2017-12-01 14:34:03 +01:00
err error
}
func ( c * fakeServicesClient ) ServiceList ( ctx context . Context , options dockertypes . ServiceListOptions ) ( [ ] swarm . Service , error ) {
return c . services , c . err
}
func ( c * fakeServicesClient ) ServerVersion ( ctx context . Context ) ( dockertypes . Version , error ) {
return dockertypes . Version { APIVersion : c . dockerVersion } , c . err
}
func ( c * fakeServicesClient ) NetworkList ( ctx context . Context , options dockertypes . NetworkListOptions ) ( [ ] dockertypes . NetworkResource , error ) {
return c . networks , c . err
}
2018-02-05 11:34:03 +01:00
func ( c * fakeServicesClient ) TaskList ( ctx context . Context , options dockertypes . TaskListOptions ) ( [ ] swarm . Task , error ) {
return c . tasks , c . err
}
2017-12-01 14:34:03 +01:00
func TestListServices ( t * testing . T ) {
testCases := [ ] struct {
desc string
services [ ] swarm . Service
2018-02-05 11:34:03 +01:00
tasks [ ] swarm . Task
2017-12-01 14:34:03 +01:00
dockerVersion string
networks [ ] dockertypes . NetworkResource
expectedServices [ ] string
} {
{
desc : "Should return no service due to no networks defined" ,
services : [ ] swarm . Service {
swarmService (
serviceName ( "service1" ) ,
serviceLabels ( map [ string ] string {
2019-01-18 15:18:04 +01:00
"traefik.docker.network" : "barnet" ,
"traefik.docker.LBSwarm" : "true" ,
2017-12-01 14:34:03 +01:00
} ) ,
withEndpointSpec ( modeVIP ) ,
withEndpoint (
virtualIP ( "1" , "10.11.12.13/24" ) ,
virtualIP ( "2" , "10.11.12.99/24" ) ,
) ) ,
swarmService (
serviceName ( "service2" ) ,
serviceLabels ( map [ string ] string {
2019-01-18 15:18:04 +01:00
"traefik.docker.network" : "barnet" ,
"traefik.docker.LBSwarm" : "true" ,
2017-12-01 14:34:03 +01:00
} ) ,
withEndpointSpec ( modeDNSSR ) ) ,
} ,
dockerVersion : "1.30" ,
networks : [ ] dockertypes . NetworkResource { } ,
expectedServices : [ ] string { } ,
} ,
{
desc : "Should return only service1" ,
services : [ ] swarm . Service {
swarmService (
serviceName ( "service1" ) ,
serviceLabels ( map [ string ] string {
2019-01-18 15:18:04 +01:00
"traefik.docker.network" : "barnet" ,
"traefik.docker.LBSwarm" : "true" ,
2017-12-01 14:34:03 +01:00
} ) ,
withEndpointSpec ( modeVIP ) ,
withEndpoint (
virtualIP ( "yk6l57rfwizjzxxzftn4amaot" , "10.11.12.13/24" ) ,
virtualIP ( "2" , "10.11.12.99/24" ) ,
) ) ,
swarmService (
serviceName ( "service2" ) ,
serviceLabels ( map [ string ] string {
2019-01-18 15:18:04 +01:00
"traefik.docker.network" : "barnet" ,
"traefik.docker.LBSwarm" : "true" ,
2017-12-01 14:34:03 +01:00
} ) ,
withEndpointSpec ( modeDNSSR ) ) ,
} ,
dockerVersion : "1.30" ,
networks : [ ] dockertypes . NetworkResource {
{
Name : "network_name" ,
ID : "yk6l57rfwizjzxxzftn4amaot" ,
Created : time . Now ( ) ,
Scope : "swarm" ,
Driver : "overlay" ,
EnableIPv6 : false ,
Internal : true ,
Ingress : false ,
ConfigOnly : false ,
Options : map [ string ] string {
"com.docker.network.driver.overlay.vxlanid_list" : "4098" ,
"com.docker.network.enable_ipv6" : "false" ,
} ,
Labels : map [ string ] string {
"com.docker.stack.namespace" : "test" ,
} ,
} ,
} ,
expectedServices : [ ] string {
"service1" ,
} ,
} ,
2018-02-05 11:34:03 +01:00
{
desc : "Should return service1 and service2" ,
services : [ ] swarm . Service {
swarmService (
serviceName ( "service1" ) ,
serviceLabels ( map [ string ] string {
2019-01-18 15:18:04 +01:00
"traefik.docker.network" : "barnet" ,
2018-02-05 11:34:03 +01:00
} ) ,
withEndpointSpec ( modeVIP ) ,
withEndpoint (
virtualIP ( "yk6l57rfwizjzxxzftn4amaot" , "10.11.12.13/24" ) ,
virtualIP ( "2" , "10.11.12.99/24" ) ,
) ) ,
swarmService (
serviceName ( "service2" ) ,
serviceLabels ( map [ string ] string {
2019-01-18 15:18:04 +01:00
"traefik.docker.network" : "barnet" ,
2018-02-05 11:34:03 +01:00
} ) ,
withEndpointSpec ( modeDNSSR ) ) ,
} ,
tasks : [ ] swarm . Task {
2018-02-12 17:50:05 +01:00
swarmTask ( "id1" ,
taskNetworkAttachment ( "yk6l57rfwizjzxxzftn4amaot" , "network_name" , "overlay" , [ ] string { "127.0.0.1" } ) ,
taskStatus ( taskState ( swarm . TaskStateRunning ) ) ,
) ,
swarmTask ( "id2" ,
taskNetworkAttachment ( "yk6l57rfwizjzxxzftn4amaot" , "network_name" , "overlay" , [ ] string { "127.0.0.1" } ) ,
taskStatus ( taskState ( swarm . TaskStateRunning ) ) ,
) ,
2018-02-05 11:34:03 +01:00
} ,
dockerVersion : "1.30" ,
networks : [ ] dockertypes . NetworkResource {
{
Name : "network_name" ,
ID : "yk6l57rfwizjzxxzftn4amaot" ,
Created : time . Now ( ) ,
Scope : "swarm" ,
Driver : "overlay" ,
EnableIPv6 : false ,
Internal : true ,
Ingress : false ,
ConfigOnly : false ,
Options : map [ string ] string {
"com.docker.network.driver.overlay.vxlanid_list" : "4098" ,
"com.docker.network.enable_ipv6" : "false" ,
} ,
Labels : map [ string ] string {
"com.docker.stack.namespace" : "test" ,
} ,
} ,
} ,
expectedServices : [ ] string {
"service1.0" ,
"service1.0" ,
"service2.0" ,
"service2.0" ,
} ,
} ,
2017-12-01 14:34:03 +01:00
}
2019-01-18 15:18:04 +01:00
for _ , test := range testCases {
2017-12-01 14:34:03 +01:00
test := test
2019-01-18 15:18:04 +01:00
t . Run ( test . desc , func ( t * testing . T ) {
2017-12-01 14:34:03 +01:00
t . Parallel ( )
2019-01-18 15:18:04 +01:00
2018-02-05 11:34:03 +01:00
dockerClient := & fakeServicesClient { services : test . services , tasks : test . tasks , dockerVersion : test . dockerVersion , networks : test . networks }
2017-12-02 19:26:44 +01:00
2019-01-18 15:18:04 +01:00
p := Provider { }
serviceDockerData , err := p . listServices ( context . Background ( ) , dockerClient )
2017-12-02 19:26:44 +01:00
assert . NoError ( t , err )
2017-12-01 14:34:03 +01:00
assert . Equal ( t , len ( test . expectedServices ) , len ( serviceDockerData ) )
for i , serviceName := range test . expectedServices {
2019-01-18 15:18:04 +01:00
if len ( serviceDockerData ) <= i {
require . Fail ( t , "index" , "invalid index %d" , i )
}
2017-12-01 14:34:03 +01:00
assert . Equal ( t , serviceName , serviceDockerData [ i ] . Name )
}
} )
}
}
2018-02-12 17:50:05 +01:00
func TestSwarmTaskParsing ( t * testing . T ) {
testCases := [ ] struct {
service swarm . Service
tasks [ ] swarm . Task
isGlobalSVC bool
expected map [ string ] dockerData
networks map [ string ] * docker . NetworkResource
} {
{
service : swarmService ( serviceName ( "container" ) ) ,
tasks : [ ] swarm . Task {
swarmTask ( "id1" , taskSlot ( 1 ) ) ,
swarmTask ( "id2" , taskSlot ( 2 ) ) ,
swarmTask ( "id3" , taskSlot ( 3 ) ) ,
} ,
isGlobalSVC : false ,
expected : map [ string ] dockerData {
"id1" : {
Name : "container.1" ,
} ,
"id2" : {
Name : "container.2" ,
} ,
"id3" : {
Name : "container.3" ,
} ,
} ,
networks : map [ string ] * docker . NetworkResource {
"1" : {
Name : "foo" ,
} ,
} ,
} ,
{
service : swarmService ( serviceName ( "container" ) ) ,
tasks : [ ] swarm . Task {
swarmTask ( "id1" ) ,
swarmTask ( "id2" ) ,
swarmTask ( "id3" ) ,
} ,
isGlobalSVC : true ,
expected : map [ string ] dockerData {
"id1" : {
Name : "container.id1" ,
} ,
"id2" : {
Name : "container.id2" ,
} ,
"id3" : {
Name : "container.id3" ,
} ,
} ,
networks : map [ string ] * docker . NetworkResource {
"1" : {
Name : "foo" ,
} ,
} ,
} ,
{
service : swarmService (
serviceName ( "container" ) ,
withEndpointSpec ( modeVIP ) ,
withEndpoint (
virtualIP ( "1" , "" ) ,
) ,
) ,
tasks : [ ] swarm . Task {
swarmTask (
"id1" ,
taskNetworkAttachment ( "1" , "vlan" , "macvlan" , [ ] string { "127.0.0.1" } ) ,
taskStatus (
taskState ( swarm . TaskStateRunning ) ,
taskContainerStatus ( "c1" ) ,
) ,
) ,
} ,
isGlobalSVC : true ,
expected : map [ string ] dockerData {
"id1" : {
Name : "container.id1" ,
NetworkSettings : networkSettings {
Networks : map [ string ] * networkData {
"vlan" : {
Name : "vlan" ,
Addr : "10.11.12.13" ,
} ,
} ,
} ,
} ,
} ,
networks : map [ string ] * docker . NetworkResource {
"1" : {
Name : "vlan" ,
} ,
} ,
} ,
}
for caseID , test := range testCases {
test := test
t . Run ( strconv . Itoa ( caseID ) , func ( t * testing . T ) {
t . Parallel ( )
2019-01-18 15:18:04 +01:00
p := Provider { }
dData , err := p . parseService ( context . Background ( ) , test . service , test . networks )
require . NoError ( t , err )
2018-02-12 17:50:05 +01:00
for _ , task := range test . tasks {
2019-01-18 15:18:04 +01:00
taskDockerData := parseTasks ( context . Background ( ) , task , dData , test . networks , test . isGlobalSVC )
2018-02-12 17:50:05 +01:00
expected := test . expected [ task . ID ]
assert . Equal ( t , expected . Name , taskDockerData . Name )
}
} )
}
}