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  }