github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/ko/build_test.go (about)

     1  /*
     2  Copyright 2021 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 ko
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/docker/docker/client"
    24  	"github.com/google/go-containerregistry/pkg/name"
    25  	"github.com/google/ko/pkg/build"
    26  	"github.com/google/ko/pkg/publish"
    27  
    28  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
    29  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
    30  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform"
    31  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
    32  	"github.com/GoogleContainerTools/skaffold/testutil"
    33  )
    34  
    35  // TestBuild doesn't actually build (or publish) any container images, because
    36  // it's a unit test. Instead, it only verifies that the Build() returns the
    37  // image identifier.
    38  func TestBuild(t *testing.T) {
    39  	tests := []struct {
    40  		description             string
    41  		imageRef                string
    42  		expectedImageIdentifier string
    43  		pushImages              bool
    44  		shouldErr               bool
    45  	}{
    46  		{
    47  			description:             "pushed image with tag",
    48  			imageRef:                "registry.example.com/repo/image1:tag1",
    49  			expectedImageIdentifier: "tag1",
    50  			pushImages:              true,
    51  		},
    52  		{
    53  			description:             "sideloaded image",
    54  			imageRef:                "registry.example.com/repo/image2:any",
    55  			expectedImageIdentifier: "ab737430e80b",
    56  			pushImages:              false,
    57  		},
    58  		{
    59  			description: "error for missing default repo when using ko:// prefix combined with pushing image to a registry",
    60  			imageRef:    "ko://github.com/google/ko",
    61  			pushImages:  true,
    62  			shouldErr:   true,
    63  		},
    64  	}
    65  	for _, test := range tests {
    66  		testutil.Run(t, test.description, func(t *testutil.T) {
    67  			importPath := "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko" // this package
    68  			b := stubKoArtifactBuilder(test.imageRef, test.expectedImageIdentifier, test.pushImages, importPath)
    69  
    70  			artifact := &latest.Artifact{
    71  				ArtifactType: latest.ArtifactType{
    72  					KoArtifact: &latest.KoArtifact{},
    73  				},
    74  				ImageName: importPath,
    75  			}
    76  			gotImageIdentifier, err := b.Build(context.Background(), nil, artifact, test.imageRef, platform.All)
    77  			t.CheckErrorAndFailNow(test.shouldErr, err)
    78  			t.CheckDeepEqual(test.expectedImageIdentifier, gotImageIdentifier)
    79  		})
    80  	}
    81  }
    82  
    83  func Test_getImportPath(t *testing.T) {
    84  	tests := []struct {
    85  		description        string
    86  		artifact           *latest.Artifact
    87  		expectedImportPath string
    88  	}{
    89  		{
    90  			description: "main is ignored when image name is ko-prefixed full Go import path",
    91  			artifact: &latest.Artifact{
    92  				ArtifactType: latest.ArtifactType{
    93  					KoArtifact: &latest.KoArtifact{
    94  						Main: "./main-should-be-ignored",
    95  					},
    96  				},
    97  				ImageName: "ko://git.example.com/org/foo",
    98  			},
    99  			expectedImportPath: "ko://git.example.com/org/foo",
   100  		},
   101  		{
   102  			description: "plain image name",
   103  			artifact: &latest.Artifact{
   104  				ArtifactType: latest.ArtifactType{
   105  					KoArtifact: &latest.KoArtifact{},
   106  				},
   107  				ImageName: "any-image-name-1",
   108  			},
   109  			expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko", // this package
   110  		},
   111  		{
   112  			description: "plain image name with workspace directory",
   113  			artifact: &latest.Artifact{
   114  				ArtifactType: latest.ArtifactType{
   115  					KoArtifact: &latest.KoArtifact{},
   116  				},
   117  				ImageName: "any-image-name-2",
   118  				Workspace: "./testdata/package-main-in-root",
   119  			},
   120  			expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-in-root",
   121  		},
   122  		{
   123  			description: "plain image name with workspace directory and main",
   124  			artifact: &latest.Artifact{
   125  				ArtifactType: latest.ArtifactType{
   126  					KoArtifact: &latest.KoArtifact{
   127  						Main: "./baz",
   128  					},
   129  				},
   130  				ImageName: "any-image-name-3",
   131  				Workspace: "./testdata/package-main-not-in-root",
   132  			},
   133  			expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-not-in-root/baz",
   134  		},
   135  		{
   136  			description: "plain image name with workspace directory and main and source directory",
   137  			artifact: &latest.Artifact{
   138  				ArtifactType: latest.ArtifactType{
   139  					KoArtifact: &latest.KoArtifact{
   140  						Dir:  "package-main-not-in-root",
   141  						Main: "./baz",
   142  					},
   143  				},
   144  				ImageName: "any-image-name-4",
   145  				Workspace: "./testdata",
   146  			},
   147  			expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-not-in-root/baz",
   148  		},
   149  	}
   150  	for _, test := range tests {
   151  		testutil.Run(t, test.description, func(t *testutil.T) {
   152  			gotImportPath, err := getImportPath(test.artifact)
   153  			t.CheckNoError(err)
   154  			t.CheckDeepEqual(test.expectedImportPath, gotImportPath)
   155  		})
   156  	}
   157  }
   158  
   159  func Test_getImageIdentifier(t *testing.T) {
   160  	tests := []struct {
   161  		description         string
   162  		pushImages          bool
   163  		imageRefFromPublish name.Reference
   164  		ref                 string
   165  		wantImageIdentifier string
   166  	}{
   167  		{
   168  			description:         "returns tag for pushed image with tag",
   169  			pushImages:          true,
   170  			imageRefFromPublish: name.MustParseReference("registry.example.com/repo/image:tag"),
   171  			ref:                 "anything", // not used
   172  			wantImageIdentifier: "tag",
   173  		},
   174  		{
   175  			description:         "returns digest for pushed image with digest",
   176  			pushImages:          true,
   177  			imageRefFromPublish: name.MustParseReference("gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229"),
   178  			ref:                 "any value", // not used
   179  			wantImageIdentifier: "sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229",
   180  		},
   181  		{
   182  			description:         "returns docker image ID for sideloaded image",
   183  			pushImages:          false,
   184  			imageRefFromPublish: nil, // not used
   185  			ref:                 "any value",
   186  			wantImageIdentifier: "ab737430e80b",
   187  		},
   188  	}
   189  	for _, test := range tests {
   190  		testutil.Run(t, test.description, func(t *testutil.T) {
   191  			b := stubKoArtifactBuilder(test.ref, test.wantImageIdentifier, test.pushImages, "")
   192  
   193  			gotImageIdentifier, err := b.getImageIdentifier(context.Background(), test.imageRefFromPublish, test.ref)
   194  			t.CheckNoError(err)
   195  
   196  			t.CheckDeepEqual(test.wantImageIdentifier, gotImageIdentifier)
   197  		})
   198  	}
   199  }
   200  
   201  // stubKoArtifactBuilder returns an instance of Builder.
   202  // Both the localDocker and the publishImages fields of the Builder are fakes.
   203  // This means that calling Build() on the returned Builder doesn't actually
   204  // build or publish any images.
   205  func stubKoArtifactBuilder(ref string, imageID string, pushImages bool, importpath string) *Builder {
   206  	api := (&testutil.FakeAPIClient{}).Add(ref, imageID)
   207  	localDocker := fakeLocalDockerDaemon(api)
   208  	b := NewArtifactBuilder(localDocker, pushImages, config.RunModes.Build, nil)
   209  
   210  	// Fake implementation of the `publishImages` function.
   211  	// Returns a map with one entry: importpath -> ref
   212  	// importpath and ref are arguments to the function creating the stub Builder.
   213  	b.publishImages = func(_ context.Context, _ []string, _ publish.Interface, _ build.Interface) (map[string]name.Reference, error) {
   214  		imageRef, err := name.ParseReference(ref)
   215  		if err != nil {
   216  			return nil, err
   217  		}
   218  		return map[string]name.Reference{
   219  			importpath: imageRef,
   220  		}, nil
   221  	}
   222  	return b
   223  }
   224  
   225  func fakeLocalDockerDaemon(api client.CommonAPIClient) docker.LocalDaemon {
   226  	return docker.NewLocalDaemon(api, nil, false, nil)
   227  }