github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/gcb/kaniko_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  	"google.golang.org/api/cloudbuild/v1"
    24  	kv1 "k8s.io/api/core/v1"
    25  
    26  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/kaniko"
    27  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
    28  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
    29  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph"
    30  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform"
    31  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
    32  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
    33  	"github.com/GoogleContainerTools/skaffold/testutil"
    34  )
    35  
    36  func TestKanikoBuildSpec(t *testing.T) {
    37  	tests := []struct {
    38  		description  string
    39  		artifact     *latest.KanikoArtifact
    40  		expectedArgs []string
    41  		expectedEnv  []string
    42  	}{
    43  		{
    44  			description: "simple build",
    45  			artifact: &latest.KanikoArtifact{
    46  				DockerfilePath: "Dockerfile",
    47  			},
    48  			expectedArgs: []string{},
    49  		},
    50  		{
    51  			description: "with BuildArgs",
    52  			artifact: &latest.KanikoArtifact{
    53  				DockerfilePath: "Dockerfile",
    54  				BuildArgs: map[string]*string{
    55  					"arg1": util.StringPtr("value1"),
    56  					"arg2": nil,
    57  				},
    58  			},
    59  			expectedArgs: []string{
    60  				kaniko.BuildArgsFlag, "arg1=value1",
    61  				kaniko.BuildArgsFlag, "arg2",
    62  			},
    63  		},
    64  		{
    65  			description: "with Env",
    66  			artifact: &latest.KanikoArtifact{
    67  				DockerfilePath: "Dockerfile",
    68  				Env:            []kv1.EnvVar{{Name: "KEY1", Value: "VALUE1"}, {Name: "KEY2", Value: "VALUE2"}},
    69  			},
    70  			expectedEnv: []string{"KEY1=VALUE1", "KEY2=VALUE2"},
    71  		},
    72  		{
    73  			description: "with Cache",
    74  			artifact: &latest.KanikoArtifact{
    75  				DockerfilePath: "Dockerfile",
    76  				Cache:          &latest.KanikoCache{},
    77  			},
    78  			expectedArgs: []string{
    79  				kaniko.CacheFlag,
    80  			},
    81  		},
    82  		{
    83  			description: "with Cache Copy Layers",
    84  			artifact: &latest.KanikoArtifact{
    85  				DockerfilePath: "Dockerfile",
    86  				Cache:          &latest.KanikoCache{CacheCopyLayers: true},
    87  			},
    88  			expectedArgs: []string{
    89  				kaniko.CacheFlag,
    90  				kaniko.CacheCopyLayersFlag,
    91  			},
    92  		},
    93  		{
    94  			description: "with Cleanup",
    95  			artifact: &latest.KanikoArtifact{
    96  				DockerfilePath: "Dockerfile",
    97  				Cleanup:        true,
    98  			},
    99  			expectedArgs: []string{
   100  				kaniko.CleanupFlag,
   101  			},
   102  		},
   103  		{
   104  			description: "with DigestFile",
   105  			artifact: &latest.KanikoArtifact{
   106  				DockerfilePath: "Dockerfile",
   107  				DigestFile:     "/tmp/digest",
   108  			},
   109  			expectedArgs: []string{
   110  				kaniko.DigestFileFlag, "/tmp/digest",
   111  			},
   112  		},
   113  		{
   114  			description: "with Force",
   115  			artifact: &latest.KanikoArtifact{
   116  				DockerfilePath: "Dockerfile",
   117  				Force:          true,
   118  			},
   119  			expectedArgs: []string{
   120  				kaniko.ForceFlag,
   121  			},
   122  		},
   123  		{
   124  			description: "with ImageFSExtractRetry",
   125  			artifact: &latest.KanikoArtifact{
   126  				DockerfilePath:      "Dockerfile",
   127  				ImageFSExtractRetry: "5",
   128  			},
   129  			expectedArgs: []string{
   130  				"--image-fs-extract-retry", "5",
   131  			},
   132  		},
   133  		{
   134  			description: "with ImageNameWithDigestFile",
   135  			artifact: &latest.KanikoArtifact{
   136  				DockerfilePath:          "Dockerfile",
   137  				ImageNameWithDigestFile: "/tmp/imageName",
   138  			},
   139  			expectedArgs: []string{
   140  				kaniko.ImageNameWithDigestFileFlag, "/tmp/imageName",
   141  			},
   142  		},
   143  		{
   144  			description: "with Insecure",
   145  			artifact: &latest.KanikoArtifact{
   146  				DockerfilePath: "Dockerfile",
   147  				Insecure:       true,
   148  			},
   149  			expectedArgs: []string{
   150  				kaniko.InsecureFlag,
   151  			},
   152  		},
   153  		{
   154  			description: "with InsecurePull",
   155  			artifact: &latest.KanikoArtifact{
   156  				DockerfilePath: "Dockerfile",
   157  				InsecurePull:   true,
   158  			},
   159  			expectedArgs: []string{
   160  				kaniko.InsecurePullFlag,
   161  			},
   162  		},
   163  		{
   164  			description: "with InsecureRegistry",
   165  			artifact: &latest.KanikoArtifact{
   166  				DockerfilePath: "Dockerfile",
   167  				InsecureRegistry: []string{
   168  					"s1.registry.url:5000",
   169  					"s2.registry.url:5000",
   170  				},
   171  			},
   172  			expectedArgs: []string{
   173  				kaniko.InsecureRegistryFlag, "s1.registry.url:5000",
   174  				kaniko.InsecureRegistryFlag, "s2.registry.url:5000",
   175  			},
   176  		},
   177  		{
   178  			description: "with LogFormat",
   179  			artifact: &latest.KanikoArtifact{
   180  				DockerfilePath: "Dockerfile",
   181  				LogFormat:      "json",
   182  			},
   183  			expectedArgs: []string{
   184  				kaniko.LogFormatFlag, "json",
   185  			},
   186  		},
   187  		{
   188  			description: "with LogTimestamp",
   189  			artifact: &latest.KanikoArtifact{
   190  				DockerfilePath: "Dockerfile",
   191  				LogTimestamp:   true,
   192  			},
   193  			expectedArgs: []string{
   194  				kaniko.LogTimestampFlag,
   195  			},
   196  		},
   197  		{
   198  			description: "with NoPush",
   199  			artifact: &latest.KanikoArtifact{
   200  				DockerfilePath: "Dockerfile",
   201  				NoPush:         true,
   202  			},
   203  			expectedArgs: []string{
   204  				kaniko.NoPushFlag,
   205  			},
   206  		},
   207  		{
   208  			description: "with OCILayoutPath",
   209  			artifact: &latest.KanikoArtifact{
   210  				DockerfilePath: "Dockerfile",
   211  				OCILayoutPath:  "/tmp/builtImage",
   212  			},
   213  			expectedArgs: []string{
   214  				kaniko.OCILayoutFlag, "/tmp/builtImage",
   215  			},
   216  		},
   217  		{
   218  			description: "with RegistryCertificate",
   219  			artifact: &latest.KanikoArtifact{
   220  				DockerfilePath: "Dockerfile",
   221  				RegistryCertificate: map[string]*string{
   222  					"s1.registry.url": util.StringPtr("/etc/certs/certificate1.cert"),
   223  					"s2.registry.url": util.StringPtr("/etc/certs/certificate2.cert"),
   224  				},
   225  			},
   226  			expectedArgs: []string{
   227  				kaniko.RegistryCertificateFlag, "s1.registry.url=/etc/certs/certificate1.cert",
   228  				kaniko.RegistryCertificateFlag, "s2.registry.url=/etc/certs/certificate2.cert",
   229  			},
   230  		},
   231  		{
   232  			description: "with RegistryMirror",
   233  			artifact: &latest.KanikoArtifact{
   234  				DockerfilePath: "Dockerfile",
   235  				RegistryMirror: "mirror.gcr.io",
   236  			},
   237  			expectedArgs: []string{
   238  				kaniko.RegistryMirrorFlag, "mirror.gcr.io",
   239  			},
   240  		},
   241  		{
   242  			description: "with Reproducible",
   243  			artifact: &latest.KanikoArtifact{
   244  				DockerfilePath: "Dockerfile",
   245  				Reproducible:   true,
   246  			},
   247  			expectedArgs: []string{
   248  				kaniko.ReproducibleFlag,
   249  			},
   250  		},
   251  		{
   252  			description: "with SingleSnapshot",
   253  			artifact: &latest.KanikoArtifact{
   254  				DockerfilePath: "Dockerfile",
   255  				SingleSnapshot: true,
   256  			},
   257  			expectedArgs: []string{
   258  				kaniko.SingleSnapshotFlag,
   259  			},
   260  		},
   261  		{
   262  			description: "with SkipTLS",
   263  			artifact: &latest.KanikoArtifact{
   264  				DockerfilePath: "Dockerfile",
   265  				SkipTLS:        true,
   266  			},
   267  			expectedArgs: []string{
   268  				kaniko.SkipTLSFlag,
   269  				kaniko.SkipTLSVerifyRegistryFlag, "gcr.io",
   270  			},
   271  		},
   272  		{
   273  			description: "with SkipTLSVerifyPull",
   274  			artifact: &latest.KanikoArtifact{
   275  				DockerfilePath:    "Dockerfile",
   276  				SkipTLSVerifyPull: true,
   277  			},
   278  			expectedArgs: []string{
   279  				kaniko.SkipTLSVerifyPullFlag,
   280  			},
   281  		},
   282  		{
   283  			description: "with SkipTLSVerifyRegistry",
   284  			artifact: &latest.KanikoArtifact{
   285  				DockerfilePath: "Dockerfile",
   286  				SkipTLSVerifyRegistry: []string{
   287  					"s1.registry.url:5000",
   288  					"s2.registry.url:5000",
   289  				},
   290  			},
   291  			expectedArgs: []string{
   292  				kaniko.SkipTLSVerifyRegistryFlag, "s1.registry.url:5000",
   293  				kaniko.SkipTLSVerifyRegistryFlag, "s2.registry.url:5000",
   294  			},
   295  		},
   296  		{
   297  			description: "with SkipUnusedStages",
   298  			artifact: &latest.KanikoArtifact{
   299  				DockerfilePath:   "Dockerfile",
   300  				SkipUnusedStages: true,
   301  			},
   302  			expectedArgs: []string{
   303  				kaniko.SkipUnusedStagesFlag,
   304  			},
   305  		},
   306  		{
   307  			description: "with Target",
   308  			artifact: &latest.KanikoArtifact{
   309  				DockerfilePath: "Dockerfile",
   310  				Target:         "builder",
   311  			},
   312  			expectedArgs: []string{
   313  				kaniko.TargetFlag, "builder",
   314  			},
   315  		},
   316  		{
   317  			description: "with SnapshotMode",
   318  			artifact: &latest.KanikoArtifact{
   319  				DockerfilePath: "Dockerfile",
   320  				SnapshotMode:   "redo",
   321  			},
   322  			expectedArgs: []string{
   323  				"--snapshotMode", "redo",
   324  			},
   325  		},
   326  		{
   327  			description: "with PushRetry",
   328  			artifact: &latest.KanikoArtifact{
   329  				DockerfilePath: "Dockerfile",
   330  				PushRetry:      "9",
   331  			},
   332  			expectedArgs: []string{
   333  				"--push-retry", "9",
   334  			},
   335  		},
   336  		{
   337  			description: "with TarPath",
   338  			artifact: &latest.KanikoArtifact{
   339  				DockerfilePath: "Dockerfile",
   340  				TarPath:        "/workspace/tars",
   341  			},
   342  			expectedArgs: []string{
   343  				kaniko.TarPathFlag, "/workspace/tars",
   344  			},
   345  		},
   346  		{
   347  			description: "with UseNewRun",
   348  			artifact: &latest.KanikoArtifact{
   349  				DockerfilePath: "Dockerfile",
   350  				UseNewRun:      true,
   351  			},
   352  			expectedArgs: []string{
   353  				kaniko.UseNewRunFlag,
   354  			},
   355  		},
   356  		{
   357  			description: "with Verbosity",
   358  			artifact: &latest.KanikoArtifact{
   359  				DockerfilePath: "Dockerfile",
   360  				Verbosity:      "trace",
   361  			},
   362  			expectedArgs: []string{
   363  				kaniko.VerbosityFlag, "trace",
   364  			},
   365  		},
   366  		{
   367  			description: "with WhitelistVarRun",
   368  			artifact: &latest.KanikoArtifact{
   369  				DockerfilePath:  "Dockerfile",
   370  				WhitelistVarRun: true,
   371  			},
   372  			expectedArgs: []string{
   373  				kaniko.WhitelistVarRunFlag,
   374  			},
   375  		},
   376  		{
   377  			description: "with WhitelistVarRun",
   378  			artifact: &latest.KanikoArtifact{
   379  				DockerfilePath:  "Dockerfile",
   380  				WhitelistVarRun: true,
   381  			},
   382  			expectedArgs: []string{
   383  				kaniko.WhitelistVarRunFlag,
   384  			},
   385  		},
   386  		{
   387  			description: "with Labels",
   388  			artifact: &latest.KanikoArtifact{
   389  				DockerfilePath: "Dockerfile",
   390  				Label: map[string]*string{
   391  					"label1": util.StringPtr("value1"),
   392  					"label2": nil,
   393  				},
   394  			},
   395  			expectedArgs: []string{
   396  				kaniko.LabelFlag, "label1=value1",
   397  				kaniko.LabelFlag, "label2",
   398  			},
   399  		},
   400  	}
   401  	store := mockArtifactStore{
   402  		"img2": "img2:tag",
   403  		"img3": "img3:tag",
   404  	}
   405  	builder := NewBuilder(&mockBuilderContext{artifactStore: store}, &latest.GoogleCloudBuild{
   406  		KanikoImage: "gcr.io/kaniko-project/executor",
   407  		DiskSizeGb:  100,
   408  		MachineType: "n1-standard-1",
   409  		Timeout:     "10m",
   410  	})
   411  
   412  	defaultExpectedArgs := []string{
   413  		"--destination", "gcr.io/nginx",
   414  		"--dockerfile", "Dockerfile",
   415  	}
   416  
   417  	for _, test := range tests {
   418  		testutil.Run(t, test.description, func(t *testutil.T) {
   419  			artifact := &latest.Artifact{
   420  				ImageName: "img1",
   421  				ArtifactType: latest.ArtifactType{
   422  					KanikoArtifact: test.artifact,
   423  				},
   424  				Dependencies: []*latest.ArtifactDependency{
   425  					{ImageName: "img2", Alias: "IMG2"},
   426  					{ImageName: "img3", Alias: "IMG3"},
   427  				},
   428  			}
   429  
   430  			imageArgs := []string{kaniko.BuildArgsFlag, "IMG2=img2:tag", kaniko.BuildArgsFlag, "IMG3=img3:tag"}
   431  
   432  			t.Override(&docker.EvalBuildArgs, func(_ config.RunMode, _ string, _ string, args map[string]*string, extra map[string]*string) (map[string]*string, error) {
   433  				m := make(map[string]*string)
   434  				for k, v := range args {
   435  					m[k] = v
   436  				}
   437  				for k, v := range extra {
   438  					m[k] = v
   439  				}
   440  				return m, nil
   441  			})
   442  			desc, err := builder.buildSpec(context.Background(), artifact, "gcr.io/nginx", platform.Matcher{}, "bucket", "object")
   443  
   444  			expected := cloudbuild.Build{
   445  				LogsBucket: "bucket",
   446  				Source: &cloudbuild.Source{
   447  					StorageSource: &cloudbuild.StorageSource{
   448  						Bucket: "bucket",
   449  						Object: "object",
   450  					},
   451  				},
   452  				Steps: []*cloudbuild.BuildStep{{
   453  					Name: "gcr.io/kaniko-project/executor",
   454  					Args: append(append(defaultExpectedArgs, imageArgs...), test.expectedArgs...),
   455  					Env:  test.expectedEnv,
   456  				}},
   457  				Options: &cloudbuild.BuildOptions{
   458  					DiskSizeGb:  100,
   459  					MachineType: "n1-standard-1",
   460  				},
   461  				Timeout: "10m",
   462  			}
   463  
   464  			t.CheckNoError(err)
   465  			t.CheckDeepEqual(expected, desc)
   466  		})
   467  	}
   468  }
   469  
   470  type mockArtifactStore map[string]string
   471  
   472  func (m mockArtifactStore) GetImageTag(imageName string) (string, bool) { return m[imageName], true }
   473  func (m mockArtifactStore) Record(a *latest.Artifact, tag string)       { m[a.ImageName] = tag }
   474  func (m mockArtifactStore) GetArtifacts([]*latest.Artifact) ([]graph.Artifact, error) {
   475  	return nil, nil
   476  }