mirror of
https://github.com/ko-build/ko.git
synced 2025-02-01 19:14:40 +02:00
Set build config via BuildOptions (#421)
* Set build config via BuildOptions Enables programmatically overriding build configs when ko is embedded in another tool. Related: #340, #419 * Use local registry for base images in unit tests Tests create a local registry (using ggcr) with a dummy base image. This speeds up tests, since they don't need to hit gcr.io to fetch the default distroless base image. * Update function comment to refer to random image
This commit is contained in:
parent
335c1ac8a6
commit
ae594dcc74
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/google/ko/pkg/build"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -39,6 +40,9 @@ type BuildOptions struct {
|
||||
UserAgent string
|
||||
|
||||
InsecureRegistry bool
|
||||
|
||||
// BuildConfigs enables programmatic overriding of build config set in `.ko.yaml`.
|
||||
BuildConfigs map[string]build.Config
|
||||
}
|
||||
|
||||
func AddBuildOptions(cmd *cobra.Command, bo *BuildOptions) {
|
||||
|
@ -29,7 +29,13 @@ import (
|
||||
)
|
||||
|
||||
func TestPublishImages(t *testing.T) {
|
||||
repo := "registry.example.com/repository"
|
||||
namespace := "base"
|
||||
s, err := registryServerWithImage(namespace)
|
||||
if err != nil {
|
||||
t.Fatalf("could not create test registry server: %v", err)
|
||||
}
|
||||
repo := s.Listener.Addr().String()
|
||||
baseImage := fmt.Sprintf("%s/%s", repo, namespace)
|
||||
sampleAppDir, err := sampleAppRelDir()
|
||||
if err != nil {
|
||||
t.Fatalf("sampleAppRelDir(): %v", err)
|
||||
@ -58,6 +64,7 @@ func TestPublishImages(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
ctx := context.Background()
|
||||
bo := &options.BuildOptions{
|
||||
BaseImage: baseImage,
|
||||
ConcurrentBuilds: 1,
|
||||
}
|
||||
builder, err := NewBuilder(ctx, bo)
|
||||
|
@ -106,7 +106,10 @@ func gobuildOptions(bo *options.BuildOptions) ([]build.Option, error) {
|
||||
opts = append(opts, build.WithLabel(parts[0], parts[1]))
|
||||
}
|
||||
|
||||
if len(buildConfigs) > 0 {
|
||||
// prefer buildConfigs from BuildOptions
|
||||
if bo.BuildConfigs != nil {
|
||||
opts = append(opts, build.WithConfig(bo.BuildConfigs))
|
||||
} else if len(buildConfigs) > 0 {
|
||||
opts = append(opts, build.WithConfig(buildConfigs))
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -29,7 +31,9 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/google/go-containerregistry/pkg/crane"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/registry"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/daemon"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
@ -156,24 +160,73 @@ kind: Bar
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBuilderCanBuild(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
bo := &options.BuildOptions{
|
||||
ConcurrentBuilds: 1,
|
||||
}
|
||||
builder, err := NewBuilder(ctx, bo)
|
||||
func TestNewBuilder(t *testing.T) {
|
||||
namespace := "base"
|
||||
s, err := registryServerWithImage(namespace)
|
||||
if err != nil {
|
||||
t.Fatalf("NewBuilder(): %v", err)
|
||||
t.Fatalf("could not create test registry server: %v", err)
|
||||
}
|
||||
res, err := builder.Build(ctx, "ko://github.com/google/ko/test")
|
||||
if err != nil {
|
||||
t.Fatalf("builder.Build(): %v", err)
|
||||
baseImage := fmt.Sprintf("%s/%s", s.Listener.Addr().String(), namespace)
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
importpath string
|
||||
bo *options.BuildOptions
|
||||
wantQualifiedImportpath string
|
||||
shouldBuildError bool
|
||||
}{
|
||||
{
|
||||
description: "test app with already qualified import path",
|
||||
importpath: "ko://github.com/google/ko/test",
|
||||
bo: &options.BuildOptions{
|
||||
BaseImage: baseImage,
|
||||
ConcurrentBuilds: 1,
|
||||
},
|
||||
wantQualifiedImportpath: "ko://github.com/google/ko/test",
|
||||
shouldBuildError: false,
|
||||
},
|
||||
{
|
||||
description: "programmatic build config",
|
||||
importpath: "./test",
|
||||
bo: &options.BuildOptions{
|
||||
BaseImage: baseImage,
|
||||
BuildConfigs: map[string]build.Config{
|
||||
"github.com/google/ko/test": {
|
||||
ID: "id-can-be-anything",
|
||||
// no easy way to assert on the output, so trigger error to ensure config is picked up
|
||||
Flags: []string{"-invalid-flag-should-cause-error"},
|
||||
},
|
||||
},
|
||||
ConcurrentBuilds: 1,
|
||||
WorkingDirectory: "../..",
|
||||
},
|
||||
wantQualifiedImportpath: "ko://github.com/google/ko/test",
|
||||
shouldBuildError: true,
|
||||
},
|
||||
}
|
||||
gotDigest, err := res.Digest()
|
||||
if err != nil {
|
||||
t.Fatalf("res.Digest(): %v", err)
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
builder, err := NewBuilder(ctx, test.bo)
|
||||
if err != nil {
|
||||
t.Fatalf("NewBuilder(): %v", err)
|
||||
}
|
||||
qualifiedImportpath, err := builder.QualifyImport(test.importpath)
|
||||
if err != nil {
|
||||
t.Fatalf("builder.QualifyImport(%s): %v", test.importpath, err)
|
||||
}
|
||||
if qualifiedImportpath != test.wantQualifiedImportpath {
|
||||
t.Fatalf("incorrect qualified import path, got %s, wanted %s", qualifiedImportpath, test.wantQualifiedImportpath)
|
||||
}
|
||||
_, err = builder.Build(ctx, qualifiedImportpath)
|
||||
if err != nil && !test.shouldBuildError {
|
||||
t.Fatalf("builder.Build(): %v", err)
|
||||
}
|
||||
if err == nil && test.shouldBuildError {
|
||||
t.Fatalf("expected error got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
fmt.Println(gotDigest.String())
|
||||
}
|
||||
|
||||
func TestNewPublisherCanPublish(t *testing.T) {
|
||||
@ -224,29 +277,47 @@ func TestNewPublisherCanPublish(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
publisher, err := NewPublisher(test.po)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: NewPublisher(): %v", test.description, err)
|
||||
}
|
||||
defer publisher.Close()
|
||||
ref, err := publisher.Publish(context.Background(), empty.Image, build.StrictScheme+importpath)
|
||||
if test.shouldError {
|
||||
if err == nil || !strings.HasSuffix(err.Error(), test.wantError.Error()) {
|
||||
t.Errorf("%s: got error %v, wanted %v", test.description, err, test.wantError)
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
publisher, err := NewPublisher(test.po)
|
||||
if err != nil {
|
||||
t.Fatalf("NewPublisher(): %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("%s: publisher.Publish(): %v", test.description, err)
|
||||
}
|
||||
fmt.Printf("ref: %+v\n", ref)
|
||||
gotImageName := ref.Context().Name()
|
||||
if gotImageName != test.wantImageName {
|
||||
t.Errorf("%s: got %s, wanted %s", test.description, gotImageName, test.wantImageName)
|
||||
}
|
||||
defer publisher.Close()
|
||||
ref, err := publisher.Publish(context.Background(), empty.Image, build.StrictScheme+importpath)
|
||||
if test.shouldError {
|
||||
if err == nil || !strings.HasSuffix(err.Error(), test.wantError.Error()) {
|
||||
t.Errorf("%s: got error %v, wanted %v", test.description, err, test.wantError)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("publisher.Publish(): %v", err)
|
||||
}
|
||||
gotImageName := ref.Context().Name()
|
||||
if gotImageName != test.wantImageName {
|
||||
t.Errorf("got %s, wanted %s", gotImageName, test.wantImageName)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// registryServerWithImage starts a local registry and pushes a random image.
|
||||
// Use this to speed up tests, by not having to reach out to gcr.io for the default base image.
|
||||
// The registry uses a NOP logger to avoid spamming test logs.
|
||||
// Remember to call `defer Close()` on the returned `httptest.Server`.
|
||||
func registryServerWithImage(namespace string) (*httptest.Server, error) {
|
||||
nopLog := log.New(ioutil.Discard, "", 0)
|
||||
r := registry.New(registry.Logger(nopLog))
|
||||
s := httptest.NewServer(r)
|
||||
imageName := fmt.Sprintf("%s/%s", s.Listener.Addr().String(), namespace)
|
||||
image, err := random.Image(1024, 1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("random.Image(): %v", err)
|
||||
}
|
||||
crane.Push(image, imageName)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func mustRepository(s string) name.Repository {
|
||||
n, err := name.NewRepository(s)
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user