From aec8e3e78beaeb874b7c08b06ff4514b68c225a8 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Tue, 12 Dec 2023 20:30:44 -0500 Subject: [PATCH] chore: inject imageInfo when expanding templates for ko builder (#9207) * chore: add ko env * chore: inject imageInfo when expanding go template for ko builder * chore: add test * chore: add test * chore: use contants to ref imageInfo --- integration/run_test.go | 5 ++++ pkg/skaffold/build/ko/build.go | 2 +- pkg/skaffold/build/ko/builder.go | 35 ++++++++++++++++++-------- pkg/skaffold/build/ko/builder_test.go | 36 ++++++++++++++++++++++++++- pkg/skaffold/constants/constants.go | 2 ++ 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/integration/run_test.go b/integration/run_test.go index 5409b8da40e..59d03d6d389 100644 --- a/integration/run_test.go +++ b/integration/run_test.go @@ -61,6 +61,11 @@ var tests = []struct { pods: []string{"getting-started"}, targetLog: "Hello world!", }, + { + description: "ko", + dir: "examples/ko", + deployments: []string{"ko"}, + }, { description: "nodejs", dir: "examples/nodejs", diff --git a/pkg/skaffold/build/ko/build.go b/pkg/skaffold/build/ko/build.go index ec89e568584..1ad894632a5 100644 --- a/pkg/skaffold/build/ko/build.go +++ b/pkg/skaffold/build/ko/build.go @@ -41,7 +41,7 @@ func (b *Builder) Build(ctx context.Context, out io.Writer, a *latest.Artifact, if b.pushImages && strings.HasPrefix(ref, build.StrictScheme) { return "", fmt.Errorf("default repo must be set when using the 'ko://' prefix and pushing to a registry: %s, see https://skaffold.dev/docs/environment/image-registries/", a.ImageName) } - koBuilder, err := b.newKoBuilder(ctx, a, platforms) + koBuilder, err := b.newKoBuilder(ctx, a, platforms, ref) if err != nil { return "", fmt.Errorf("error creating ko builder: %w", err) } diff --git a/pkg/skaffold/build/ko/builder.go b/pkg/skaffold/build/ko/builder.go index eae0cf60d83..884c6f82f4c 100644 --- a/pkg/skaffold/build/ko/builder.go +++ b/pkg/skaffold/build/ko/builder.go @@ -27,22 +27,35 @@ import ( "github.com/google/ko/pkg/commands/options" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/config" + "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/constants" + "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/docker" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/platform" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/util" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/version" ) -func (b *Builder) newKoBuilder(ctx context.Context, a *latest.Artifact, platforms platform.Matcher) (build.Interface, error) { - bo, err := buildOptions(a, b.runMode, platforms) +func (b *Builder) newKoBuilder(ctx context.Context, a *latest.Artifact, platforms platform.Matcher, tag string) (build.Interface, error) { + ref, err := docker.ParseReference(tag) + if err != nil { + return nil, fmt.Errorf("parsing image %v: %w", tag, err) + } + imageInfoEnv := map[string]string{ + constants.ImageRef.Repo: ref.Repo, + constants.ImageRef.Name: ref.Name, + constants.ImageRef.Tag: ref.Tag, + } + if err != nil { + return nil, fmt.Errorf("could not resolve skaffold runtime env for ko builder: %v", err) + } + bo, err := buildOptions(a, b.runMode, platforms, imageInfoEnv) if err != nil { return nil, fmt.Errorf("could not construct ko build options: %v", err) } return commands.NewBuilder(ctx, bo) } - -func buildOptions(a *latest.Artifact, runMode config.RunMode, platforms platform.Matcher) (*options.BuildOptions, error) { - buildconfig, err := buildConfig(a) +func buildOptions(a *latest.Artifact, runMode config.RunMode, platforms platform.Matcher, envs map[string]string) (*options.BuildOptions, error) { + buildconfig, err := buildConfig(a, envs) if err != nil { return nil, fmt.Errorf("could not create ko build config: %v", err) } @@ -68,7 +81,7 @@ func buildOptions(a *latest.Artifact, runMode config.RunMode, platforms platform // A map entry is only required if the artifact config specifies fields that need to be part of ko build configs. // If none of these are specified, we can provide an empty `BuildConfigs` map. // In this case, ko falls back to build configs provided in `.ko.yaml`, or to the default zero config. -func buildConfig(a *latest.Artifact) (map[string]build.Config, error) { +func buildConfig(a *latest.Artifact, envs map[string]string) (map[string]build.Config, error) { buildconfigs := map[string]build.Config{} if !koArtifactSpecifiesBuildConfig(*a.KoArtifact) { return buildconfigs, nil @@ -77,15 +90,15 @@ func buildConfig(a *latest.Artifact) (map[string]build.Config, error) { if err != nil { return nil, fmt.Errorf("could not determine import path of image %s: %v", a.ImageName, err) } - env, err := expand(a.KoArtifact.Env) + env, err := expand(a.KoArtifact.Env, envs) if err != nil { return nil, fmt.Errorf("could not expand env: %v", err) } - flags, err := expand(a.KoArtifact.Flags) + flags, err := expand(a.KoArtifact.Flags, envs) if err != nil { return nil, fmt.Errorf("could not expand build flags: %v", err) } - ldflags, err := expand(a.KoArtifact.Ldflags) + ldflags, err := expand(a.KoArtifact.Ldflags, envs) if err != nil { return nil, fmt.Errorf("could not expand linker flags: %v", err) } @@ -136,12 +149,12 @@ func labels(a *latest.Artifact) ([]string, error) { return labels, nil } -func expand(dryValues []string) ([]string, error) { +func expand(dryValues []string, envs map[string]string) ([]string, error) { var expandedValues []string for _, rawValue := range dryValues { // support ko-style envvar templating syntax, see https://github.com/GoogleContainerTools/skaffold/issues/6916 rawValue = strings.ReplaceAll(rawValue, "{{.Env.", "{{.") - expandedValue, err := util.ExpandEnvTemplate(rawValue, nil) + expandedValue, err := util.ExpandEnvTemplate(rawValue, envs) if err != nil { return nil, err } diff --git a/pkg/skaffold/build/ko/builder_test.go b/pkg/skaffold/build/ko/builder_test.go index 5e46cba4d0c..783265b6e9a 100644 --- a/pkg/skaffold/build/ko/builder_test.go +++ b/pkg/skaffold/build/ko/builder_test.go @@ -40,6 +40,7 @@ const ( func TestBuildOptions(t *testing.T) { tests := []struct { description string + envs map[string]string artifact latest.Artifact platforms platform.Matcher envVarValue string @@ -150,11 +151,44 @@ func TestBuildOptions(t *testing.T) { UserAgent: version.UserAgentWithClient(), }, }, + { + description: "test build option, inject envs for expanding templates", + artifact: latest.Artifact{ + ArtifactType: latest.ArtifactType{ + KoArtifact: &latest.KoArtifact{ + Flags: []string{ + "-v", + fmt.Sprintf("-flag-{{.%s}}", "IMAGE_NAME"), + }, + Ldflags: []string{ + "-s", + fmt.Sprintf("-ldflag-{{.%s}}", "IMAGE_TAG"), + }, + }, + }, + ImageName: "ko://example.com/foo", + }, + envs: map[string]string{"IMAGE_NAME": "name", "IMAGE_TAG": "tag"}, + wantBo: options.BuildOptions{ + BuildConfigs: map[string]build.Config{ + "example.com/foo": { + ID: "ko://example.com/foo", + Dir: ".", + Flags: build.FlagArray{"-v", "-flag-name"}, + Ldflags: build.StringArray{"-s", "-ldflag-tag"}, + }, + }, + ConcurrentBuilds: 1, + SBOM: "none", + Trimpath: true, + UserAgent: version.UserAgentWithClient(), + }, + }, } for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { t.Setenv(testKoBuildOptionsEnvVar, test.envVarValue) - gotBo, err := buildOptions(&test.artifact, test.runMode, test.platforms) + gotBo, err := buildOptions(&test.artifact, test.runMode, test.platforms, test.envs) t.CheckErrorAndFailNow(false, err) t.CheckDeepEqual(test.wantBo, *gotBo, cmpopts.EquateEmpty(), diff --git a/pkg/skaffold/constants/constants.go b/pkg/skaffold/constants/constants.go index f113a9bc8ee..1e5ef4c1dd5 100644 --- a/pkg/skaffold/constants/constants.go +++ b/pkg/skaffold/constants/constants.go @@ -140,10 +140,12 @@ var ImageRef = struct { Repo string Tag string Digest string + Name string }{ Repo: "IMAGE_REPO", Tag: "IMAGE_TAG", Digest: "IMAGE_DIGEST", + Name: "IMAGE_NAME", } var DefaultKubectlManifests = []string{"k8s/*.yaml"}