From b89023578cdcdc574236202778df823f63f98fcd Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Mon, 5 Oct 2020 17:34:54 -0400 Subject: [PATCH] Avoid panic caused by MultiPublisher MultiPublisher now returns an error when it's configured with no publishers, and resolver.go now appends a nop publisher when it's configured not to publish, that simulates a publish without actually pushing any images. . --- pkg/commands/resolver.go | 27 +++++++++++++++++++++++++++ pkg/publish/multi.go | 7 ++++++- pkg/publish/multi_test.go | 12 ++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/pkg/commands/resolver.go b/pkg/commands/resolver.go index 579659ecda..24d18961c4 100644 --- a/pkg/commands/resolver.go +++ b/pkg/commands/resolver.go @@ -160,6 +160,16 @@ func makePublisher(po *options.PublishOptions) (publish.Interface, error) { } publishers = append(publishers, dp) } + + // If not publishing, at least generate a digest to simulate + // publishing. + if len(publishers) == 0 { + publishers = append(publishers, nopPublisher{ + repoName: repoName, + namer: namer, + }) + } + return publish.MultiPublisher(publishers...), nil }() if err != nil { @@ -170,6 +180,23 @@ func makePublisher(po *options.PublishOptions) (publish.Interface, error) { return publish.NewCaching(innerPublisher) } +// nopPublisher simulates publishing without actually publishing anything, to +// provide fallback behavior when the user configures no push destinations. +type nopPublisher struct { + repoName string + namer publish.Namer +} + +func (n nopPublisher) Publish(br build.Result, s string) (name.Reference, error) { + h, err := br.Digest() + if err != nil { + return nil, err + } + return name.NewDigest(fmt.Sprintf("%s/%s@%s", n.repoName, n.namer(s), h)) +} + +func (n nopPublisher) Close() error { return nil } + // resolvedFuture represents a "future" for the bytes of a resolved file. type resolvedFuture chan []byte diff --git a/pkg/publish/multi.go b/pkg/publish/multi.go index f4c2f8e73a..6824000596 100644 --- a/pkg/publish/multi.go +++ b/pkg/publish/multi.go @@ -15,6 +15,8 @@ package publish import ( + "errors" + "github.com/google/go-containerregistry/pkg/name" "github.com/google/ko/pkg/build" ) @@ -34,13 +36,16 @@ type multiPublisher struct { // Publish implements publish.Interface. func (p *multiPublisher) Publish(br build.Result, s string) (ref name.Reference, err error) { + if len(p.publishers) == 0 { + return nil, errors.New("MultiPublisher configured with zero publishers") + } + for _, pub := range p.publishers { ref, err = pub.Publish(br, s) if err != nil { return } } - return } diff --git a/pkg/publish/multi_test.go b/pkg/publish/multi_test.go index 46ed21205a..4112fa29de 100644 --- a/pkg/publish/multi_test.go +++ b/pkg/publish/multi_test.go @@ -61,3 +61,15 @@ func TestMulti(t *testing.T) { t.Errorf("Close() = %v", err) } } + +func TestMulti_Zero(t *testing.T) { + img, err := random.Image(1024, 1) + if err != nil { + t.Fatalf("random.Image() = %v", err) + } + + p := MultiPublisher() // No publishers. + if _, err := p.Publish(img, "foo"); err == nil { + t.Errorf("Publish() got nil error") + } +}