github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/gcb/docker_test.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package gcb 18 19 import ( 20 "context" 21 "testing" 22 23 v1 "github.com/opencontainers/image-spec/specs-go/v1" 24 "google.golang.org/api/cloudbuild/v1" 25 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" 31 "github.com/GoogleContainerTools/skaffold/testutil" 32 ) 33 34 func TestDockerBuildSpec(t *testing.T) { 35 tests := []struct { 36 description string 37 artifact *latest.Artifact 38 platforms platform.Matcher 39 expected cloudbuild.Build 40 shouldErr bool 41 }{ 42 { 43 description: "normal docker build", 44 artifact: &latest.Artifact{ 45 ArtifactType: latest.ArtifactType{ 46 DockerArtifact: &latest.DockerArtifact{ 47 DockerfilePath: "Dockerfile", 48 BuildArgs: map[string]*string{ 49 "arg1": util.StringPtr("value1"), 50 "arg2": nil, 51 }, 52 }, 53 }, 54 }, 55 expected: cloudbuild.Build{ 56 LogsBucket: "bucket", 57 Source: &cloudbuild.Source{ 58 StorageSource: &cloudbuild.StorageSource{ 59 Bucket: "bucket", 60 Object: "object", 61 }, 62 }, 63 Steps: []*cloudbuild.BuildStep{{ 64 Name: "docker/docker", 65 Args: []string{"build", "--tag", "nginx", "-f", "Dockerfile", "--build-arg", "arg1=value1", "--build-arg", "arg2", "."}, 66 }}, 67 Images: []string{"nginx"}, 68 Options: &cloudbuild.BuildOptions{ 69 DiskSizeGb: 100, 70 MachineType: "n1-standard-1", 71 }, 72 Timeout: "10m", 73 }, 74 }, 75 { 76 description: "docker build with artifact dependencies", 77 artifact: &latest.Artifact{ 78 ImageName: "img1", 79 ArtifactType: latest.ArtifactType{ 80 DockerArtifact: &latest.DockerArtifact{ 81 DockerfilePath: "Dockerfile", 82 BuildArgs: map[string]*string{ 83 "arg1": util.StringPtr("value1"), 84 "arg2": nil, 85 }, 86 }, 87 }, 88 Dependencies: []*latest.ArtifactDependency{{ImageName: "img2", Alias: "IMG2"}, {ImageName: "img3", Alias: "IMG3"}}, 89 }, 90 expected: cloudbuild.Build{ 91 LogsBucket: "bucket", 92 Source: &cloudbuild.Source{ 93 StorageSource: &cloudbuild.StorageSource{ 94 Bucket: "bucket", 95 Object: "object", 96 }, 97 }, 98 Steps: []*cloudbuild.BuildStep{{ 99 Name: "docker/docker", 100 Args: []string{"build", "--tag", "nginx", "-f", "Dockerfile", "--build-arg", "IMG2=img2:tag", "--build-arg", "IMG3=img3:tag", "--build-arg", "arg1=value1", "--build-arg", "arg2", "."}, 101 }}, 102 Images: []string{"nginx"}, 103 Options: &cloudbuild.BuildOptions{ 104 DiskSizeGb: 100, 105 MachineType: "n1-standard-1", 106 }, 107 Timeout: "10m", 108 }, 109 }, 110 { 111 description: "buildkit `secret` option not supported in GCB", 112 artifact: &latest.Artifact{ 113 ArtifactType: latest.ArtifactType{ 114 DockerArtifact: &latest.DockerArtifact{ 115 DockerfilePath: "Dockerfile", 116 Secrets: []*latest.DockerSecret{ 117 {ID: "secret"}, 118 }, 119 }, 120 }, 121 }, 122 shouldErr: true, 123 }, 124 { 125 description: "buildkit `ssh` option not supported in GCB", 126 artifact: &latest.Artifact{ 127 ArtifactType: latest.ArtifactType{ 128 DockerArtifact: &latest.DockerArtifact{ 129 DockerfilePath: "Dockerfile", 130 SSH: "default", 131 }, 132 }, 133 }, 134 shouldErr: true, 135 }, 136 137 { 138 description: "cross-platform build", 139 artifact: &latest.Artifact{ 140 ArtifactType: latest.ArtifactType{ 141 DockerArtifact: &latest.DockerArtifact{ 142 DockerfilePath: "Dockerfile", 143 BuildArgs: map[string]*string{ 144 "arg1": util.StringPtr("value1"), 145 "arg2": nil, 146 }, 147 }, 148 }, 149 }, 150 platforms: platform.Matcher{Platforms: []v1.Platform{{Architecture: "arm", OS: "freebsd"}}}, 151 expected: cloudbuild.Build{ 152 LogsBucket: "bucket", 153 Source: &cloudbuild.Source{ 154 StorageSource: &cloudbuild.StorageSource{ 155 Bucket: "bucket", 156 Object: "object", 157 }, 158 }, 159 Steps: []*cloudbuild.BuildStep{{ 160 Name: "docker/docker", 161 Args: []string{"build", "--tag", "nginx", "-f", "Dockerfile", "--platform", "freebsd/arm", "--build-arg", "arg1=value1", "--build-arg", "arg2", "."}, 162 Env: []string{"DOCKER_BUILDKIT=1"}, 163 }}, 164 Images: []string{"nginx"}, 165 Options: &cloudbuild.BuildOptions{ 166 DiskSizeGb: 100, 167 MachineType: "n1-standard-1", 168 }, 169 Timeout: "10m", 170 }, 171 }, 172 } 173 174 for _, test := range tests { 175 testutil.Run(t, test.description, func(t *testutil.T) { 176 t.Override(&docker.EvalBuildArgs, func(_ config.RunMode, _ string, _ string, args map[string]*string, extra map[string]*string) (map[string]*string, error) { 177 m := make(map[string]*string) 178 for k, v := range args { 179 m[k] = v 180 } 181 for k, v := range extra { 182 m[k] = v 183 } 184 return m, nil 185 }) 186 187 store := mockArtifactStore{ 188 "img2": "img2:tag", 189 "img3": "img3:tag", 190 } 191 192 builder := NewBuilder(&mockBuilderContext{artifactStore: store}, &latest.GoogleCloudBuild{ 193 DockerImage: "docker/docker", 194 DiskSizeGb: 100, 195 MachineType: "n1-standard-1", 196 Timeout: "10m", 197 }) 198 199 desc, err := builder.buildSpec(context.Background(), test.artifact, "nginx", test.platforms, "bucket", "object") 200 t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expected, desc) 201 }) 202 } 203 } 204 205 func TestPullCacheFrom(t *testing.T) { 206 tests := []struct { 207 description string 208 artifact *latest.Artifact 209 tag string 210 platforms platform.Matcher 211 expected []*cloudbuild.BuildStep 212 shouldErr bool 213 }{ 214 { 215 description: "multiple cache-from images", 216 artifact: &latest.Artifact{ 217 ArtifactType: latest.ArtifactType{ 218 DockerArtifact: &latest.DockerArtifact{ 219 DockerfilePath: "Dockerfile", 220 CacheFrom: []string{"from/image1", "from/image2"}, 221 }, 222 }, 223 }, 224 tag: "nginx2", 225 expected: []*cloudbuild.BuildStep{{ 226 Name: "docker/docker", 227 Entrypoint: "sh", 228 Args: []string{"-c", "docker pull from/image1 || true"}, 229 }, { 230 Name: "docker/docker", 231 Entrypoint: "sh", 232 Args: []string{"-c", "docker pull from/image2 || true"}, 233 }, { 234 Name: "docker/docker", 235 Args: []string{"build", "--tag", "nginx2", "-f", "Dockerfile", "--cache-from", "from/image1", "--cache-from", "from/image2", "."}, 236 }}, 237 }, 238 { 239 description: "cache-from self uses tagged image", 240 artifact: &latest.Artifact{ 241 ImageName: "gcr.io/k8s-skaffold/test", 242 ArtifactType: latest.ArtifactType{ 243 DockerArtifact: &latest.DockerArtifact{ 244 DockerfilePath: "Dockerfile", 245 CacheFrom: []string{"gcr.io/k8s-skaffold/test"}, 246 }, 247 }, 248 }, 249 tag: "gcr.io/k8s-skaffold/test:tagged", 250 expected: []*cloudbuild.BuildStep{{ 251 Name: "docker/docker", 252 Entrypoint: "sh", 253 Args: []string{"-c", "docker pull gcr.io/k8s-skaffold/test:tagged || true"}, 254 }, { 255 Name: "docker/docker", 256 Args: []string{"build", "--tag", "gcr.io/k8s-skaffold/test:tagged", "-f", "Dockerfile", "--cache-from", "gcr.io/k8s-skaffold/test:tagged", "."}, 257 }}, 258 }, 259 { 260 description: "cross-platform cache-from images", 261 artifact: &latest.Artifact{ 262 ArtifactType: latest.ArtifactType{ 263 DockerArtifact: &latest.DockerArtifact{ 264 DockerfilePath: "Dockerfile", 265 CacheFrom: []string{"from/image1", "from/image2"}, 266 }, 267 }, 268 }, 269 tag: "nginx2", 270 platforms: platform.Matcher{Platforms: []v1.Platform{{Architecture: "arm", OS: "freebsd"}}}, 271 expected: []*cloudbuild.BuildStep{{ 272 Name: "docker/docker", 273 Entrypoint: "sh", 274 Args: []string{"-c", "docker pull --platform freebsd/arm from/image1 || true"}, 275 }, { 276 Name: "docker/docker", 277 Entrypoint: "sh", 278 Args: []string{"-c", "docker pull --platform freebsd/arm from/image2 || true"}, 279 }, { 280 Name: "docker/docker", 281 Args: []string{"build", "--tag", "nginx2", "-f", "Dockerfile", "--platform", "freebsd/arm", "--cache-from", "from/image1", "--cache-from", "from/image2", "."}, 282 Env: []string{"DOCKER_BUILDKIT=1"}, 283 }}, 284 }, 285 } 286 287 for _, test := range tests { 288 testutil.Run(t, test.description, func(t *testutil.T) { 289 t.Override(&docker.EvalBuildArgs, func(_ config.RunMode, _ string, _ string, args map[string]*string, _ map[string]*string) (map[string]*string, error) { 290 return args, nil 291 }) 292 builder := NewBuilder(&mockBuilderContext{}, &latest.GoogleCloudBuild{ 293 DockerImage: "docker/docker", 294 }) 295 desc, err := builder.dockerBuildSpec(test.artifact, test.tag, test.platforms) 296 297 t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expected, desc.Steps) 298 }) 299 } 300 }