github.com/devdivbcp/moby@v17.12.0-ce-rc1.0.20200726071732-2d4bfdc789ad+incompatible/internal/test/environment/environment.go (about) 1 package environment // import "github.com/docker/docker/internal/test/environment" 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/api/types/filters" 12 "github.com/docker/docker/client" 13 "github.com/docker/docker/internal/test" 14 "github.com/docker/docker/internal/test/fixtures/load" 15 "github.com/pkg/errors" 16 "gotest.tools/assert" 17 ) 18 19 // Execution contains information about the current test execution and daemon 20 // under test 21 type Execution struct { 22 client client.APIClient 23 DaemonInfo types.Info 24 OSType string 25 PlatformDefaults PlatformDefaults 26 protectedElements protectedElements 27 } 28 29 // PlatformDefaults are defaults values for the platform of the daemon under test 30 type PlatformDefaults struct { 31 BaseImage string 32 VolumesConfigPath string 33 ContainerStoragePath string 34 } 35 36 // New creates a new Execution struct 37 // This is configured useing the env client (see client.FromEnv) 38 func New() (*Execution, error) { 39 c, err := client.NewClientWithOpts(client.FromEnv) 40 if err != nil { 41 return nil, errors.Wrapf(err, "failed to create client") 42 } 43 return FromClient(c) 44 } 45 46 // FromClient creates a new Execution environment from the passed in client 47 func FromClient(c *client.Client) (*Execution, error) { 48 info, err := c.Info(context.Background()) 49 if err != nil { 50 return nil, errors.Wrapf(err, "failed to get info from daemon") 51 } 52 53 osType := getOSType(info) 54 55 return &Execution{ 56 client: c, 57 DaemonInfo: info, 58 OSType: osType, 59 PlatformDefaults: getPlatformDefaults(info, osType), 60 protectedElements: newProtectedElements(), 61 }, nil 62 } 63 64 func getOSType(info types.Info) string { 65 // Docker EE does not set the OSType so allow the user to override this value. 66 userOsType := os.Getenv("TEST_OSTYPE") 67 if userOsType != "" { 68 return userOsType 69 } 70 return info.OSType 71 } 72 73 func getPlatformDefaults(info types.Info, osType string) PlatformDefaults { 74 volumesPath := filepath.Join(info.DockerRootDir, "volumes") 75 containersPath := filepath.Join(info.DockerRootDir, "containers") 76 77 switch osType { 78 case "linux": 79 return PlatformDefaults{ 80 BaseImage: "scratch", 81 VolumesConfigPath: toSlash(volumesPath), 82 ContainerStoragePath: toSlash(containersPath), 83 } 84 case "windows": 85 baseImage := "microsoft/windowsservercore" 86 if overrideBaseImage := os.Getenv("WINDOWS_BASE_IMAGE"); overrideBaseImage != "" { 87 baseImage = overrideBaseImage 88 if overrideBaseImageTag := os.Getenv("WINDOWS_BASE_IMAGE_TAG"); overrideBaseImageTag != "" { 89 baseImage = baseImage + ":" + overrideBaseImageTag 90 } 91 } 92 fmt.Println("INFO: Windows Base image is ", baseImage) 93 return PlatformDefaults{ 94 BaseImage: baseImage, 95 VolumesConfigPath: filepath.FromSlash(volumesPath), 96 ContainerStoragePath: filepath.FromSlash(containersPath), 97 } 98 default: 99 panic(fmt.Sprintf("unknown OSType for daemon: %s", osType)) 100 } 101 } 102 103 // Make sure in context of daemon, not the local platform. Note we can't 104 // use filepath.FromSlash or ToSlash here as they are a no-op on Unix. 105 func toSlash(path string) string { 106 return strings.Replace(path, `\`, `/`, -1) 107 } 108 109 // IsLocalDaemon is true if the daemon under test is on the same 110 // host as the test process. 111 // 112 // Deterministically working out the environment in which CI is running 113 // to evaluate whether the daemon is local or remote is not possible through 114 // a build tag. 115 // 116 // For example Windows to Linux CI under Jenkins tests the 64-bit 117 // Windows binary build with the daemon build tag, but calls a remote 118 // Linux daemon. 119 // 120 // We can't just say if Windows then assume the daemon is local as at 121 // some point, we will be testing the Windows CLI against a Windows daemon. 122 // 123 // Similarly, it will be perfectly valid to also run CLI tests from 124 // a Linux CLI (built with the daemon tag) against a Windows daemon. 125 func (e *Execution) IsLocalDaemon() bool { 126 return os.Getenv("DOCKER_REMOTE_DAEMON") == "" 127 } 128 129 // IsRemoteDaemon is true if the daemon under test is on different host 130 // as the test process. 131 func (e *Execution) IsRemoteDaemon() bool { 132 return !e.IsLocalDaemon() 133 } 134 135 // DaemonAPIVersion returns the negotiated daemon api version 136 func (e *Execution) DaemonAPIVersion() string { 137 version, err := e.APIClient().ServerVersion(context.TODO()) 138 if err != nil { 139 return "" 140 } 141 return version.APIVersion 142 } 143 144 // Print the execution details to stdout 145 // TODO: print everything 146 func (e *Execution) Print() { 147 if e.IsLocalDaemon() { 148 fmt.Println("INFO: Testing against a local daemon") 149 } else { 150 fmt.Println("INFO: Testing against a remote daemon") 151 } 152 } 153 154 // APIClient returns an APIClient connected to the daemon under test 155 func (e *Execution) APIClient() client.APIClient { 156 return e.client 157 } 158 159 // IsUserNamespace returns whether the user namespace remapping is enabled 160 func (e *Execution) IsUserNamespace() bool { 161 root := os.Getenv("DOCKER_REMAP_ROOT") 162 return root != "" 163 } 164 165 // HasExistingImage checks whether there is an image with the given reference. 166 // Note that this is done by filtering and then checking whether there were any 167 // results -- so ambiguous references might result in false-positives. 168 func (e *Execution) HasExistingImage(t assert.TestingT, reference string) bool { 169 if ht, ok := t.(test.HelperT); ok { 170 ht.Helper() 171 } 172 client := e.APIClient() 173 filter := filters.NewArgs() 174 filter.Add("dangling", "false") 175 filter.Add("reference", reference) 176 imageList, err := client.ImageList(context.Background(), types.ImageListOptions{ 177 All: true, 178 Filters: filter, 179 }) 180 assert.NilError(t, err, "failed to list images") 181 182 return len(imageList) > 0 183 } 184 185 // EnsureFrozenImagesLinux loads frozen test images into the daemon 186 // if they aren't already loaded 187 func EnsureFrozenImagesLinux(testEnv *Execution) error { 188 if testEnv.OSType == "linux" { 189 err := load.FrozenImagesLinux(testEnv.APIClient(), frozenImages...) 190 if err != nil { 191 return errors.Wrap(err, "error loading frozen images") 192 } 193 } 194 return nil 195 }