Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for --image-refs #555

Merged
merged 2 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/ko_apply.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ ko apply -f FILENAME [flags]
-f, --filename strings Filename, directory, or URL to files to use to create the resource
-h, --help help for apply
--image-label strings Which labels (key=value) to add to the image.
--image-refs string Path to file where a list of the published image references will be written.
--insecure-registry Whether to skip TLS verification on the registry
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure (DEPRECATED)
-j, --jobs int The maximum number of concurrent builds (default GOMAXPROCS)
Expand Down
1 change: 1 addition & 0 deletions doc/ko_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ ko build IMPORTPATH... [flags]
--disable-optimizations Disable optimizations when building Go code. Useful when you want to interactively debug the created container.
-h, --help help for build
--image-label strings Which labels (key=value) to add to the image.
--image-refs string Path to file where a list of the published image references will be written.
--insecure-registry Whether to skip TLS verification on the registry
-j, --jobs int The maximum number of concurrent builds (default GOMAXPROCS)
-L, --local Load into images to local docker daemon.
Expand Down
1 change: 1 addition & 0 deletions doc/ko_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ ko create -f FILENAME [flags]
-f, --filename strings Filename, directory, or URL to files to use to create the resource
-h, --help help for create
--image-label strings Which labels (key=value) to add to the image.
--image-refs string Path to file where a list of the published image references will be written.
--insecure-registry Whether to skip TLS verification on the registry
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure (DEPRECATED)
-j, --jobs int The maximum number of concurrent builds (default GOMAXPROCS)
Expand Down
1 change: 1 addition & 0 deletions doc/ko_resolve.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ ko resolve -f FILENAME [flags]
-f, --filename strings Filename, directory, or URL to files to use to create the resource
-h, --help help for resolve
--image-label strings Which labels (key=value) to add to the image.
--image-refs string Path to file where a list of the published image references will be written.
--insecure-registry Whether to skip TLS verification on the registry
-j, --jobs int The maximum number of concurrent builds (default GOMAXPROCS)
-L, --local Load into images to local docker daemon.
Expand Down
1 change: 1 addition & 0 deletions doc/ko_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ ko run IMPORTPATH [flags]
--disable-optimizations Disable optimizations when building Go code. Useful when you want to interactively debug the created container.
-h, --help help for run
--image-label strings Which labels (key=value) to add to the image.
--image-refs string Path to file where a list of the published image references will be written.
--insecure-registry Whether to skip TLS verification on the registry
-j, --jobs int The maximum number of concurrent builds (default GOMAXPROCS)
-L, --local Load into images to local docker daemon.
Expand Down
5 changes: 5 additions & 0 deletions pkg/commands/options/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ type PublishOptions struct {
OCILayoutPath string
TarballFile string

ImageRefsFile string

// PreserveImportPaths preserves the full import path after KO_DOCKER_REPO.
PreserveImportPaths bool
// BaseImportPaths uses the base path without MD5 hash after KO_DOCKER_REPO.
Expand Down Expand Up @@ -93,6 +95,9 @@ func AddPublishArg(cmd *cobra.Command, po *PublishOptions) {
cmd.Flags().StringVar(&po.OCILayoutPath, "oci-layout-path", "", "Path to save the OCI image layout of the built images")
cmd.Flags().StringVar(&po.TarballFile, "tarball", "", "File to save images tarballs")

cmd.Flags().StringVar(&po.ImageRefsFile, "image-refs", "",
"Path to file where a list of the published image references will be written.")

cmd.Flags().BoolVarP(&po.PreserveImportPaths, "preserve-import-paths", "P", po.PreserveImportPaths,
"Whether to preserve the full import path after KO_DOCKER_REPO.")
cmd.Flags().BoolVarP(&po.BaseImportPaths, "base-import-paths", "B", po.BaseImportPaths,
Expand Down
14 changes: 13 additions & 1 deletion pkg/commands/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ func makePublisher(po *options.PublishOptions) (publish.Interface, error) {
publish.WithNamer(namer),
publish.WithTags(po.Tags),
publish.WithTagOnly(po.TagOnly),
publish.Insecure(po.InsecureRegistry))
publish.Insecure(po.InsecureRegistry),
)
if err != nil {
return nil, err
}
Expand All @@ -237,6 +238,17 @@ func makePublisher(po *options.PublishOptions) (publish.Interface, error) {
return nil, err
}

if po.ImageRefsFile != "" {
f, err := os.OpenFile(po.ImageRefsFile, os.O_RDWR|os.O_CREATE, 0600)
if err != nil {
return nil, err
}
innerPublisher, err = publish.NewRecorder(innerPublisher, f)
if err != nil {
return nil, err
}
}

// Wrap publisher in a memoizing publisher implementation.
return publish.NewCaching(innerPublisher)
}
Expand Down
65 changes: 65 additions & 0 deletions pkg/publish/recorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2021 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package publish

import (
"context"
"io"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/ko/pkg/build"
)

// recorder wraps a publisher implementation in a layer that recordes the published
// references to an io.Writer.
type recorder struct {
inner Interface
wc io.Writer
}

// recorder implements Interface
var _ Interface = (*recorder)(nil)

// NewRecorder wraps the provided publish.Interface in an implementation that
// records publish results to an io.Writer.
func NewRecorder(inner Interface, wc io.Writer) (Interface, error) {
return &recorder{
inner: inner,
wc: wc,
}, nil
}

// Publish implements Interface
func (r *recorder) Publish(ctx context.Context, br build.Result, ref string) (name.Reference, error) {
result, err := r.inner.Publish(ctx, br, ref)
if err != nil {
return nil, err
}
if _, err := r.wc.Write([]byte(result.String() + "\n")); err != nil {
return nil, err
}
return result, nil
}

// Close implements Interface
func (r *recorder) Close() error {
imjasonh marked this conversation as resolved.
Show resolved Hide resolved
if err := r.inner.Close(); err != nil {
return err
}
if c, ok := r.wc.(io.Closer); ok {
return c.Close()
}
return nil
}
72 changes: 72 additions & 0 deletions pkg/publish/recorder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2021 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package publish

import (
"bytes"
"context"
"fmt"
"testing"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/ko/pkg/build"
)

type cbPublish struct {
cb func(context.Context, build.Result, string) (name.Reference, error)
}

var _ Interface = (*cbPublish)(nil)

func (sp *cbPublish) Publish(ctx context.Context, br build.Result, ref string) (name.Reference, error) {
return sp.cb(ctx, br, ref)
}

func (sp *cbPublish) Close() error {
return nil
}

func TestRecorder(t *testing.T) {
num := 0
inner := &cbPublish{cb: func(c context.Context, b build.Result, s string) (name.Reference, error) {
num++
return name.ParseReference(fmt.Sprintf("ubuntu:%d", num))
}}

buf := bytes.NewBuffer(nil)

recorder, err := NewRecorder(inner, buf)
if err != nil {
t.Fatalf("NewRecorder() = %v", err)
}

if _, err := recorder.Publish(context.Background(), nil, ""); err != nil {
t.Errorf("recorder.Publish() = %v", err)
}
if _, err := recorder.Publish(context.Background(), nil, ""); err != nil {
t.Errorf("recorder.Publish() = %v", err)
}
if _, err := recorder.Publish(context.Background(), nil, ""); err != nil {
t.Errorf("recorder.Publish() = %v", err)
}
if err := recorder.Close(); err != nil {
t.Errorf("recorder.Close() = %v", err)
}

want, got := "ubuntu:1\nubuntu:2\nubuntu:3\n", buf.String()
if got != want {
t.Errorf("buf.String() = %s, wanted %s", got, want)
}
}