github.com/GoogleContainerTools/skaffold/v2@v2.13.2/integration/ko_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 integration
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"io"
    23  	stdlog "log"
    24  	"net/http/httptest"
    25  	"path/filepath"
    26  	"runtime"
    27  	"testing"
    28  
    29  	"github.com/google/go-containerregistry/pkg/crane"
    30  	"github.com/google/go-containerregistry/pkg/registry"
    31  	"github.com/google/go-containerregistry/pkg/v1/mutate"
    32  	"github.com/google/go-containerregistry/pkg/v1/random"
    33  
    34  	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/build/ko"
    35  	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/config"
    36  	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/platform"
    37  	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/schema/latest"
    38  )
    39  
    40  func TestBuildAndPushKoImageProgrammatically(t *testing.T) {
    41  	MarkIntegrationTest(t, CanRunWithoutGcp)
    42  
    43  	// Start a local registry server.
    44  	// This registry hosts the base image, and it is the target registry for the built image.
    45  	baseimageNamespace := "baseimage"
    46  	registryServer, err := registryServerWithImage(baseimageNamespace)
    47  	if err != nil {
    48  		t.Fatalf("could not create test registry server: %v", err)
    49  	}
    50  	defer registryServer.Close()
    51  	registryAddr := registryServer.Listener.Addr().String()
    52  	baseImage := fmt.Sprintf("%s/%s", registryAddr, baseimageNamespace)
    53  
    54  	// Get the directory of the basic ko sample app from the `examples` directory.
    55  	exampleAppDir, err := koExampleAppDir()
    56  	if err != nil {
    57  		t.Fatalf("could not get ko example app dir: %+v", err)
    58  	}
    59  
    60  	// Build the artifact
    61  	b := ko.NewArtifactBuilder(nil, true, config.RunModes.Build, nil)
    62  	artifact := &latest.Artifact{
    63  		ArtifactType: latest.ArtifactType{
    64  			KoArtifact: &latest.KoArtifact{
    65  				BaseImage: baseImage,
    66  			},
    67  		},
    68  		Workspace: exampleAppDir,
    69  	}
    70  	imageName := fmt.Sprintf("%s/%s", registryAddr, "skaffold-ko")
    71  	_, err = b.Build(context.Background(), nil, artifact, imageName, platform.Matcher{})
    72  	if err != nil {
    73  		t.Fatalf("b.Build(): %+v", err)
    74  	}
    75  }
    76  
    77  // registryServerWithImage starts a local registry and pushes a random image.
    78  // Use this to speed up tests, by not having to reach out to a real registry.
    79  // The registry uses a NOP logger to avoid spamming test logs.
    80  // Remember to call `defer Close()` on the returned `httptest.Server`.
    81  func registryServerWithImage(namespace string) (*httptest.Server, error) {
    82  	nopLog := stdlog.New(io.Discard, "", 0)
    83  	r := registry.New(registry.Logger(nopLog))
    84  	s := httptest.NewServer(r)
    85  	imageName := fmt.Sprintf("%s/%s", s.Listener.Addr().String(), namespace)
    86  	image, err := random.Image(1024, 1)
    87  	if err != nil {
    88  		return nil, fmt.Errorf("random.Image(): %+v", err)
    89  	}
    90  	// ko 0.12 starts to validate image platform, the random generated image doesn't that info, we need to manually to set
    91  	// image platform back to the image. image.ConfigFile() is a deepCopy() method, we need to use mutate.ConfigFile() to inject
    92  	// the platform info.
    93  	configFile, _ := image.ConfigFile()
    94  	configFile.OS = runtime.GOOS
    95  	configFile.Architecture = runtime.GOARCH
    96  	configFile.OSVersion = runtime.Version()
    97  
    98  	image, err = mutate.ConfigFile(image, configFile)
    99  	if err != nil {
   100  		return nil, fmt.Errorf("failed to mutate image: %+v", err)
   101  	}
   102  
   103  	err = crane.Push(image, imageName)
   104  	if err != nil {
   105  		return nil, fmt.Errorf("crane.Push(): %+v", err)
   106  	}
   107  	return s, nil
   108  }
   109  
   110  // koExampleAppDir returns the directory path of the basic ko builder sample app.
   111  func koExampleAppDir() (string, error) {
   112  	_, filename, _, ok := runtime.Caller(0)
   113  	if !ok {
   114  		return "", fmt.Errorf("could not get current filename")
   115  	}
   116  	basepath := filepath.Dir(filename)
   117  	exampleDir, err := filepath.Abs(filepath.Join(basepath, "examples", "ko"))
   118  	if err != nil {
   119  		return "", fmt.Errorf("could not get absolute path of example from basepath %q: %w", basepath, err)
   120  	}
   121  	return exampleDir, nil
   122  }