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  }