2014-09-09 04:33:17 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2014-09-09 04:33:17 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package dockertools
import (
2015-05-08 17:53:00 +00:00
"encoding/json"
2014-09-09 04:33:17 +00:00
"fmt"
"hash/adler32"
2016-07-24 21:28:31 +00:00
"math/rand"
"path"
2014-09-09 04:33:17 +00:00
"reflect"
2015-04-13 22:25:14 +00:00
"sort"
2015-08-31 12:53:02 +00:00
"strconv"
2015-06-05 00:37:07 +00:00
"strings"
2014-09-09 04:33:17 +00:00
"testing"
2015-08-05 22:05:17 +00:00
"github.com/docker/docker/pkg/jsonmessage"
2016-04-04 08:56:49 +00:00
dockertypes "github.com/docker/engine-api/types"
2016-04-14 17:36:13 +00:00
dockernat "github.com/docker/go-connections/nat"
2015-10-16 03:00:28 +00:00
cadvisorapi "github.com/google/cadvisor/info/v1"
2016-07-20 00:36:48 +00:00
"github.com/stretchr/testify/assert"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
2016-03-31 22:20:04 +00:00
"k8s.io/kubernetes/pkg/apis/componentconfig"
2015-09-03 21:40:58 +00:00
"k8s.io/kubernetes/pkg/client/record"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/credentialprovider"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
2016-02-25 23:40:44 +00:00
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
2016-07-19 22:42:21 +00:00
"k8s.io/kubernetes/pkg/kubelet/images"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/kubelet/network"
2016-02-25 23:40:44 +00:00
nettest "k8s.io/kubernetes/pkg/kubelet/network/testing"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/types"
2016-01-05 07:31:20 +00:00
hashutil "k8s.io/kubernetes/pkg/util/hash"
2014-09-09 04:33:17 +00:00
)
func verifyCalls ( t * testing . T , fakeDocker * FakeDockerClient , calls [ ] string ) {
2016-07-20 00:36:48 +00:00
assert . New ( t ) . NoError ( fakeDocker . AssertCalls ( calls ) )
2014-09-09 04:33:17 +00:00
}
func verifyStringArrayEquals ( t * testing . T , actual , expected [ ] string ) {
invalid := len ( actual ) != len ( expected )
if ! invalid {
for ix , value := range actual {
if expected [ ix ] != value {
invalid = true
}
}
}
if invalid {
t . Errorf ( "Expected: %#v, Actual: %#v" , expected , actual )
}
}
2016-04-04 08:56:49 +00:00
func findPodContainer ( dockerContainers [ ] * dockertypes . Container , podFullName string , uid types . UID , containerName string ) ( * dockertypes . Container , bool , uint64 ) {
2015-11-02 17:49:07 +00:00
for _ , dockerContainer := range dockerContainers {
if len ( dockerContainer . Names ) == 0 {
continue
}
dockerName , hash , err := ParseDockerName ( dockerContainer . Names [ 0 ] )
if err != nil {
continue
}
if dockerName . PodFullName == podFullName &&
( uid == "" || dockerName . PodUID == uid ) &&
dockerName . ContainerName == containerName {
return dockerContainer , true , hash
}
}
return nil , false , 0
}
2014-09-09 04:33:17 +00:00
func TestGetContainerID ( t * testing . T ) {
2016-04-04 23:01:11 +00:00
fakeDocker := NewFakeDockerClient ( )
2016-04-04 22:27:20 +00:00
fakeDocker . SetFakeRunningContainers ( [ ] * FakeContainer {
2014-09-09 04:33:17 +00:00
{
2015-11-19 21:59:18 +00:00
ID : "foobar" ,
Name : "/k8s_foo_qux_ns_1234_42" ,
2014-09-09 04:33:17 +00:00
} ,
{
2015-11-19 21:59:18 +00:00
ID : "barbar" ,
Name : "/k8s_bar_qux_ns_2565_42" ,
2014-09-09 04:33:17 +00:00
} ,
2015-11-19 21:59:18 +00:00
} )
2014-09-09 04:33:17 +00:00
2014-09-29 21:38:31 +00:00
dockerContainers , err := GetKubeletDockerContainers ( fakeDocker , false )
2014-09-09 04:33:17 +00:00
if err != nil {
t . Errorf ( "Expected no error, Got %#v" , err )
}
if len ( dockerContainers ) != 2 {
2016-04-04 08:56:49 +00:00
t . Errorf ( "Expected %#v, Got %#v" , fakeDocker . RunningContainerList , dockerContainers )
2014-09-09 04:33:17 +00:00
}
verifyCalls ( t , fakeDocker , [ ] string { "list" } )
2015-11-02 02:49:05 +00:00
dockerContainer , found , _ := findPodContainer ( dockerContainers , "qux_ns" , "" , "foo" )
2014-09-09 04:33:17 +00:00
if dockerContainer == nil || ! found {
t . Errorf ( "Failed to find container %#v" , dockerContainer )
}
2014-12-17 05:11:27 +00:00
fakeDocker . ClearCalls ( )
2015-11-02 02:49:05 +00:00
dockerContainer , found , _ = findPodContainer ( dockerContainers , "foobar" , "" , "foo" )
2014-09-09 04:33:17 +00:00
verifyCalls ( t , fakeDocker , [ ] string { } )
if dockerContainer != nil || found {
t . Errorf ( "Should not have found container %#v" , dockerContainer )
}
}
2015-01-05 01:30:30 +00:00
func verifyPackUnpack ( t * testing . T , podNamespace , podUID , podName , containerName string ) {
2014-09-09 04:33:17 +00:00
container := & api . Container { Name : containerName }
hasher := adler32 . New ( )
2016-01-05 07:31:20 +00:00
hashutil . DeepHashObject ( hasher , * container )
2014-09-09 04:33:17 +00:00
computedHash := uint64 ( hasher . Sum32 ( ) )
2015-02-26 20:27:14 +00:00
podFullName := fmt . Sprintf ( "%s_%s" , podName , podNamespace )
2016-02-04 00:40:04 +00:00
_ , name , _ := BuildDockerName ( KubeletContainerName { podFullName , types . UID ( podUID ) , container . Name } , container )
2015-03-20 11:55:02 +00:00
returned , hash , err := ParseDockerName ( name )
2015-03-12 23:31:57 +00:00
if err != nil {
t . Errorf ( "Failed to parse Docker container name %q: %v" , name , err )
}
2015-03-20 11:55:02 +00:00
if podFullName != returned . PodFullName || podUID != string ( returned . PodUID ) || containerName != returned . ContainerName || computedHash != hash {
t . Errorf ( "For (%s, %s, %s, %d), unpacked (%s, %s, %s, %d)" , podFullName , podUID , containerName , computedHash , returned . PodFullName , returned . PodUID , returned . ContainerName , hash )
2014-09-09 04:33:17 +00:00
}
}
2015-06-15 19:04:30 +00:00
func TestContainerNaming ( t * testing . T ) {
2015-01-10 01:19:31 +00:00
podUID := "12345678"
verifyPackUnpack ( t , "file" , podUID , "name" , "container" )
verifyPackUnpack ( t , "file" , podUID , "name-with-dashes" , "container" )
2015-01-05 01:30:30 +00:00
// UID is same as pod name
2015-01-10 01:19:31 +00:00
verifyPackUnpack ( t , "file" , podUID , podUID , "container" )
2014-09-25 00:05:53 +00:00
// No Container name
2015-01-10 01:19:31 +00:00
verifyPackUnpack ( t , "other" , podUID , "name" , "" )
2014-09-09 04:33:17 +00:00
container := & api . Container { Name : "container" }
podName := "foo"
podNamespace := "test"
2015-02-26 20:27:14 +00:00
name := fmt . Sprintf ( "k8s_%s_%s_%s_%s_42" , container . Name , podName , podNamespace , podUID )
podFullName := fmt . Sprintf ( "%s_%s" , podName , podNamespace )
2015-01-10 01:19:31 +00:00
2015-03-20 11:55:02 +00:00
returned , hash , err := ParseDockerName ( name )
2015-03-12 23:31:57 +00:00
if err != nil {
t . Errorf ( "Failed to parse Docker container name %q: %v" , name , err )
}
2015-03-20 11:55:02 +00:00
if returned . PodFullName != podFullName || string ( returned . PodUID ) != podUID || returned . ContainerName != container . Name || hash != 0 {
t . Errorf ( "unexpected parse: %s %s %s %d" , returned . PodFullName , returned . PodUID , returned . ContainerName , hash )
2014-09-09 04:33:17 +00:00
}
}
2016-04-25 19:40:59 +00:00
func TestApplyDefaultImageTag ( t * testing . T ) {
for _ , testCase := range [ ] struct {
Input string
Output string
2015-03-17 00:51:20 +00:00
} {
2016-04-25 19:40:59 +00:00
{ Input : "root" , Output : "root:latest" } ,
{ Input : "root:tag" , Output : "root:tag" } ,
{ Input : "root@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" , Output : "root@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" } ,
} {
image , err := applyDefaultImageTag ( testCase . Input )
2016-03-30 14:23:07 +00:00
if err != nil {
2016-04-25 19:40:59 +00:00
t . Errorf ( "applyDefaultTag(%s) failed: %v" , testCase . Input , err )
} else if image != testCase . Output {
t . Errorf ( "Expected image reference: %q, got %q" , testCase . Output , image )
2015-03-17 00:51:20 +00:00
}
}
2015-03-17 22:16:33 +00:00
}
2015-05-08 17:30:59 +00:00
func TestPullWithNoSecrets ( t * testing . T ) {
2015-03-17 00:51:20 +00:00
tests := [ ] struct {
imageName string
expectedImage string
} {
2015-05-08 17:30:59 +00:00
{ "ubuntu" , "ubuntu:latest using {}" } ,
{ "ubuntu:2342" , "ubuntu:2342 using {}" } ,
{ "ubuntu:latest" , "ubuntu:latest using {}" } ,
{ "foo/bar:445566" , "foo/bar:445566 using {}" } ,
{ "registry.example.com:5000/foobar" , "registry.example.com:5000/foobar:latest using {}" } ,
{ "registry.example.com:5000/foobar:5342" , "registry.example.com:5000/foobar:5342 using {}" } ,
{ "registry.example.com:5000/foobar:latest" , "registry.example.com:5000/foobar:latest using {}" } ,
2015-03-17 00:51:20 +00:00
}
for _ , test := range tests {
fakeKeyring := & credentialprovider . FakeKeyring { }
2016-04-04 23:01:11 +00:00
fakeClient := NewFakeDockerClient ( )
2015-03-17 00:51:20 +00:00
dp := dockerPuller {
client : fakeClient ,
keyring : fakeKeyring ,
}
2015-05-08 17:53:00 +00:00
err := dp . Pull ( test . imageName , [ ] api . Secret { } )
2015-03-17 00:51:20 +00:00
if err != nil {
t . Errorf ( "unexpected non-nil err: %s" , err )
continue
}
if e , a := 1 , len ( fakeClient . pulled ) ; e != a {
t . Errorf ( "%s: expected 1 pulled image, got %d: %v" , test . imageName , a , fakeClient . pulled )
continue
}
if e , a := test . expectedImage , fakeClient . pulled [ 0 ] ; e != a {
t . Errorf ( "%s: expected pull of %q, but got %q" , test . imageName , e , a )
2015-03-17 22:16:33 +00:00
}
}
}
2015-06-05 00:37:07 +00:00
func TestPullWithJSONError ( t * testing . T ) {
tests := map [ string ] struct {
imageName string
err error
expectedError string
} {
"Json error" : {
"ubuntu" ,
& jsonmessage . JSONError { Code : 50 , Message : "Json error" } ,
"Json error" ,
} ,
"Bad gateway" : {
"ubuntu" ,
& jsonmessage . JSONError { Code : 502 , Message : "<!doctype html>\n<html class=\"no-js\" lang=\"\">\n <head>\n </head>\n <body>\n <h1>Oops, there was an error!</h1>\n <p>We have been contacted of this error, feel free to check out <a href=\"http://status.docker.com/\">status.docker.com</a>\n to see if there is a bigger issue.</p>\n\n </body>\n</html>" } ,
2016-07-19 22:42:21 +00:00
images . RegistryUnavailable . Error ( ) ,
2015-06-05 00:37:07 +00:00
} ,
}
for i , test := range tests {
fakeKeyring := & credentialprovider . FakeKeyring { }
2016-04-04 23:01:11 +00:00
fakeClient := NewFakeDockerClient ( )
fakeClient . InjectError ( "pull" , test . err )
2015-06-05 00:37:07 +00:00
puller := & dockerPuller {
client : fakeClient ,
keyring : fakeKeyring ,
}
err := puller . Pull ( test . imageName , [ ] api . Secret { } )
if err == nil || ! strings . Contains ( err . Error ( ) , test . expectedError ) {
2015-08-08 01:52:23 +00:00
t . Errorf ( "%s: expect error %s, got : %s" , i , test . expectedError , err )
2015-06-05 00:37:07 +00:00
continue
}
}
}
2015-05-08 17:53:00 +00:00
func TestPullWithSecrets ( t * testing . T ) {
2015-05-19 13:00:12 +00:00
// auth value is equivalent to: "username":"passed-user","password":"passed-password"
dockerCfg := map [ string ] map [ string ] string { "index.docker.io/v1/" : { "email" : "passed-email" , "auth" : "cGFzc2VkLXVzZXI6cGFzc2VkLXBhc3N3b3Jk" } }
2015-05-08 17:53:00 +00:00
dockercfgContent , err := json . Marshal ( dockerCfg )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-08-14 09:08:08 +00:00
dockerConfigJson := map [ string ] map [ string ] map [ string ] string { "auths" : dockerCfg }
dockerConfigJsonContent , err := json . Marshal ( dockerConfigJson )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2015-05-08 17:53:00 +00:00
tests := map [ string ] struct {
imageName string
passedSecrets [ ] api . Secret
builtInDockerConfig credentialprovider . DockerConfig
expectedPulls [ ] string
} {
"no matching secrets" : {
"ubuntu" ,
[ ] api . Secret { } ,
credentialprovider . DockerConfig ( map [ string ] credentialprovider . DockerConfigEntry { } ) ,
[ ] string { "ubuntu:latest using {}" } ,
} ,
"default keyring secrets" : {
"ubuntu" ,
[ ] api . Secret { } ,
2016-03-29 18:27:59 +00:00
credentialprovider . DockerConfig ( map [ string ] credentialprovider . DockerConfigEntry { "index.docker.io/v1/" : { "built-in" , "password" , "email" , nil } } ) ,
2015-05-08 17:53:00 +00:00
[ ] string { ` ubuntu:latest using { "username":"built-in","password":"password","email":"email"} ` } ,
} ,
"default keyring secrets unused" : {
"ubuntu" ,
[ ] api . Secret { } ,
2016-03-29 18:27:59 +00:00
credentialprovider . DockerConfig ( map [ string ] credentialprovider . DockerConfigEntry { "extraneous" : { "built-in" , "password" , "email" , nil } } ) ,
2015-05-08 17:53:00 +00:00
[ ] string { ` ubuntu:latest using { } ` } ,
} ,
"builtin keyring secrets, but use passed" : {
"ubuntu" ,
[ ] api . Secret { { Type : api . SecretTypeDockercfg , Data : map [ string ] [ ] byte { api . DockerConfigKey : dockercfgContent } } } ,
2016-03-29 18:27:59 +00:00
credentialprovider . DockerConfig ( map [ string ] credentialprovider . DockerConfigEntry { "index.docker.io/v1/" : { "built-in" , "password" , "email" , nil } } ) ,
2015-05-08 17:53:00 +00:00
[ ] string { ` ubuntu:latest using { "username":"passed-user","password":"passed-password","email":"passed-email"} ` } ,
} ,
2015-08-14 09:08:08 +00:00
"builtin keyring secrets, but use passed with new docker config" : {
"ubuntu" ,
[ ] api . Secret { { Type : api . SecretTypeDockerConfigJson , Data : map [ string ] [ ] byte { api . DockerConfigJsonKey : dockerConfigJsonContent } } } ,
2016-03-29 18:27:59 +00:00
credentialprovider . DockerConfig ( map [ string ] credentialprovider . DockerConfigEntry { "index.docker.io/v1/" : { "built-in" , "password" , "email" , nil } } ) ,
2015-05-08 17:53:00 +00:00
[ ] string { ` ubuntu:latest using { "username":"passed-user","password":"passed-password","email":"passed-email"} ` } ,
} ,
}
2016-02-16 01:32:12 +00:00
for i , test := range tests {
2015-05-08 17:53:00 +00:00
builtInKeyRing := & credentialprovider . BasicDockerKeyring { }
builtInKeyRing . Add ( test . builtInDockerConfig )
2016-04-04 23:01:11 +00:00
fakeClient := NewFakeDockerClient ( )
2015-05-08 17:53:00 +00:00
dp := dockerPuller {
client : fakeClient ,
keyring : builtInKeyRing ,
}
err := dp . Pull ( test . imageName , test . passedSecrets )
if err != nil {
2016-02-16 01:32:12 +00:00
t . Errorf ( "%s: unexpected non-nil err: %s" , i , err )
2015-05-08 17:53:00 +00:00
continue
}
if e , a := 1 , len ( fakeClient . pulled ) ; e != a {
2016-02-16 01:32:12 +00:00
t . Errorf ( "%s: expected 1 pulled image, got %d: %v" , i , a , fakeClient . pulled )
2015-05-08 17:53:00 +00:00
continue
}
if e , a := test . expectedPulls , fakeClient . pulled ; ! reflect . DeepEqual ( e , a ) {
2016-02-16 01:32:12 +00:00
t . Errorf ( "%s: expected pull of %v, but got %v" , i , e , a )
2015-05-08 17:53:00 +00:00
}
}
}
2015-02-10 15:23:32 +00:00
func TestDockerKeyringLookupFails ( t * testing . T ) {
fakeKeyring := & credentialprovider . FakeKeyring { }
2016-04-04 23:01:11 +00:00
fakeClient := NewFakeDockerClient ( )
fakeClient . InjectError ( "pull" , fmt . Errorf ( "test error" ) )
2015-02-10 15:23:32 +00:00
dp := dockerPuller {
client : fakeClient ,
keyring : fakeKeyring ,
}
2015-05-08 17:53:00 +00:00
err := dp . Pull ( "host/repository/image:version" , [ ] api . Secret { } )
2015-02-10 15:23:32 +00:00
if err == nil {
t . Errorf ( "unexpected non-error" )
}
2015-03-17 00:51:20 +00:00
msg := "image pull failed for host/repository/image:version, this may be because there are no credentials on this request. details: (test error)"
2015-02-10 15:23:32 +00:00
if err . Error ( ) != msg {
t . Errorf ( "expected: %s, saw: %s" , msg , err . Error ( ) )
}
}
2014-09-06 01:13:19 +00:00
func TestDockerKeyringLookup ( t * testing . T ) {
2016-03-29 18:27:59 +00:00
ada := credentialprovider . LazyAuthConfiguration {
2016-04-06 15:06:37 +00:00
AuthConfig : dockertypes . AuthConfig {
2016-03-29 18:27:59 +00:00
Username : "ada" ,
Password : "smash" ,
Email : "ada@example.com" ,
} ,
2014-09-06 01:13:19 +00:00
}
2016-03-29 18:27:59 +00:00
grace := credentialprovider . LazyAuthConfiguration {
2016-04-06 15:06:37 +00:00
AuthConfig : dockertypes . AuthConfig {
2016-03-29 18:27:59 +00:00
Username : "grace" ,
Password : "squash" ,
Email : "grace@example.com" ,
} ,
2014-09-06 01:13:19 +00:00
}
2014-11-15 13:50:59 +00:00
dk := & credentialprovider . BasicDockerKeyring { }
dk . Add ( credentialprovider . DockerConfig {
"bar.example.com/pong" : credentialprovider . DockerConfigEntry {
Username : grace . Username ,
Password : grace . Password ,
Email : grace . Email ,
} ,
"bar.example.com" : credentialprovider . DockerConfigEntry {
Username : ada . Username ,
Password : ada . Password ,
Email : ada . Email ,
} ,
} )
2014-09-06 01:13:19 +00:00
tests := [ ] struct {
image string
2016-03-29 18:27:59 +00:00
match [ ] credentialprovider . LazyAuthConfiguration
2014-09-06 01:13:19 +00:00
ok bool
} {
// direct match
2016-03-29 18:27:59 +00:00
{ "bar.example.com" , [ ] credentialprovider . LazyAuthConfiguration { ada } , true } ,
2014-09-06 01:13:19 +00:00
// direct match deeper than other possible matches
2016-03-29 18:27:59 +00:00
{ "bar.example.com/pong" , [ ] credentialprovider . LazyAuthConfiguration { grace , ada } , true } ,
2014-09-06 01:13:19 +00:00
// no direct match, deeper path ignored
2016-03-29 18:27:59 +00:00
{ "bar.example.com/ping" , [ ] credentialprovider . LazyAuthConfiguration { ada } , true } ,
2014-09-06 01:13:19 +00:00
// match first part of path token
2016-03-29 18:27:59 +00:00
{ "bar.example.com/pongz" , [ ] credentialprovider . LazyAuthConfiguration { grace , ada } , true } ,
2014-09-06 01:13:19 +00:00
// match regardless of sub-path
2016-03-29 18:27:59 +00:00
{ "bar.example.com/pong/pang" , [ ] credentialprovider . LazyAuthConfiguration { grace , ada } , true } ,
2014-09-06 01:13:19 +00:00
// no host match
2016-03-29 18:27:59 +00:00
{ "example.com" , [ ] credentialprovider . LazyAuthConfiguration { } , false } ,
{ "foo.example.com" , [ ] credentialprovider . LazyAuthConfiguration { } , false } ,
2014-09-06 01:13:19 +00:00
}
for i , tt := range tests {
2014-11-15 13:50:59 +00:00
match , ok := dk . Lookup ( tt . image )
2014-09-06 01:13:19 +00:00
if tt . ok != ok {
t . Errorf ( "case %d: expected ok=%t, got %t" , i , tt . ok , ok )
}
if ! reflect . DeepEqual ( tt . match , match ) {
t . Errorf ( "case %d: expected match=%#v, got %#v" , i , tt . match , match )
}
}
}
2014-12-10 20:33:38 +00:00
2015-01-26 22:06:12 +00:00
// This validates that dockercfg entries with a scheme and url path are properly matched
// by images that only match the hostname.
// NOTE: the above covers the case of a more specific match trumping just hostname.
func TestIssue3797 ( t * testing . T ) {
2016-03-29 18:27:59 +00:00
rex := credentialprovider . LazyAuthConfiguration {
2016-04-06 15:06:37 +00:00
AuthConfig : dockertypes . AuthConfig {
2016-03-29 18:27:59 +00:00
Username : "rex" ,
Password : "tiny arms" ,
Email : "rex@example.com" ,
} ,
2015-01-26 22:06:12 +00:00
}
dk := & credentialprovider . BasicDockerKeyring { }
dk . Add ( credentialprovider . DockerConfig {
"https://quay.io/v1/" : credentialprovider . DockerConfigEntry {
Username : rex . Username ,
Password : rex . Password ,
Email : rex . Email ,
} ,
} )
tests := [ ] struct {
image string
2016-03-29 18:27:59 +00:00
match [ ] credentialprovider . LazyAuthConfiguration
2015-01-26 22:06:12 +00:00
ok bool
} {
// direct match
2016-03-29 18:27:59 +00:00
{ "quay.io" , [ ] credentialprovider . LazyAuthConfiguration { rex } , true } ,
2015-01-26 22:06:12 +00:00
// partial matches
2016-03-29 18:27:59 +00:00
{ "quay.io/foo" , [ ] credentialprovider . LazyAuthConfiguration { rex } , true } ,
{ "quay.io/foo/bar" , [ ] credentialprovider . LazyAuthConfiguration { rex } , true } ,
2015-01-26 22:06:12 +00:00
}
for i , tt := range tests {
match , ok := dk . Lookup ( tt . image )
if tt . ok != ok {
t . Errorf ( "case %d: expected ok=%t, got %t" , i , tt . ok , ok )
}
if ! reflect . DeepEqual ( tt . match , match ) {
t . Errorf ( "case %d: expected match=%#v, got %#v" , i , tt . match , match )
}
}
}
2014-12-10 20:33:38 +00:00
type imageTrackingDockerClient struct {
* FakeDockerClient
imageName string
}
2014-12-13 01:43:07 +00:00
2016-04-06 14:15:38 +00:00
func ( f * imageTrackingDockerClient ) InspectImage ( name string ) ( image * dockertypes . ImageInspect , err error ) {
2014-12-10 20:33:38 +00:00
image , err = f . FakeDockerClient . InspectImage ( name )
f . imageName = name
return
}
2014-12-13 01:43:07 +00:00
2014-12-10 20:33:38 +00:00
func TestIsImagePresent ( t * testing . T ) {
2016-04-04 23:01:11 +00:00
cl := & imageTrackingDockerClient { NewFakeDockerClient ( ) , "" }
2014-12-10 20:33:38 +00:00
puller := & dockerPuller {
client : cl ,
}
_ , _ = puller . IsImagePresent ( "abc:123" )
if cl . imageName != "abc:123" {
t . Errorf ( "expected inspection of image abc:123, instead inspected image %v" , cl . imageName )
}
}
2015-02-03 20:14:16 +00:00
2015-04-13 22:25:14 +00:00
type podsByID [ ] * kubecontainer . Pod
func ( b podsByID ) Len ( ) int { return len ( b ) }
func ( b podsByID ) Swap ( i , j int ) { b [ i ] , b [ j ] = b [ j ] , b [ i ] }
func ( b podsByID ) Less ( i , j int ) bool { return b [ i ] . ID < b [ j ] . ID }
type containersByID [ ] * kubecontainer . Container
func ( b containersByID ) Len ( ) int { return len ( b ) }
func ( b containersByID ) Swap ( i , j int ) { b [ i ] , b [ j ] = b [ j ] , b [ i ] }
2015-10-07 17:58:05 +00:00
func ( b containersByID ) Less ( i , j int ) bool { return b [ i ] . ID . ID < b [ j ] . ID . ID }
2015-04-13 22:25:14 +00:00
2015-03-04 01:33:48 +00:00
func TestFindContainersByPod ( t * testing . T ) {
tests := [ ] struct {
2016-04-04 08:56:49 +00:00
runningContainerList [ ] dockertypes . Container
exitedContainerList [ ] dockertypes . Container
all bool
expectedPods [ ] * kubecontainer . Pod
2015-03-04 01:33:48 +00:00
} {
2015-04-13 22:25:14 +00:00
2015-03-04 01:33:48 +00:00
{
2016-04-04 08:56:49 +00:00
[ ] dockertypes . Container {
2015-04-13 22:25:14 +00:00
{
2015-03-04 01:33:48 +00:00
ID : "foobar" ,
2015-04-13 22:25:14 +00:00
Names : [ ] string { "/k8s_foobar.1234_qux_ns_1234_42" } ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
2015-03-04 01:33:48 +00:00
ID : "barbar" ,
2015-04-13 22:25:14 +00:00
Names : [ ] string { "/k8s_barbar.1234_qux_ns_2343_42" } ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
2015-03-04 01:33:48 +00:00
ID : "baz" ,
2015-04-13 22:25:14 +00:00
Names : [ ] string { "/k8s_baz.1234_qux_ns_1234_42" } ,
2015-03-04 01:33:48 +00:00
} ,
} ,
2016-04-04 08:56:49 +00:00
[ ] dockertypes . Container {
2015-04-13 22:25:14 +00:00
{
ID : "barfoo" ,
Names : [ ] string { "/k8s_barfoo.1234_qux_ns_1234_42" } ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
ID : "bazbaz" ,
Names : [ ] string { "/k8s_bazbaz.1234_qux_ns_5678_42" } ,
2015-03-04 01:33:48 +00:00
} ,
} ,
2015-04-13 22:25:14 +00:00
false ,
[ ] * kubecontainer . Pod {
{
ID : "1234" ,
Name : "qux" ,
Namespace : "ns" ,
Containers : [ ] * kubecontainer . Container {
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "foobar" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "foobar" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "baz" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "baz" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
} ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
ID : "2343" ,
Name : "qux" ,
Namespace : "ns" ,
Containers : [ ] * kubecontainer . Container {
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "barbar" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "barbar" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
} ,
2015-03-04 01:33:48 +00:00
} ,
} ,
} ,
{
2016-04-04 08:56:49 +00:00
[ ] dockertypes . Container {
2015-04-13 22:25:14 +00:00
{
2015-03-04 01:33:48 +00:00
ID : "foobar" ,
2015-04-13 22:25:14 +00:00
Names : [ ] string { "/k8s_foobar.1234_qux_ns_1234_42" } ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
2015-03-04 01:33:48 +00:00
ID : "barbar" ,
2015-04-13 22:25:14 +00:00
Names : [ ] string { "/k8s_barbar.1234_qux_ns_2343_42" } ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
2015-03-04 01:33:48 +00:00
ID : "baz" ,
2015-04-13 22:25:14 +00:00
Names : [ ] string { "/k8s_baz.1234_qux_ns_1234_42" } ,
2015-03-04 01:33:48 +00:00
} ,
} ,
2016-04-04 08:56:49 +00:00
[ ] dockertypes . Container {
2015-04-13 22:25:14 +00:00
{
ID : "barfoo" ,
Names : [ ] string { "/k8s_barfoo.1234_qux_ns_1234_42" } ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
ID : "bazbaz" ,
Names : [ ] string { "/k8s_bazbaz.1234_qux_ns_5678_42" } ,
2015-03-04 01:33:48 +00:00
} ,
} ,
2015-04-13 22:25:14 +00:00
true ,
[ ] * kubecontainer . Pod {
{
ID : "1234" ,
Name : "qux" ,
Namespace : "ns" ,
Containers : [ ] * kubecontainer . Container {
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "foobar" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "foobar" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "barfoo" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "barfoo" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "baz" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "baz" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
} ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
ID : "2343" ,
Name : "qux" ,
Namespace : "ns" ,
Containers : [ ] * kubecontainer . Container {
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "barbar" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "barbar" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
} ,
2015-03-04 01:33:48 +00:00
} ,
2015-04-13 22:25:14 +00:00
{
ID : "5678" ,
Name : "qux" ,
Namespace : "ns" ,
Containers : [ ] * kubecontainer . Container {
{
2015-12-24 23:46:56 +00:00
ID : kubecontainer . DockerID ( "bazbaz" ) . ContainerID ( ) ,
2015-12-05 00:06:25 +00:00
Name : "bazbaz" ,
Hash : 0x1234 ,
State : kubecontainer . ContainerStateUnknown ,
2015-04-13 22:25:14 +00:00
} ,
} ,
2015-03-04 01:33:48 +00:00
} ,
} ,
} ,
2015-04-13 22:25:14 +00:00
{
2016-04-04 08:56:49 +00:00
[ ] dockertypes . Container { } ,
[ ] dockertypes . Container { } ,
2015-04-13 22:25:14 +00:00
true ,
nil ,
} ,
2015-03-04 01:33:48 +00:00
}
2016-04-04 23:01:11 +00:00
fakeClient := NewFakeDockerClient ( )
2016-06-09 17:32:28 +00:00
np , _ := network . InitNetworkPlugin ( [ ] network . NetworkPlugin { } , "" , nettest . NewFakeHost ( nil ) , componentconfig . HairpinNone , "10.0.0.0/8" )
2016-02-12 19:33:32 +00:00
// image back-off is set to nil, this test should not pull images
2016-06-20 18:38:37 +00:00
containerManager := NewFakeDockerManager ( fakeClient , & record . FakeRecorder { } , nil , nil , & cadvisorapi . MachineInfo { } , "" , 0 , 0 , "" , & containertest . FakeOS { } , np , nil , nil , nil )
2015-04-13 22:25:14 +00:00
for i , test := range tests {
2016-04-04 08:56:49 +00:00
fakeClient . RunningContainerList = test . runningContainerList
2015-04-13 22:25:14 +00:00
fakeClient . ExitedContainerList = test . exitedContainerList
result , _ := containerManager . GetPods ( test . all )
for i := range result {
sort . Sort ( containersByID ( result [ i ] . Containers ) )
}
for i := range test . expectedPods {
sort . Sort ( containersByID ( test . expectedPods [ i ] . Containers ) )
}
sort . Sort ( podsByID ( result ) )
sort . Sort ( podsByID ( test . expectedPods ) )
if ! reflect . DeepEqual ( test . expectedPods , result ) {
t . Errorf ( "%d: expected: %#v, saw: %#v" , i , test . expectedPods , result )
2015-03-04 01:33:48 +00:00
}
}
}
2015-03-26 18:59:41 +00:00
func TestMakePortsAndBindings ( t * testing . T ) {
2016-04-27 04:53:07 +00:00
portMapping := func ( container , host int , protocol api . Protocol , ip string ) kubecontainer . PortMapping {
return kubecontainer . PortMapping {
ContainerPort : container ,
HostPort : host ,
Protocol : protocol ,
HostIP : ip ,
}
}
portBinding := func ( port , ip string ) dockernat . PortBinding {
return dockernat . PortBinding {
HostPort : port ,
HostIP : ip ,
}
}
2015-05-12 21:49:35 +00:00
ports := [ ] kubecontainer . PortMapping {
2016-04-27 04:53:07 +00:00
portMapping ( 80 , 8080 , "" , "127.0.0.1" ) ,
portMapping ( 443 , 443 , "tcp" , "" ) ,
portMapping ( 444 , 444 , "udp" , "" ) ,
portMapping ( 445 , 445 , "foobar" , "" ) ,
portMapping ( 443 , 446 , "tcp" , "" ) ,
portMapping ( 443 , 446 , "udp" , "" ) ,
2015-03-26 18:59:41 +00:00
}
2015-08-31 12:53:02 +00:00
2015-05-12 21:49:35 +00:00
exposedPorts , bindings := makePortsAndBindings ( ports )
2015-08-31 12:53:02 +00:00
// Count the expected exposed ports and bindings
expectedExposedPorts := map [ string ] struct { } { }
for _ , binding := range ports {
dockerKey := strconv . Itoa ( binding . ContainerPort ) + "/" + string ( binding . Protocol )
expectedExposedPorts [ dockerKey ] = struct { } { }
}
// Should expose right ports in docker
if len ( expectedExposedPorts ) != len ( exposedPorts ) {
2015-05-12 21:49:35 +00:00
t . Errorf ( "Unexpected ports and bindings, %#v %#v %#v" , ports , exposedPorts , bindings )
2015-03-26 18:59:41 +00:00
}
2015-08-31 12:53:02 +00:00
// Construct expected bindings
2016-04-14 17:36:13 +00:00
expectPortBindings := map [ string ] [ ] dockernat . PortBinding {
2015-08-31 12:53:02 +00:00
"80/tcp" : {
2016-04-27 04:53:07 +00:00
portBinding ( "8080" , "127.0.0.1" ) ,
2015-08-31 12:53:02 +00:00
} ,
"443/tcp" : {
2016-04-27 04:53:07 +00:00
portBinding ( "443" , "" ) ,
portBinding ( "446" , "" ) ,
2015-08-31 12:53:02 +00:00
} ,
"443/udp" : {
2016-04-27 04:53:07 +00:00
portBinding ( "446" , "" ) ,
2015-08-31 12:53:02 +00:00
} ,
"444/udp" : {
2016-04-27 04:53:07 +00:00
portBinding ( "444" , "" ) ,
2015-08-31 12:53:02 +00:00
} ,
"445/tcp" : {
2016-04-27 04:53:07 +00:00
portBinding ( "445" , "" ) ,
2015-08-31 12:53:02 +00:00
} ,
}
// interate the bindings by dockerPort, and check its portBindings
for dockerPort , portBindings := range bindings {
switch dockerPort {
case "80/tcp" , "443/tcp" , "443/udp" , "444/udp" , "445/tcp" :
if ! reflect . DeepEqual ( expectPortBindings [ string ( dockerPort ) ] , portBindings ) {
t . Errorf ( "Unexpected portbindings for %#v, expected: %#v, but got: %#v" ,
dockerPort , expectPortBindings [ string ( dockerPort ) ] , portBindings )
2015-03-26 18:59:41 +00:00
}
2015-08-31 12:53:02 +00:00
default :
t . Errorf ( "Unexpected docker port: %#v with portbindings: %#v" , dockerPort , portBindings )
2015-03-26 18:59:41 +00:00
}
}
}
2015-09-01 13:27:01 +00:00
func TestMilliCPUToQuota ( t * testing . T ) {
testCases := [ ] struct {
input int64
quota int64
period int64
} {
{
input : int64 ( 0 ) ,
quota : int64 ( 0 ) ,
period : int64 ( 0 ) ,
} ,
2016-03-17 19:10:04 +00:00
{
input : int64 ( 5 ) ,
quota : int64 ( 1000 ) ,
period : int64 ( 100000 ) ,
} ,
{
input : int64 ( 9 ) ,
quota : int64 ( 1000 ) ,
period : int64 ( 100000 ) ,
} ,
{
input : int64 ( 10 ) ,
quota : int64 ( 1000 ) ,
period : int64 ( 100000 ) ,
} ,
2015-09-01 13:27:01 +00:00
{
input : int64 ( 200 ) ,
quota : int64 ( 20000 ) ,
period : int64 ( 100000 ) ,
} ,
{
input : int64 ( 500 ) ,
quota : int64 ( 50000 ) ,
period : int64 ( 100000 ) ,
} ,
{
input : int64 ( 1000 ) ,
quota : int64 ( 100000 ) ,
period : int64 ( 100000 ) ,
} ,
{
input : int64 ( 1500 ) ,
quota : int64 ( 150000 ) ,
period : int64 ( 100000 ) ,
} ,
}
for _ , testCase := range testCases {
quota , period := milliCPUToQuota ( testCase . input )
if quota != testCase . quota || period != testCase . period {
t . Errorf ( "Input %v, expected quota %v period %v, but got quota %v period %v" , testCase . input , testCase . quota , testCase . period , quota , period )
}
}
}
2016-07-24 21:28:31 +00:00
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func randStringBytes ( n int ) string {
b := make ( [ ] byte , n )
for i := range b {
b [ i ] = letterBytes [ rand . Intn ( len ( letterBytes ) ) ]
}
return string ( b )
}
func TestLogSymLink ( t * testing . T ) {
as := assert . New ( t )
containerLogsDir := "/foo/bar"
podFullName := randStringBytes ( 128 )
containerName := randStringBytes ( 70 )
dockerId := randStringBytes ( 80 )
// The file name cannot exceed 255 characters. Since .log suffix is required, the prefix cannot exceed 251 characters.
expectedPath := path . Join ( containerLogsDir , fmt . Sprintf ( "%s_%s-%s" , podFullName , containerName , dockerId ) [ : 251 ] + ".log" )
as . Equal ( expectedPath , LogSymlink ( containerLogsDir , podFullName , containerName , dockerId ) )
}