From 746c861e29fcf402b18636860b26dc0da4a51324 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:53:34 -0500 Subject: [PATCH 1/5] chore: add ko env --- pkg/skaffold/build/ko/build.go | 2 +- pkg/skaffold/build/ko/builder.go | 36 ++++++++++++++++++++++++--- pkg/skaffold/build/ko/builder_test.go | 2 +- 3 files changed, 35 insertions(+), 5 deletions(-) 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..dd4bb91acdc 100644 --- a/pkg/skaffold/build/ko/builder.go +++ b/pkg/skaffold/build/ko/builder.go @@ -19,6 +19,8 @@ package ko import ( "context" "fmt" + "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/constants" + "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/docker" "path/filepath" "strings" @@ -33,15 +35,43 @@ import ( "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) { + envs, err := b.runtimeEnv(a, tag, platforms) + 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, envs) 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) { +func (b *Builder) runtimeEnv(a *latest.Artifact, tag string, platforms platform.Matcher) ([]string, error) { + buildContext, err := filepath.Abs(a.Workspace) + if err != nil { + return nil, fmt.Errorf("getting absolute path for artifact build context: %w", err) + } + + envs := []string{ + fmt.Sprintf("%s=%s", constants.Image, tag), + fmt.Sprintf("%s=%t", constants.PushImage, b.pushImages), + fmt.Sprintf("%s=%s", constants.BuildContext, buildContext), + fmt.Sprintf("%s=%s", constants.Platforms, platforms.String()), + } + + ref, err := docker.ParseReference(tag) + if err != nil { + return nil, fmt.Errorf("parsing image %v: %w", tag, err) + } + + // Standardize access to Image reference fields in templates + envs = append(envs, fmt.Sprintf("%s=%s", constants.ImageRef.Repo, ref.BaseName)) + envs = append(envs, fmt.Sprintf("%s=%s", constants.ImageRef.Tag, ref.Tag)) + return envs, nil +} + +func buildOptions(a *latest.Artifact, runMode config.RunMode, platforms platform.Matcher, envs []string) (*options.BuildOptions, error) { buildconfig, err := buildConfig(a) if err != nil { return nil, fmt.Errorf("could not create ko build config: %v", err) diff --git a/pkg/skaffold/build/ko/builder_test.go b/pkg/skaffold/build/ko/builder_test.go index 5e46cba4d0c..3639b7227ed 100644 --- a/pkg/skaffold/build/ko/builder_test.go +++ b/pkg/skaffold/build/ko/builder_test.go @@ -154,7 +154,7 @@ func TestBuildOptions(t *testing.T) { 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, "") t.CheckErrorAndFailNow(false, err) t.CheckDeepEqual(test.wantBo, *gotBo, cmpopts.EquateEmpty(), From 2eb1af11c3bdeb200d2f7b8caa820a8b6facd690 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:19:27 -0500 Subject: [PATCH 2/5] chore: inject imageInfo when expanding go template for ko builder --- pkg/skaffold/build/ko/builder.go | 56 +++++++++------------------ pkg/skaffold/build/ko/builder_test.go | 2 +- 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/pkg/skaffold/build/ko/builder.go b/pkg/skaffold/build/ko/builder.go index dd4bb91acdc..8756c081d68 100644 --- a/pkg/skaffold/build/ko/builder.go +++ b/pkg/skaffold/build/ko/builder.go @@ -19,8 +19,6 @@ package ko import ( "context" "fmt" - "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/constants" - "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/docker" "path/filepath" "strings" @@ -29,6 +27,7 @@ import ( "github.com/google/ko/pkg/commands/options" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/config" + "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" @@ -36,43 +35,26 @@ import ( ) func (b *Builder) newKoBuilder(ctx context.Context, a *latest.Artifact, platforms platform.Matcher, tag string) (build.Interface, error) { - envs, err := b.runtimeEnv(a, tag, platforms) + ref, err := docker.ParseReference(tag) if err != nil { - return nil, fmt.Errorf("could not resolve skaffold runtime env for ko builder: %v", err) + return nil, fmt.Errorf("parsing image %v: %w", tag, err) } - bo, err := buildOptions(a, b.runMode, platforms, envs) - if err != nil { - return nil, fmt.Errorf("could not construct ko build options: %v", err) + imageInfoEnv := map[string]string{ + "IMAGE_REPO": ref.Repo, + "IMAGE_NAME": ref.Name, + "IMAGE_TAG": ref.Tag, } - return commands.NewBuilder(ctx, bo) -} - -func (b *Builder) runtimeEnv(a *latest.Artifact, tag string, platforms platform.Matcher) ([]string, error) { - buildContext, err := filepath.Abs(a.Workspace) if err != nil { - return nil, fmt.Errorf("getting absolute path for artifact build context: %w", err) - } - - envs := []string{ - fmt.Sprintf("%s=%s", constants.Image, tag), - fmt.Sprintf("%s=%t", constants.PushImage, b.pushImages), - fmt.Sprintf("%s=%s", constants.BuildContext, buildContext), - fmt.Sprintf("%s=%s", constants.Platforms, platforms.String()), + return nil, fmt.Errorf("could not resolve skaffold runtime env for ko builder: %v", err) } - - ref, err := docker.ParseReference(tag) + bo, err := buildOptions(a, b.runMode, platforms, imageInfoEnv) if err != nil { - return nil, fmt.Errorf("parsing image %v: %w", tag, err) + return nil, fmt.Errorf("could not construct ko build options: %v", err) } - - // Standardize access to Image reference fields in templates - envs = append(envs, fmt.Sprintf("%s=%s", constants.ImageRef.Repo, ref.BaseName)) - envs = append(envs, fmt.Sprintf("%s=%s", constants.ImageRef.Tag, ref.Tag)) - return envs, nil + return commands.NewBuilder(ctx, bo) } - -func buildOptions(a *latest.Artifact, runMode config.RunMode, platforms platform.Matcher, envs []string) (*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) } @@ -98,7 +80,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 @@ -107,15 +89,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) } @@ -166,12 +148,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 3639b7227ed..f1f364fdf65 100644 --- a/pkg/skaffold/build/ko/builder_test.go +++ b/pkg/skaffold/build/ko/builder_test.go @@ -154,7 +154,7 @@ func TestBuildOptions(t *testing.T) { 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, nil) t.CheckErrorAndFailNow(false, err) t.CheckDeepEqual(test.wantBo, *gotBo, cmpopts.EquateEmpty(), From 55a1d0d82b6ab70bb68a26f471581c8295583d43 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Tue, 5 Dec 2023 10:59:30 -0500 Subject: [PATCH 3/5] chore: add test --- pkg/skaffold/build/ko/builder_test.go | 36 ++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/pkg/skaffold/build/ko/builder_test.go b/pkg/skaffold/build/ko/builder_test.go index f1f364fdf65..5401ae0d2ff 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: "", + 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, nil) + gotBo, err := buildOptions(&test.artifact, test.runMode, test.platforms, test.envs) t.CheckErrorAndFailNow(false, err) t.CheckDeepEqual(test.wantBo, *gotBo, cmpopts.EquateEmpty(), From 20b6a65a0b85ad1b5be9650cffb78e3433f66644 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Tue, 5 Dec 2023 11:05:18 -0500 Subject: [PATCH 4/5] chore: add test --- integration/run_test.go | 5 +++++ 1 file changed, 5 insertions(+) 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", From e4568e40ea84ce6ac13f47288156450fdb3def1e Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:45:54 -0500 Subject: [PATCH 5/5] chore: use contants to ref imageInfo --- pkg/skaffold/build/ko/builder.go | 7 ++++--- pkg/skaffold/build/ko/builder_test.go | 2 +- pkg/skaffold/constants/constants.go | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/skaffold/build/ko/builder.go b/pkg/skaffold/build/ko/builder.go index 8756c081d68..884c6f82f4c 100644 --- a/pkg/skaffold/build/ko/builder.go +++ b/pkg/skaffold/build/ko/builder.go @@ -27,6 +27,7 @@ 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" @@ -40,9 +41,9 @@ func (b *Builder) newKoBuilder(ctx context.Context, a *latest.Artifact, platform return nil, fmt.Errorf("parsing image %v: %w", tag, err) } imageInfoEnv := map[string]string{ - "IMAGE_REPO": ref.Repo, - "IMAGE_NAME": ref.Name, - "IMAGE_TAG": ref.Tag, + 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) diff --git a/pkg/skaffold/build/ko/builder_test.go b/pkg/skaffold/build/ko/builder_test.go index 5401ae0d2ff..783265b6e9a 100644 --- a/pkg/skaffold/build/ko/builder_test.go +++ b/pkg/skaffold/build/ko/builder_test.go @@ -152,7 +152,7 @@ func TestBuildOptions(t *testing.T) { }, }, { - description: "", + description: "test build option, inject envs for expanding templates", artifact: latest.Artifact{ ArtifactType: latest.ArtifactType{ KoArtifact: &latest.KoArtifact{ 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"}