github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/docker_test.go (about)

     1  package tiltfile
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/tilt-dev/tilt/internal/testutils"
    13  	"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
    14  )
    15  
    16  func TestDockerignoreInSyncDir(t *testing.T) {
    17  	f := newFixture(t)
    18  
    19  	f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
    20  	f.file("Dockerfile", `
    21  FROM alpine
    22  ADD ./src /src
    23  `)
    24  	f.file("Tiltfile", `
    25  k8s_yaml('fe.yaml')
    26  docker_build('gcr.io/fe', '.', live_update=[
    27    sync('./src', '/src')
    28  ])
    29  `)
    30  	f.file(".dockerignore", "build")
    31  	f.file("Dockerfile.custom.dockerignore", "shouldntmatch")
    32  	f.file(filepath.Join("src", "index.html"), "Hello world!")
    33  	f.file(filepath.Join("src", ".dockerignore"), "**")
    34  
    35  	f.load()
    36  	m := f.assertNextManifest("fe")
    37  	assert.Equal(t,
    38  		[]v1alpha1.IgnoreDef{
    39  			{
    40  				BasePath: f.JoinPath("Tiltfile"),
    41  			},
    42  			{
    43  				BasePath: f.Path(),
    44  				Patterns: []string{"build"},
    45  			},
    46  			{
    47  				BasePath: f.JoinPath("Dockerfile"),
    48  			},
    49  		},
    50  		m.ImageTargetAt(0).GetFileWatchIgnores())
    51  }
    52  
    53  func TestNonDefaultDockerignoreInSyncDir(t *testing.T) {
    54  	f := newFixture(t)
    55  
    56  	f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
    57  	f.file("Dockerfile.custom", `
    58  FROM alpine
    59  ADD ./src /src
    60  `)
    61  	f.file("Tiltfile", `
    62  k8s_yaml('fe.yaml')
    63  docker_build('gcr.io/fe', '.', dockerfile="Dockerfile.custom", live_update=[
    64    sync('./src', '/src')
    65  ])
    66  `)
    67  	f.file(".dockerignore", "shouldntmatch")
    68  	f.file("Dockerfile.custom.dockerignore", "build")
    69  	f.file(filepath.Join("src", "index.html"), "Hello world!")
    70  	f.file(filepath.Join("src", "Dockerfile.custom.dockerignore"), "**")
    71  
    72  	f.load()
    73  	m := f.assertNextManifest("fe")
    74  	assert.Equal(t,
    75  		[]v1alpha1.IgnoreDef{
    76  			{
    77  				BasePath: f.JoinPath("Tiltfile"),
    78  			},
    79  			{
    80  				BasePath: f.Path(),
    81  				Patterns: []string{"build"},
    82  			},
    83  			{
    84  				BasePath: f.JoinPath("Dockerfile.custom"),
    85  			},
    86  		},
    87  		m.ImageTargetAt(0).GetFileWatchIgnores())
    88  }
    89  
    90  func TestCustomPlatform(t *testing.T) {
    91  	type tc struct {
    92  		name     string
    93  		argValue string
    94  		envValue string
    95  		expected string
    96  	}
    97  	tcs := []tc{
    98  		{name: "No Platform"},
    99  		{name: "Arg Only", argValue: "linux/arm64", expected: "linux/arm64"},
   100  		{name: "Env Only", envValue: "linux/arm64", expected: "linux/arm64"},
   101  		// explicit arg takes precedence over env
   102  		{name: "Arg + Env", argValue: "linux/arm64", envValue: "linux/amd64", expected: "linux/arm64"},
   103  	}
   104  
   105  	for _, tt := range tcs {
   106  		t.Run(
   107  			tt.name, func(t *testing.T) {
   108  				if tt.envValue == "" {
   109  					testutils.Unsetenv(t, dockerPlatformEnv)
   110  				} else {
   111  					testutils.Setenv(t, dockerPlatformEnv, tt.envValue)
   112  				}
   113  
   114  				f := newFixture(t)
   115  
   116  				f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
   117  				f.file("Dockerfile", `FROM alpine`)
   118  
   119  				tf := "k8s_yaml('fe.yaml')\n"
   120  				if tt.argValue == "" {
   121  					tf += "docker_build('gcr.io/fe', '.')\n"
   122  				} else {
   123  					tf += fmt.Sprintf("docker_build('gcr.io/fe', '.', platform='%s')", tt.argValue)
   124  				}
   125  
   126  				f.file("Tiltfile", tf)
   127  
   128  				f.load()
   129  				m := f.assertNextManifest("fe")
   130  				require.Equal(t, tt.expected, m.ImageTargetAt(0).DockerBuildInfo().Platform)
   131  			})
   132  	}
   133  }
   134  
   135  func TestCustomBuildDepsAreLocalRepos(t *testing.T) {
   136  	f := newFixture(t)
   137  
   138  	f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
   139  	f.file("Dockerfile", `
   140  FROM alpine
   141  ADD . .
   142  `)
   143  	f.file("Tiltfile", `
   144  k8s_yaml('fe.yaml')
   145  custom_build('gcr.io/fe', 'docker build -t $EXPECTED_REF .', ['src'])
   146  `)
   147  	f.file(".dockerignore", "build")
   148  	f.file(filepath.Join("src", "index.html"), "Hello world!")
   149  	f.file(filepath.Join("src", ".git", "hi"), "hi")
   150  
   151  	f.load()
   152  
   153  	m := f.assertNextManifest("fe")
   154  	it := m.ImageTargets[0]
   155  
   156  	assert.Equal(t, []v1alpha1.IgnoreDef{
   157  		{BasePath: f.JoinPath("Tiltfile")},
   158  		{BasePath: f.JoinPath("src", ".git")},
   159  	}, it.GetFileWatchIgnores())
   160  }
   161  
   162  func TestCustomBuildDepsZeroArgs(t *testing.T) {
   163  	f := newFixture(t)
   164  
   165  	f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
   166  	f.file("Tiltfile", `
   167  k8s_yaml('fe.yaml')
   168  custom_build('gcr.io/fe', 'docker build -t $EXPECTED_REF .', [])
   169  `)
   170  
   171  	f.load()
   172  }
   173  
   174  func TestCustomBuildOutputsImageRefsTo(t *testing.T) {
   175  	f := newFixture(t)
   176  
   177  	f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
   178  	f.file("Dockerfile", `
   179  FROM alpine
   180  ADD . .
   181  `)
   182  	f.file("Tiltfile", `
   183  k8s_yaml('fe.yaml')
   184  custom_build('gcr.io/fe', 'export MY_REF="gcr.io/fe:dev" && docker build -t $MY_REF . && echo $MY_REF > ref.txt',
   185              ['src'],
   186              outputs_image_ref_to='ref.txt')
   187  `)
   188  
   189  	f.load()
   190  
   191  	m := f.assertNextManifest("fe")
   192  	it := m.ImageTargets[0]
   193  	assert.Equal(t, f.JoinPath("ref.txt"), it.CustomBuildInfo().OutputsImageRefTo)
   194  }
   195  
   196  func TestCustomBuildOutputsImageRefsToIncompatibleWithTag(t *testing.T) {
   197  	f := newFixture(t)
   198  
   199  	f.file("Tiltfile", `
   200  custom_build('gcr.io/fe', 'export MY_REF="gcr.io/fe:dev" && docker build -t $MY_REF . && echo $MY_REF > ref.txt',
   201              ['src'],
   202              tag='dev',
   203              outputs_image_ref_to='ref.txt')
   204  `)
   205  
   206  	f.loadErrString("Cannot specify both tag= and outputs_image_ref_to=")
   207  }
   208  
   209  func TestExtraHosts(t *testing.T) {
   210  	type tc struct {
   211  		name     string
   212  		argValue []string
   213  		expected []string
   214  	}
   215  	tcs := []tc{
   216  		{
   217  			//docker_build('gcr.io/fe', '.')
   218  			name: "No Extra Hosts",
   219  		},
   220  		{
   221  			// docker_build('gcr.io/fe', '.', extra_hosts='testing.example.com:10.0.0.1')
   222  			name:     "One Extra Host Only",
   223  			argValue: []string{"testing.example.com:10.0.0.1"},
   224  			expected: []string{"testing.example.com:10.0.0.1"},
   225  		},
   226  		{
   227  			// docker_build('gcr.io/fe', '.', extra_hosts=["testing.example.com:10.0.0.1","app.testing.example.com:10.0.0.3"])
   228  			name:     "Two Extra Hosts",
   229  			argValue: []string{"testing.example.com:10.0.0.1", "app.testing.example.com:10.0.0.3"},
   230  			expected: []string{"testing.example.com:10.0.0.1", "app.testing.example.com:10.0.0.3"},
   231  		},
   232  	}
   233  
   234  	for _, tt := range tcs {
   235  		t.Run(
   236  			tt.name, func(t *testing.T) {
   237  				f := newFixture(t)
   238  
   239  				f.yaml("fe.yaml", deployment("fe", image("gcr.io/fe")))
   240  				f.file("Dockerfile", `FROM alpine`)
   241  
   242  				tf := "k8s_yaml('fe.yaml')\ndocker_build('gcr.io/fe', '.'"
   243  				if len(tt.argValue) == 1 {
   244  					tf += fmt.Sprintf(", extra_hosts='%s'", tt.argValue[0])
   245  				} else if len(tt.argValue) > 1 {
   246  					tf += `, extra_hosts=["` + strings.Join(tt.argValue, `","`) + `"]`
   247  				}
   248  				tf += ")"
   249  				fmt.Println(tf)
   250  
   251  				f.file("Tiltfile", tf)
   252  
   253  				f.load()
   254  				m := f.assertNextManifest("fe")
   255  				require.Equal(t, tt.expected, m.ImageTargetAt(0).DockerBuildInfo().ExtraHosts)
   256  			},
   257  		)
   258  	}
   259  }