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 }