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 }