1
0
mirror of https://github.com/ko-build/ko.git synced 2024-12-15 09:04:09 +02:00
ko-build/pkg/publish/default.go
tanner-bruce 48afd62710 Allow skipping TLS verification while publishing (#65)
Why this is necessary: when using a local docker registry, users may not
want to support https, or there may be other troubles not allowing
verifiable TLS support.

This commit adds this functionality by adding an `--insecure-registry`
flag.
2019-07-24 10:58:10 -07:00

130 lines
3.5 KiB
Go

// Copyright 2018 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 (
"fmt"
"log"
"net/http"
"strings"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
// defalt is intentionally misspelled to avoid keyword collision (and drive Jon nuts).
type defalt struct {
base string
t http.RoundTripper
auth authn.Authenticator
namer Namer
tags []string
insecure bool
}
// Option is a functional option for NewDefault.
type Option func(*defaultOpener) error
type defaultOpener struct {
base string
t http.RoundTripper
auth authn.Authenticator
namer Namer
tags []string
insecure bool
}
// Namer is a function from a supported import path to the portion of the resulting
// image name that follows the "base" repository name.
type Namer func(string) string
// identity is the default namer, so import paths are affixed as-is under the repository
// name for maximum clarity, e.g.
// gcr.io/foo/github.com/bar/baz/cmd/blah
// ^--base--^ ^-------import path-------^
func identity(in string) string { return in }
// As some registries do not support pushing an image by digest, the default tag for pushing
// is the 'latest' tag.
var defaultTags = []string{"latest"}
func (do *defaultOpener) Open() (Interface, error) {
return &defalt{
base: do.base,
t: do.t,
auth: do.auth,
namer: do.namer,
tags: do.tags,
insecure: do.insecure,
}, nil
}
// NewDefault returns a new publish.Interface that publishes references under the provided base
// repository using the default keychain to authenticate and the default naming scheme.
func NewDefault(base string, options ...Option) (Interface, error) {
do := &defaultOpener{
base: base,
t: http.DefaultTransport,
auth: authn.Anonymous,
namer: identity,
tags: defaultTags,
}
for _, option := range options {
if err := option(do); err != nil {
return nil, err
}
}
return do.Open()
}
// Publish implements publish.Interface
func (d *defalt) Publish(img v1.Image, s string) (name.Reference, error) {
// https://github.com/google/go-containerregistry/issues/212
s = strings.ToLower(s)
for _, tagName := range d.tags {
var os []name.Option
if d.insecure {
os = []name.Option{name.Insecure}
}
tag, err := name.NewTag(fmt.Sprintf("%s/%s:%s", d.base, d.namer(s), tagName), os...)
if err != nil {
return nil, err
}
log.Printf("Publishing %v", tag)
// TODO: This is slow because we have to load the image multiple times.
// Figure out some way to publish the manifest with another tag.
if err := remote.Write(tag, img, remote.WithAuth(d.auth), remote.WithTransport(d.t)); err != nil {
return nil, err
}
}
h, err := img.Digest()
if err != nil {
return nil, err
}
dig, err := name.NewDigest(fmt.Sprintf("%s/%s@%s", d.base, d.namer(s), h))
if err != nil {
return nil, err
}
log.Printf("Published %v", dig)
return &dig, nil
}