github.com/tilt-dev/tilt@v0.36.0/internal/docker/client_test.go (about) 1 package docker 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "testing" 8 9 "github.com/docker/docker/api/types" 10 "github.com/stretchr/testify/assert" 11 12 "github.com/tilt-dev/clusterid" 13 "github.com/tilt-dev/tilt/internal/container" 14 "github.com/tilt-dev/tilt/internal/k8s" 15 ) 16 17 type buildkitTestCase struct { 18 v types.Version 19 env Env 20 expected bool 21 } 22 23 func TestSupportsBuildkit(t *testing.T) { 24 cases := []buildkitTestCase{ 25 {types.Version{APIVersion: "1.37", Experimental: true}, Env{}, false}, 26 {types.Version{APIVersion: "1.37", Experimental: false}, Env{}, false}, 27 {types.Version{APIVersion: "1.38", Experimental: true}, Env{}, true}, 28 {types.Version{APIVersion: "1.38", Experimental: false}, Env{}, false}, 29 {types.Version{APIVersion: "1.39", Experimental: true}, Env{}, true}, 30 {types.Version{APIVersion: "1.39", Experimental: false}, Env{}, true}, 31 {types.Version{APIVersion: "1.40", Experimental: true}, Env{}, true}, 32 {types.Version{APIVersion: "1.40", Experimental: false}, Env{}, true}, 33 {types.Version{APIVersion: "garbage", Experimental: false}, Env{}, false}, 34 {types.Version{APIVersion: "1.39", Experimental: true}, Env{IsOldMinikube: true}, false}, 35 } 36 37 for i, c := range cases { 38 t.Run(fmt.Sprintf("Case%d", i), func(t *testing.T) { 39 assert.Equal(t, c.expected, SupportsBuildkit(c.v, c.env)) 40 }) 41 } 42 } 43 44 type builderVersionTestCase struct { 45 v string 46 bkEnv string 47 expected types.BuilderVersion 48 } 49 50 func TestProvideBuilderVersion(t *testing.T) { 51 cases := []builderVersionTestCase{ 52 {"1.37", "", types.BuilderV1}, 53 {"1.37", "0", types.BuilderV1}, 54 {"1.37", "1", types.BuilderV1}, 55 {"1.40", "", types.BuilderBuildKit}, 56 {"1.40", "0", types.BuilderV1}, 57 {"1.40", "1", types.BuilderBuildKit}, 58 } 59 60 for i, c := range cases { 61 t.Run(fmt.Sprintf("Case%d", i), func(t *testing.T) { 62 t.Setenv("DOCKER_BUILDKIT", c.bkEnv) 63 64 v, err := getDockerBuilderVersion( 65 types.Version{APIVersion: c.v}, Env{}) 66 assert.NoError(t, err) 67 assert.Equal(t, c.expected, v) 68 }) 69 } 70 } 71 72 type versionTestCase struct { 73 v types.Version 74 expected bool 75 } 76 77 func TestSupported(t *testing.T) { 78 cases := []versionTestCase{ 79 {types.Version{APIVersion: "1.22"}, false}, 80 {types.Version{APIVersion: "1.23"}, true}, 81 {types.Version{APIVersion: "1.39"}, true}, 82 {types.Version{APIVersion: "1.40"}, true}, 83 {types.Version{APIVersion: "garbage"}, false}, 84 } 85 86 for i, c := range cases { 87 t.Run(fmt.Sprintf("Case%d", i), func(t *testing.T) { 88 assert.Equal(t, c.expected, SupportedVersion(c.v)) 89 }) 90 } 91 } 92 93 type provideEnvTestCase struct { 94 env clusterid.Product 95 runtime container.Runtime 96 minikubeV string 97 osEnv map[string]string 98 mkEnv map[string]string 99 expectedCluster Env 100 expectedLocal Env 101 } 102 103 type hostClient struct { 104 Host string 105 } 106 107 func (c hostClient) DaemonHost() string { return c.Host } 108 109 type fakeClientCreator struct { 110 } 111 112 func (c fakeClientCreator) FromCLI(ctx context.Context) (DaemonClient, error) { 113 host := os.Getenv("DOCKER_HOST") 114 if host == "" { 115 host = "unix:///var/run/docker.sock" 116 } 117 return hostClient{Host: host}, nil 118 } 119 func (c fakeClientCreator) FromEnvMap(envMap map[string]string) (DaemonClient, error) { 120 host := envMap["DOCKER_HOST"] 121 return hostClient{Host: host}, nil 122 } 123 124 func TestProvideClusterProduct(t *testing.T) { 125 envVars := []string{ 126 "DOCKER_TLS_VERIFY", 127 "DOCKER_HOST", 128 "DOCKER_CERT_PATH", 129 "DOCKER_API_VERSION", 130 } 131 132 cases := []provideEnvTestCase{ 133 { 134 expectedCluster: Env{ 135 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 136 }, 137 expectedLocal: Env{ 138 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 139 }, 140 }, 141 { 142 env: clusterid.ProductUnknown, 143 osEnv: map[string]string{ 144 "DOCKER_HOST": "tcp://192.168.99.100:2376", 145 }, 146 expectedCluster: Env{ 147 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 148 }, 149 expectedLocal: Env{ 150 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 151 }, 152 }, 153 { 154 env: clusterid.ProductMicroK8s, 155 runtime: container.RuntimeCrio, 156 expectedCluster: Env{ 157 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 158 }, 159 expectedLocal: Env{ 160 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 161 }, 162 }, 163 { 164 env: clusterid.ProductMinikube, 165 runtime: container.RuntimeDocker, 166 mkEnv: map[string]string{ 167 "DOCKER_TLS_VERIFY": "1", 168 "DOCKER_HOST": "tcp://192.168.99.100:2376", 169 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 170 "DOCKER_API_VERSION": "1.35", 171 }, 172 expectedCluster: Env{ 173 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 174 Environ: []string{ 175 "DOCKER_API_VERSION=1.35", 176 "DOCKER_CERT_PATH=/home/nick/.minikube/certs", 177 "DOCKER_HOST=tcp://192.168.99.100:2376", 178 "DOCKER_TLS_VERIFY=1", 179 }, 180 IsOldMinikube: true, 181 BuildToKubeContexts: []string{"minikube-me"}, 182 }, 183 expectedLocal: Env{ 184 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 185 }, 186 }, 187 { 188 env: clusterid.ProductMinikube, 189 runtime: container.RuntimeDocker, 190 minikubeV: "1.8.2", 191 mkEnv: map[string]string{ 192 "DOCKER_TLS_VERIFY": "1", 193 "DOCKER_HOST": "tcp://192.168.99.100:2376", 194 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 195 "DOCKER_API_VERSION": "1.35", 196 }, 197 expectedCluster: Env{ 198 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 199 Environ: []string{ 200 "DOCKER_API_VERSION=1.35", 201 "DOCKER_CERT_PATH=/home/nick/.minikube/certs", 202 "DOCKER_HOST=tcp://192.168.99.100:2376", 203 "DOCKER_TLS_VERIFY=1", 204 }, 205 BuildToKubeContexts: []string{"minikube-me"}, 206 }, 207 expectedLocal: Env{ 208 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 209 }, 210 }, 211 { 212 env: clusterid.ProductMinikube, 213 runtime: container.RuntimeDocker, 214 mkEnv: map[string]string{ 215 "DOCKER_TLS_VERIFY": "1", 216 "DOCKER_HOST": "tcp://192.168.99.100:2376", 217 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 218 "DOCKER_API_VERSION": "1.35", 219 }, 220 osEnv: map[string]string{ 221 "DOCKER_HOST": "tcp://registry.local:80", 222 }, 223 expectedCluster: Env{ 224 Client: hostClient{Host: "tcp://registry.local:80"}, 225 }, 226 expectedLocal: Env{ 227 Client: hostClient{Host: "tcp://registry.local:80"}, 228 }, 229 }, 230 { 231 // Test the case where the user has already run 232 // eval $(minikube docker-env) 233 env: clusterid.ProductMinikube, 234 runtime: container.RuntimeDocker, 235 mkEnv: map[string]string{ 236 "DOCKER_TLS_VERIFY": "1", 237 "DOCKER_HOST": "tcp://192.168.99.100:2376", 238 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 239 }, 240 osEnv: map[string]string{ 241 "DOCKER_TLS_VERIFY": "1", 242 "DOCKER_HOST": "tcp://192.168.99.100:2376", 243 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 244 }, 245 expectedCluster: Env{ 246 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 247 Environ: []string{"DOCKER_CERT_PATH=/home/nick/.minikube/certs", "DOCKER_HOST=tcp://192.168.99.100:2376", "DOCKER_TLS_VERIFY=1"}, 248 IsOldMinikube: true, 249 BuildToKubeContexts: []string{"minikube-me"}, 250 }, 251 expectedLocal: Env{ 252 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 253 Environ: []string{"DOCKER_CERT_PATH=/home/nick/.minikube/certs", "DOCKER_HOST=tcp://192.168.99.100:2376", "DOCKER_TLS_VERIFY=1"}, 254 IsOldMinikube: true, 255 BuildToKubeContexts: []string{"minikube-me"}, 256 }, 257 }, 258 { 259 env: clusterid.ProductMinikube, 260 runtime: container.RuntimeCrio, 261 mkEnv: map[string]string{ 262 "DOCKER_TLS_VERIFY": "1", 263 "DOCKER_HOST": "tcp://192.168.99.100:2376", 264 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 265 "DOCKER_API_VERSION": "1.35", 266 }, 267 expectedCluster: Env{ 268 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 269 }, 270 expectedLocal: Env{ 271 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 272 }, 273 }, 274 { 275 env: clusterid.ProductUnknown, 276 osEnv: map[string]string{ 277 "DOCKER_TLS_VERIFY": "1", 278 "DOCKER_HOST": "localhost:2376", 279 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 280 "DOCKER_API_VERSION": "1.35", 281 }, 282 expectedCluster: Env{ 283 Client: hostClient{Host: "localhost:2376"}, 284 }, 285 expectedLocal: Env{ 286 Client: hostClient{Host: "localhost:2376"}, 287 }, 288 }, 289 { 290 env: clusterid.ProductDockerDesktop, 291 runtime: container.RuntimeDocker, 292 expectedCluster: Env{ 293 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 294 BuildToKubeContexts: []string{"docker-desktop-me"}, 295 }, 296 expectedLocal: Env{ 297 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 298 BuildToKubeContexts: []string{"docker-desktop-me", "docker-desktop-me"}, 299 }, 300 }, 301 { 302 env: clusterid.ProductDockerDesktop, 303 runtime: container.RuntimeDocker, 304 // Set DOCKER_HOST here to mimic docker client discovering socket from desktop-linux context 305 osEnv: map[string]string{ 306 "DOCKER_HOST": "unix:///home/tilt/.docker/desktop/docker.sock", 307 }, 308 expectedCluster: Env{ 309 Client: hostClient{Host: "unix:///home/tilt/.docker/desktop/docker.sock"}, 310 BuildToKubeContexts: []string{"docker-desktop-me"}, 311 }, 312 expectedLocal: Env{ 313 Client: hostClient{Host: "unix:///home/tilt/.docker/desktop/docker.sock"}, 314 BuildToKubeContexts: []string{"docker-desktop-me", "docker-desktop-me"}, 315 }, 316 }, 317 { 318 env: clusterid.ProductDockerDesktop, 319 runtime: container.RuntimeDocker, 320 osEnv: map[string]string{ 321 "DOCKER_HOST": "unix:///home/tilt/.docker/run/docker.sock", 322 }, 323 expectedCluster: Env{ 324 Client: hostClient{Host: "unix:///home/tilt/.docker/run/docker.sock"}, 325 BuildToKubeContexts: []string{"docker-desktop-me"}, 326 }, 327 expectedLocal: Env{ 328 Client: hostClient{Host: "unix:///home/tilt/.docker/run/docker.sock"}, 329 BuildToKubeContexts: []string{"docker-desktop-me", "docker-desktop-me"}, 330 }, 331 }, 332 { 333 env: clusterid.ProductRancherDesktop, 334 runtime: container.RuntimeDocker, 335 expectedCluster: Env{ 336 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 337 BuildToKubeContexts: []string{"rancher-desktop-me"}, 338 }, 339 expectedLocal: Env{ 340 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 341 BuildToKubeContexts: []string{"rancher-desktop-me"}, 342 }, 343 }, 344 { 345 env: clusterid.ProductRancherDesktop, 346 runtime: container.RuntimeContainerd, 347 expectedCluster: Env{ 348 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 349 }, 350 expectedLocal: Env{ 351 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 352 }, 353 }, 354 { 355 env: clusterid.ProductRancherDesktop, 356 runtime: container.RuntimeDocker, 357 // Set DOCKER_HOST here to mimic rancher-desktop docker context in non-admin mode 358 osEnv: map[string]string{ 359 "DOCKER_HOST": "unix:///Users/tilt/.rd/docker.sock", 360 }, 361 expectedCluster: Env{ 362 Client: hostClient{Host: "unix:///Users/tilt/.rd/docker.sock"}, 363 BuildToKubeContexts: []string{"rancher-desktop-me"}, 364 }, 365 expectedLocal: Env{ 366 Client: hostClient{Host: "unix:///Users/tilt/.rd/docker.sock"}, 367 BuildToKubeContexts: []string{"rancher-desktop-me"}, 368 }, 369 }, 370 } 371 372 for i, c := range cases { 373 t.Run(fmt.Sprintf("Case%d", i), func(t *testing.T) { 374 for _, k := range envVars { 375 t.Setenv(k, c.osEnv[k]) 376 } 377 378 minikubeV := c.minikubeV 379 if minikubeV == "" { 380 minikubeV = "1.3.0" // an Old version 381 } 382 383 mkClient := k8s.FakeMinikube{DockerEnvMap: c.mkEnv, FakeVersion: minikubeV} 384 kubeContext := k8s.KubeContext(fmt.Sprintf("%s-me", c.env)) 385 kCli := k8s.NewFakeK8sClient(t) 386 kCli.Runtime = c.runtime 387 cluster := ProvideClusterEnv(context.Background(), fakeClientCreator{}, kubeContext, c.env, kCli, mkClient) 388 assert.Equal(t, c.expectedCluster, Env(cluster)) 389 390 local := ProvideLocalEnv(context.Background(), fakeClientCreator{}, kubeContext, c.env, cluster) 391 assert.Equal(t, c.expectedLocal, Env(local)) 392 }) 393 } 394 }