github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/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.RuntimeDocker, 156 expectedCluster: Env{ 157 Client: hostClient{Host: "unix:///var/snap/microk8s/current/docker.sock"}, 158 Environ: []string{"DOCKER_HOST=unix:///var/snap/microk8s/current/docker.sock"}, 159 BuildToKubeContexts: []string{"microk8s-me"}, 160 }, 161 expectedLocal: Env{ 162 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 163 }, 164 }, 165 { 166 env: clusterid.ProductMicroK8s, 167 runtime: container.RuntimeCrio, 168 expectedCluster: Env{ 169 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 170 }, 171 expectedLocal: Env{ 172 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 173 }, 174 }, 175 { 176 env: clusterid.ProductMinikube, 177 runtime: container.RuntimeDocker, 178 mkEnv: map[string]string{ 179 "DOCKER_TLS_VERIFY": "1", 180 "DOCKER_HOST": "tcp://192.168.99.100:2376", 181 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 182 "DOCKER_API_VERSION": "1.35", 183 }, 184 expectedCluster: Env{ 185 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 186 Environ: []string{ 187 "DOCKER_API_VERSION=1.35", 188 "DOCKER_CERT_PATH=/home/nick/.minikube/certs", 189 "DOCKER_HOST=tcp://192.168.99.100:2376", 190 "DOCKER_TLS_VERIFY=1", 191 }, 192 IsOldMinikube: true, 193 BuildToKubeContexts: []string{"minikube-me"}, 194 }, 195 expectedLocal: Env{ 196 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 197 }, 198 }, 199 { 200 env: clusterid.ProductMinikube, 201 runtime: container.RuntimeDocker, 202 minikubeV: "1.8.2", 203 mkEnv: map[string]string{ 204 "DOCKER_TLS_VERIFY": "1", 205 "DOCKER_HOST": "tcp://192.168.99.100:2376", 206 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 207 "DOCKER_API_VERSION": "1.35", 208 }, 209 expectedCluster: Env{ 210 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 211 Environ: []string{ 212 "DOCKER_API_VERSION=1.35", 213 "DOCKER_CERT_PATH=/home/nick/.minikube/certs", 214 "DOCKER_HOST=tcp://192.168.99.100:2376", 215 "DOCKER_TLS_VERIFY=1", 216 }, 217 BuildToKubeContexts: []string{"minikube-me"}, 218 }, 219 expectedLocal: Env{ 220 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 221 }, 222 }, 223 { 224 env: clusterid.ProductMinikube, 225 runtime: container.RuntimeDocker, 226 mkEnv: map[string]string{ 227 "DOCKER_TLS_VERIFY": "1", 228 "DOCKER_HOST": "tcp://192.168.99.100:2376", 229 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 230 "DOCKER_API_VERSION": "1.35", 231 }, 232 osEnv: map[string]string{ 233 "DOCKER_HOST": "tcp://registry.local:80", 234 }, 235 expectedCluster: Env{ 236 Client: hostClient{Host: "tcp://registry.local:80"}, 237 }, 238 expectedLocal: Env{ 239 Client: hostClient{Host: "tcp://registry.local:80"}, 240 }, 241 }, 242 { 243 // Test the case where the user has already run 244 // eval $(minikube docker-env) 245 env: clusterid.ProductMinikube, 246 runtime: container.RuntimeDocker, 247 mkEnv: map[string]string{ 248 "DOCKER_TLS_VERIFY": "1", 249 "DOCKER_HOST": "tcp://192.168.99.100:2376", 250 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 251 }, 252 osEnv: map[string]string{ 253 "DOCKER_TLS_VERIFY": "1", 254 "DOCKER_HOST": "tcp://192.168.99.100:2376", 255 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 256 }, 257 expectedCluster: Env{ 258 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 259 Environ: []string{"DOCKER_CERT_PATH=/home/nick/.minikube/certs", "DOCKER_HOST=tcp://192.168.99.100:2376", "DOCKER_TLS_VERIFY=1"}, 260 IsOldMinikube: true, 261 BuildToKubeContexts: []string{"minikube-me"}, 262 }, 263 expectedLocal: Env{ 264 Client: hostClient{Host: "tcp://192.168.99.100:2376"}, 265 Environ: []string{"DOCKER_CERT_PATH=/home/nick/.minikube/certs", "DOCKER_HOST=tcp://192.168.99.100:2376", "DOCKER_TLS_VERIFY=1"}, 266 IsOldMinikube: true, 267 BuildToKubeContexts: []string{"minikube-me"}, 268 }, 269 }, 270 { 271 env: clusterid.ProductMinikube, 272 runtime: container.RuntimeCrio, 273 mkEnv: map[string]string{ 274 "DOCKER_TLS_VERIFY": "1", 275 "DOCKER_HOST": "tcp://192.168.99.100:2376", 276 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 277 "DOCKER_API_VERSION": "1.35", 278 }, 279 expectedCluster: Env{ 280 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 281 }, 282 expectedLocal: Env{ 283 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 284 }, 285 }, 286 { 287 env: clusterid.ProductUnknown, 288 osEnv: map[string]string{ 289 "DOCKER_TLS_VERIFY": "1", 290 "DOCKER_HOST": "localhost:2376", 291 "DOCKER_CERT_PATH": "/home/nick/.minikube/certs", 292 "DOCKER_API_VERSION": "1.35", 293 }, 294 expectedCluster: Env{ 295 Client: hostClient{Host: "localhost:2376"}, 296 }, 297 expectedLocal: Env{ 298 Client: hostClient{Host: "localhost:2376"}, 299 }, 300 }, 301 { 302 env: clusterid.ProductDockerDesktop, 303 runtime: container.RuntimeDocker, 304 expectedCluster: Env{ 305 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 306 BuildToKubeContexts: []string{"docker-desktop-me"}, 307 }, 308 expectedLocal: Env{ 309 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 310 BuildToKubeContexts: []string{"docker-desktop-me", "docker-desktop-me"}, 311 }, 312 }, 313 { 314 env: clusterid.ProductDockerDesktop, 315 runtime: container.RuntimeDocker, 316 // Set DOCKER_HOST here to mimic docker client discovering socket from desktop-linux context 317 osEnv: map[string]string{ 318 "DOCKER_HOST": "unix:///home/tilt/.docker/desktop/docker.sock", 319 }, 320 expectedCluster: Env{ 321 Client: hostClient{Host: "unix:///home/tilt/.docker/desktop/docker.sock"}, 322 BuildToKubeContexts: []string{"docker-desktop-me"}, 323 }, 324 expectedLocal: Env{ 325 Client: hostClient{Host: "unix:///home/tilt/.docker/desktop/docker.sock"}, 326 BuildToKubeContexts: []string{"docker-desktop-me", "docker-desktop-me"}, 327 }, 328 }, 329 { 330 env: clusterid.ProductDockerDesktop, 331 runtime: container.RuntimeDocker, 332 osEnv: map[string]string{ 333 "DOCKER_HOST": "unix:///home/tilt/.docker/run/docker.sock", 334 }, 335 expectedCluster: Env{ 336 Client: hostClient{Host: "unix:///home/tilt/.docker/run/docker.sock"}, 337 BuildToKubeContexts: []string{"docker-desktop-me"}, 338 }, 339 expectedLocal: Env{ 340 Client: hostClient{Host: "unix:///home/tilt/.docker/run/docker.sock"}, 341 BuildToKubeContexts: []string{"docker-desktop-me", "docker-desktop-me"}, 342 }, 343 }, 344 { 345 env: clusterid.ProductRancherDesktop, 346 runtime: container.RuntimeDocker, 347 expectedCluster: Env{ 348 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 349 BuildToKubeContexts: []string{"rancher-desktop-me"}, 350 }, 351 expectedLocal: Env{ 352 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 353 BuildToKubeContexts: []string{"rancher-desktop-me"}, 354 }, 355 }, 356 { 357 env: clusterid.ProductRancherDesktop, 358 runtime: container.RuntimeContainerd, 359 expectedCluster: Env{ 360 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 361 }, 362 expectedLocal: Env{ 363 Client: hostClient{Host: "unix:///var/run/docker.sock"}, 364 }, 365 }, 366 { 367 env: clusterid.ProductRancherDesktop, 368 runtime: container.RuntimeDocker, 369 // Set DOCKER_HOST here to mimic rancher-desktop docker context in non-admin mode 370 osEnv: map[string]string{ 371 "DOCKER_HOST": "unix:///Users/tilt/.rd/docker.sock", 372 }, 373 expectedCluster: Env{ 374 Client: hostClient{Host: "unix:///Users/tilt/.rd/docker.sock"}, 375 BuildToKubeContexts: []string{"rancher-desktop-me"}, 376 }, 377 expectedLocal: Env{ 378 Client: hostClient{Host: "unix:///Users/tilt/.rd/docker.sock"}, 379 BuildToKubeContexts: []string{"rancher-desktop-me"}, 380 }, 381 }, 382 } 383 384 for i, c := range cases { 385 t.Run(fmt.Sprintf("Case%d", i), func(t *testing.T) { 386 for _, k := range envVars { 387 t.Setenv(k, c.osEnv[k]) 388 } 389 390 minikubeV := c.minikubeV 391 if minikubeV == "" { 392 minikubeV = "1.3.0" // an Old version 393 } 394 395 mkClient := k8s.FakeMinikube{DockerEnvMap: c.mkEnv, FakeVersion: minikubeV} 396 kubeContext := k8s.KubeContext(fmt.Sprintf("%s-me", c.env)) 397 kCli := k8s.NewFakeK8sClient(t) 398 kCli.Runtime = c.runtime 399 cluster := ProvideClusterEnv(context.Background(), fakeClientCreator{}, kubeContext, c.env, kCli, mkClient) 400 assert.Equal(t, c.expectedCluster, Env(cluster)) 401 402 local := ProvideLocalEnv(context.Background(), fakeClientCreator{}, kubeContext, c.env, cluster) 403 assert.Equal(t, c.expectedLocal, Env(local)) 404 }) 405 } 406 }