environment.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package environment
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "github.com/docker/docker/api/types"
  8. "github.com/docker/docker/client"
  9. "github.com/pkg/errors"
  10. "golang.org/x/net/context"
  11. )
  12. // Execution contains information about the current test execution and daemon
  13. // under test
  14. type Execution struct {
  15. client client.APIClient
  16. DaemonInfo types.Info
  17. OSType string
  18. PlatformDefaults PlatformDefaults
  19. protectedElements protectedElements
  20. }
  21. // PlatformDefaults are defaults values for the platform of the daemon under test
  22. type PlatformDefaults struct {
  23. BaseImage string
  24. VolumesConfigPath string
  25. ContainerStoragePath string
  26. }
  27. // New creates a new Execution struct
  28. func New() (*Execution, error) {
  29. client, err := client.NewEnvClient()
  30. if err != nil {
  31. return nil, errors.Wrapf(err, "failed to create client")
  32. }
  33. info, err := client.Info(context.Background())
  34. if err != nil {
  35. return nil, errors.Wrapf(err, "failed to get info from daemon")
  36. }
  37. osType := getOSType(info)
  38. return &Execution{
  39. client: client,
  40. DaemonInfo: info,
  41. OSType: osType,
  42. PlatformDefaults: getPlatformDefaults(info, osType),
  43. protectedElements: newProtectedElements(),
  44. }, nil
  45. }
  46. func getOSType(info types.Info) string {
  47. // Docker EE does not set the OSType so allow the user to override this value.
  48. userOsType := os.Getenv("TEST_OSTYPE")
  49. if userOsType != "" {
  50. return userOsType
  51. }
  52. return info.OSType
  53. }
  54. func getPlatformDefaults(info types.Info, osType string) PlatformDefaults {
  55. volumesPath := filepath.Join(info.DockerRootDir, "volumes")
  56. containersPath := filepath.Join(info.DockerRootDir, "containers")
  57. switch osType {
  58. case "linux":
  59. return PlatformDefaults{
  60. BaseImage: "scratch",
  61. VolumesConfigPath: toSlash(volumesPath),
  62. ContainerStoragePath: toSlash(containersPath),
  63. }
  64. case "windows":
  65. baseImage := "microsoft/windowsservercore"
  66. if override := os.Getenv("WINDOWS_BASE_IMAGE"); override != "" {
  67. baseImage = override
  68. fmt.Println("INFO: Windows Base image is ", baseImage)
  69. }
  70. return PlatformDefaults{
  71. BaseImage: baseImage,
  72. VolumesConfigPath: filepath.FromSlash(volumesPath),
  73. ContainerStoragePath: filepath.FromSlash(containersPath),
  74. }
  75. default:
  76. panic(fmt.Sprintf("unknown OSType for daemon: %s", osType))
  77. }
  78. }
  79. // Make sure in context of daemon, not the local platform. Note we can't
  80. // use filepath.FromSlash or ToSlash here as they are a no-op on Unix.
  81. func toSlash(path string) string {
  82. return strings.Replace(path, `\`, `/`, -1)
  83. }
  84. // IsLocalDaemon is true if the daemon under test is on the same
  85. // host as the CLI.
  86. //
  87. // Deterministically working out the environment in which CI is running
  88. // to evaluate whether the daemon is local or remote is not possible through
  89. // a build tag.
  90. //
  91. // For example Windows to Linux CI under Jenkins tests the 64-bit
  92. // Windows binary build with the daemon build tag, but calls a remote
  93. // Linux daemon.
  94. //
  95. // We can't just say if Windows then assume the daemon is local as at
  96. // some point, we will be testing the Windows CLI against a Windows daemon.
  97. //
  98. // Similarly, it will be perfectly valid to also run CLI tests from
  99. // a Linux CLI (built with the daemon tag) against a Windows daemon.
  100. func (e *Execution) IsLocalDaemon() bool {
  101. return os.Getenv("DOCKER_REMOTE_DAEMON") == ""
  102. }
  103. // Print the execution details to stdout
  104. // TODO: print everything
  105. func (e *Execution) Print() {
  106. if e.IsLocalDaemon() {
  107. fmt.Println("INFO: Testing against a local daemon")
  108. } else {
  109. fmt.Println("INFO: Testing against a remote daemon")
  110. }
  111. }
  112. // APIClient returns an APIClient connected to the daemon under test
  113. func (e *Execution) APIClient() client.APIClient {
  114. return e.client
  115. }