github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/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/client" 12 "github.com/docker/docker/internal/test/fixtures/load" 13 "github.com/pkg/errors" 14 ) 15 16 // Execution contains information about the current test execution and daemon 17 // under test 18 type Execution struct { 19 client client.APIClient 20 DaemonInfo types.Info 21 OSType string 22 PlatformDefaults PlatformDefaults 23 protectedElements protectedElements 24 } 25 26 // PlatformDefaults are defaults values for the platform of the daemon under test 27 type PlatformDefaults struct { 28 BaseImage string 29 VolumesConfigPath string 30 ContainerStoragePath string 31 } 32 33 // New creates a new Execution struct 34 func New() (*Execution, error) { 35 client, err := client.NewClientWithOpts(client.FromEnv) 36 if err != nil { 37 return nil, errors.Wrapf(err, "failed to create client") 38 } 39 40 info, err := client.Info(context.Background()) 41 if err != nil { 42 return nil, errors.Wrapf(err, "failed to get info from daemon") 43 } 44 45 osType := getOSType(info) 46 47 return &Execution{ 48 client: client, 49 DaemonInfo: info, 50 OSType: osType, 51 PlatformDefaults: getPlatformDefaults(info, osType), 52 protectedElements: newProtectedElements(), 53 }, nil 54 } 55 56 func getOSType(info types.Info) string { 57 // Docker EE does not set the OSType so allow the user to override this value. 58 userOsType := os.Getenv("TEST_OSTYPE") 59 if userOsType != "" { 60 return userOsType 61 } 62 return info.OSType 63 } 64 65 func getPlatformDefaults(info types.Info, osType string) PlatformDefaults { 66 volumesPath := filepath.Join(info.DockerRootDir, "volumes") 67 containersPath := filepath.Join(info.DockerRootDir, "containers") 68 69 switch osType { 70 case "linux": 71 return PlatformDefaults{ 72 BaseImage: "scratch", 73 VolumesConfigPath: toSlash(volumesPath), 74 ContainerStoragePath: toSlash(containersPath), 75 } 76 case "windows": 77 baseImage := "microsoft/windowsservercore" 78 if overrideBaseImage := os.Getenv("WINDOWS_BASE_IMAGE"); overrideBaseImage != "" { 79 baseImage = overrideBaseImage 80 if overrideBaseImageTag := os.Getenv("WINDOWS_BASE_IMAGE_TAG"); overrideBaseImageTag != "" { 81 baseImage = baseImage + ":" + overrideBaseImageTag 82 } 83 } 84 fmt.Println("INFO: Windows Base image is ", baseImage) 85 return PlatformDefaults{ 86 BaseImage: baseImage, 87 VolumesConfigPath: filepath.FromSlash(volumesPath), 88 ContainerStoragePath: filepath.FromSlash(containersPath), 89 } 90 default: 91 panic(fmt.Sprintf("unknown OSType for daemon: %s", osType)) 92 } 93 } 94 95 // Make sure in context of daemon, not the local platform. Note we can't 96 // use filepath.FromSlash or ToSlash here as they are a no-op on Unix. 97 func toSlash(path string) string { 98 return strings.Replace(path, `\`, `/`, -1) 99 } 100 101 // IsLocalDaemon is true if the daemon under test is on the same 102 // host as the test process. 103 // 104 // Deterministically working out the environment in which CI is running 105 // to evaluate whether the daemon is local or remote is not possible through 106 // a build tag. 107 // 108 // For example Windows to Linux CI under Jenkins tests the 64-bit 109 // Windows binary build with the daemon build tag, but calls a remote 110 // Linux daemon. 111 // 112 // We can't just say if Windows then assume the daemon is local as at 113 // some point, we will be testing the Windows CLI against a Windows daemon. 114 // 115 // Similarly, it will be perfectly valid to also run CLI tests from 116 // a Linux CLI (built with the daemon tag) against a Windows daemon. 117 func (e *Execution) IsLocalDaemon() bool { 118 return os.Getenv("DOCKER_REMOTE_DAEMON") == "" 119 } 120 121 // IsRemoteDaemon is true if the daemon under test is on different host 122 // as the test process. 123 func (e *Execution) IsRemoteDaemon() bool { 124 return !e.IsLocalDaemon() 125 } 126 127 // DaemonAPIVersion returns the negotiated daemon api version 128 func (e *Execution) DaemonAPIVersion() string { 129 version, err := e.APIClient().ServerVersion(context.TODO()) 130 if err != nil { 131 return "" 132 } 133 return version.APIVersion 134 } 135 136 // Print the execution details to stdout 137 // TODO: print everything 138 func (e *Execution) Print() { 139 if e.IsLocalDaemon() { 140 fmt.Println("INFO: Testing against a local daemon") 141 } else { 142 fmt.Println("INFO: Testing against a remote daemon") 143 } 144 } 145 146 // APIClient returns an APIClient connected to the daemon under test 147 func (e *Execution) APIClient() client.APIClient { 148 return e.client 149 } 150 151 // IsUserNamespace returns whether the user namespace remapping is enabled 152 func (e *Execution) IsUserNamespace() bool { 153 root := os.Getenv("DOCKER_REMAP_ROOT") 154 return root != "" 155 } 156 157 // EnsureFrozenImagesLinux loads frozen test images into the daemon 158 // if they aren't already loaded 159 func EnsureFrozenImagesLinux(testEnv *Execution) error { 160 if testEnv.OSType == "linux" { 161 err := load.FrozenImagesLinux(testEnv.APIClient(), frozenImages...) 162 if err != nil { 163 return errors.Wrap(err, "error loading frozen images") 164 } 165 } 166 return nil 167 }