2021-05-26 04:44:52 +10:00
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
2019-03-14 14:23:47 -04:00
|
|
|
|
2019-04-26 15:56:15 -07:00
|
|
|
package commands
|
2019-03-14 14:23:47 -04:00
|
|
|
|
|
|
|
import (
|
2019-11-10 01:23:09 +08:00
|
|
|
"context"
|
2019-03-14 14:23:47 -04:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
2020-04-20 09:13:33 -07:00
|
|
|
"strings"
|
2019-03-14 14:23:47 -04:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/google/go-containerregistry/pkg/authn"
|
|
|
|
"github.com/google/go-containerregistry/pkg/name"
|
|
|
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
2021-06-09 09:20:45 -07:00
|
|
|
"github.com/google/go-containerregistry/pkg/v1/daemon"
|
2019-03-14 14:23:47 -04:00
|
|
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
2021-10-21 16:14:06 +11:00
|
|
|
|
2020-09-24 15:58:08 -07:00
|
|
|
"github.com/google/ko/pkg/build"
|
2021-05-26 04:44:52 +10:00
|
|
|
"github.com/google/ko/pkg/commands/options"
|
2021-06-09 09:20:45 -07:00
|
|
|
"github.com/google/ko/pkg/publish"
|
2019-03-14 14:23:47 -04:00
|
|
|
)
|
|
|
|
|
2021-05-26 04:44:52 +10:00
|
|
|
// getBaseImage returns a function that determines the base image for a given import path.
|
2021-12-15 16:08:27 -05:00
|
|
|
func getBaseImage(bo *options.BuildOptions) build.GetBase {
|
2021-12-08 06:28:15 -08:00
|
|
|
cache := map[string]build.Result{}
|
|
|
|
fetch := func(ctx context.Context, ref name.Reference) (build.Result, error) {
|
2021-06-09 09:20:45 -07:00
|
|
|
// For ko.local, look in the daemon.
|
|
|
|
if ref.Context().RegistryStr() == publish.LocalDomain {
|
2021-12-08 06:28:15 -08:00
|
|
|
return daemon.Image(ref)
|
2021-06-09 09:20:45 -07:00
|
|
|
}
|
|
|
|
|
2021-05-26 04:44:52 +10:00
|
|
|
userAgent := ua()
|
|
|
|
if bo.UserAgent != "" {
|
|
|
|
userAgent = bo.UserAgent
|
|
|
|
}
|
2020-09-24 15:58:08 -07:00
|
|
|
ropt := []remote.Option{
|
|
|
|
remote.WithAuthFromKeychain(authn.DefaultKeychain),
|
2021-05-26 04:44:52 +10:00
|
|
|
remote.WithUserAgent(userAgent),
|
2020-12-21 11:47:05 -08:00
|
|
|
remote.WithContext(ctx),
|
2020-09-24 15:58:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
desc, err := remote.Get(ref, ropt...)
|
|
|
|
if err != nil {
|
2021-12-08 06:28:15 -08:00
|
|
|
return nil, err
|
2020-09-24 15:58:08 -07:00
|
|
|
}
|
2022-01-27 17:06:35 -05:00
|
|
|
if desc.MediaType.IsIndex() {
|
|
|
|
return desc.ImageIndex()
|
2021-12-08 06:28:15 -08:00
|
|
|
}
|
2022-01-27 17:06:35 -05:00
|
|
|
return desc.Image()
|
2021-12-08 06:28:15 -08:00
|
|
|
}
|
|
|
|
return func(ctx context.Context, s string) (name.Reference, build.Result, error) {
|
|
|
|
s = strings.TrimPrefix(s, build.StrictScheme)
|
|
|
|
// Viper configuration file keys are case insensitive, and are
|
|
|
|
// returned as all lowercase. This means that import paths with
|
|
|
|
// uppercase must be normalized for matching here, e.g.
|
|
|
|
// github.com/GoogleCloudPlatform/foo/cmd/bar
|
|
|
|
// comes through as:
|
|
|
|
// github.com/googlecloudplatform/foo/cmd/bar
|
|
|
|
baseImage, ok := bo.BaseImageOverrides[strings.ToLower(s)]
|
|
|
|
if !ok || baseImage == "" {
|
|
|
|
baseImage = bo.BaseImage
|
2020-09-24 15:58:08 -07:00
|
|
|
}
|
2021-12-08 06:28:15 -08:00
|
|
|
var nameOpts []name.Option
|
|
|
|
if bo.InsecureRegistry {
|
|
|
|
nameOpts = append(nameOpts, name.Insecure)
|
|
|
|
}
|
|
|
|
ref, err := name.ParseReference(baseImage, nameOpts...)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("parsing base image (%q): %w", baseImage, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if cached, ok := cache[ref.String()]; ok {
|
|
|
|
return ref, cached, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Using base %s for %s", ref, s)
|
|
|
|
result, err := fetch(ctx, ref)
|
|
|
|
if err != nil {
|
|
|
|
return ref, result, err
|
|
|
|
}
|
|
|
|
|
|
|
|
cache[ref.String()] = result
|
|
|
|
return ref, result, nil
|
2019-03-14 14:23:47 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-15 21:50:35 +02:00
|
|
|
func getTimeFromEnv(env string) (*v1.Time, error) {
|
|
|
|
epoch := os.Getenv(env)
|
2019-03-14 14:23:47 -04:00
|
|
|
if epoch == "" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
seconds, err := strconv.ParseInt(epoch, 10, 64)
|
|
|
|
if err != nil {
|
2021-11-05 13:26:09 -04:00
|
|
|
return nil, fmt.Errorf("the environment variable %s should be the number of seconds since January 1st 1970, 00:00 UTC, got: %w", env, err)
|
2019-03-14 14:23:47 -04:00
|
|
|
}
|
2020-08-10 17:21:31 +02:00
|
|
|
return &v1.Time{Time: time.Unix(seconds, 0)}, nil
|
2019-03-14 14:23:47 -04:00
|
|
|
}
|
|
|
|
|
2021-06-15 21:50:35 +02:00
|
|
|
func getCreationTime() (*v1.Time, error) {
|
|
|
|
return getTimeFromEnv("SOURCE_DATE_EPOCH")
|
|
|
|
}
|
|
|
|
|
|
|
|
func getKoDataCreationTime() (*v1.Time, error) {
|
|
|
|
return getTimeFromEnv("KO_DATA_DATE_EPOCH")
|
|
|
|
}
|