Skip to content

Commit

Permalink
WIP - adding a new flag --append-image-name-suffix to append [os]-[ar…
Browse files Browse the repository at this point in the history
…ch]-[variant] to the image name when pushing a multi-arch buildpack or builder

Signed-off-by: Juan Bustamante <[email protected]>
  • Loading branch information
jjbustamante committed Jan 15, 2025
1 parent 0adeb45 commit b999752
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 42 deletions.
41 changes: 24 additions & 17 deletions internal/commands/builder_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ import (

// BuilderCreateFlags define flags provided to the CreateBuilder command
type BuilderCreateFlags struct {
Publish bool
BuilderTomlPath string
Registry string
Policy string
Flatten []string
Targets []string
Label map[string]string
Publish bool
AppendImageNameSuffix bool
BuilderTomlPath string
Registry string
Policy string
Flatten []string
Targets []string
Label map[string]string
}

// CreateBuilder creates a builder image, based on a builder config
Expand Down Expand Up @@ -97,18 +98,23 @@ Creating a custom builder allows you to control what buildpacks are used and wha
logger.Infof("Pro tip: use --targets flag OR [[targets]] in builder.toml to specify the desired platform")
}

if !flags.Publish && flags.AppendImageNameSuffix {
logger.Warnf("--append-image-name-suffix will be ignored, use combined with --publish")
}

imageName := args[0]
if err := pack.CreateBuilder(cmd.Context(), client.CreateBuilderOptions{
RelativeBaseDir: relativeBaseDir,
BuildConfigEnv: envMap,
BuilderName: imageName,
Config: builderConfig,
Publish: flags.Publish,
Registry: flags.Registry,
PullPolicy: pullPolicy,
Flatten: toFlatten,
Labels: flags.Label,
Targets: multiArchCfg.Targets(),
RelativeBaseDir: relativeBaseDir,
BuildConfigEnv: envMap,
BuilderName: imageName,
Config: builderConfig,
Publish: flags.Publish,
AppendImageNameSuffix: flags.AppendImageNameSuffix && flags.Publish,
Registry: flags.Registry,
PullPolicy: pullPolicy,
Flatten: toFlatten,
Labels: flags.Label,
Targets: multiArchCfg.Targets(),
}); err != nil {
return err
}
Expand All @@ -124,6 +130,7 @@ Creating a custom builder allows you to control what buildpacks are used and wha
}
cmd.Flags().StringVarP(&flags.BuilderTomlPath, "config", "c", "", "Path to builder TOML file (required)")
cmd.Flags().BoolVar(&flags.Publish, "publish", false, "Publish the builder directly to the container registry specified in <image-name>, instead of the daemon.")
cmd.Flags().BoolVar(&flags.AppendImageNameSuffix, "append-image-name-suffix", false, "When publishing to a registry that doesn't allow overwrite existing tags use this flag to append a [os]-[arch] suffix to <image-name>")
cmd.Flags().StringVar(&flags.Policy, "pull-policy", "", "Pull policy to use. Accepted values are always, never, and if-not-present. The default is always")
cmd.Flags().StringArrayVar(&flags.Flatten, "flatten", nil, "List of buildpacks to flatten together into a single layer (format: '<buildpack-id>@<buildpack-version>,<buildpack-id>@<buildpack-version>'")
cmd.Flags().StringToStringVarP(&flags.Label, "label", "l", nil, "Labels to add to the builder image, in the form of '<name>=<value>'")
Expand Down
49 changes: 28 additions & 21 deletions internal/commands/buildpack_package.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ import (

// BuildpackPackageFlags define flags provided to the BuildpackPackage command
type BuildpackPackageFlags struct {
PackageTomlPath string
Format string
Policy string
BuildpackRegistry string
Path string
FlattenExclude []string
Targets []string
Label map[string]string
Publish bool
Flatten bool
PackageTomlPath string
Format string
Policy string
BuildpackRegistry string
Path string
FlattenExclude []string
Targets []string
Label map[string]string
Publish bool
Flatten bool
AppendImageNameSuffix bool
}

// BuildpackPackager packages buildpacks
Expand Down Expand Up @@ -130,18 +131,23 @@ func BuildpackPackage(logger logging.Logger, cfg config.Config, packager Buildpa
defer clean(filesToClean)
}

if !flags.Publish && flags.AppendImageNameSuffix {
logger.Warnf("--append-image-name-suffix will be ignored, use combined with --publish")
}

if err := packager.PackageBuildpack(cmd.Context(), client.PackageBuildpackOptions{
RelativeBaseDir: relativeBaseDir,
Name: name,
Format: flags.Format,
Config: bpPackageCfg,
Publish: flags.Publish,
PullPolicy: pullPolicy,
Registry: flags.BuildpackRegistry,
Flatten: flags.Flatten,
FlattenExclude: flags.FlattenExclude,
Labels: flags.Label,
Targets: multiArchCfg.Targets(),
RelativeBaseDir: relativeBaseDir,
Name: name,
Format: flags.Format,
Config: bpPackageCfg,
Publish: flags.Publish,
AppendImageNameSuffix: flags.AppendImageNameSuffix && flags.Publish,
PullPolicy: pullPolicy,
Registry: flags.BuildpackRegistry,
Flatten: flags.Flatten,
FlattenExclude: flags.FlattenExclude,
Labels: flags.Label,
Targets: multiArchCfg.Targets(),
}); err != nil {
return err
}
Expand All @@ -163,6 +169,7 @@ func BuildpackPackage(logger logging.Logger, cfg config.Config, packager Buildpa
cmd.Flags().StringVarP(&flags.PackageTomlPath, "config", "c", "", "Path to package TOML config")
cmd.Flags().StringVarP(&flags.Format, "format", "f", "", `Format to save package as ("image" or "file")`)
cmd.Flags().BoolVar(&flags.Publish, "publish", false, `Publish the buildpack directly to the container registry specified in <name>, instead of the daemon (applies to "--format=image" only).`)
cmd.Flags().BoolVar(&flags.AppendImageNameSuffix, "append-image-name-suffix", false, "When publishing to a registry that doesn't allow overwrite existing tags use this flag to append a [os]-[arch] suffix to package <name>")
cmd.Flags().StringVar(&flags.Policy, "pull-policy", "", "Pull policy to use. Accepted values are always, never, and if-not-present. The default is always")
cmd.Flags().StringVarP(&flags.Path, "path", "p", "", "Path to the Buildpack that needs to be packaged")
cmd.Flags().StringVarP(&flags.BuildpackRegistry, "buildpack-registry", "r", "", "Buildpack Registry name")
Expand Down
10 changes: 10 additions & 0 deletions internal/name/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package name

import (
"fmt"
"github.com/buildpacks/pack/pkg/dist"
"strings"

gname "github.com/google/go-containerregistry/pkg/name"
Expand Down Expand Up @@ -49,6 +50,15 @@ func TranslateRegistry(name string, registryMirrors map[string]string, logger Lo
return refName, nil
}

func AppendSuffix(name string, target dist.Target) string {
if target.Arch != "" {
name = fmt.Sprintf("%s:%s-%s", name, target.OS, target.Arch)
} else {
name = fmt.Sprintf("%s:%s", name, target.OS)
}
return name
}

func getMirror(repo gname.Repository, registryMirrors map[string]string) (string, bool) {
mirror, ok := registryMirrors["*"]
if ok {
Expand Down
29 changes: 29 additions & 0 deletions internal/name/name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,33 @@ func testTranslateRegistry(t *testing.T, when spec.G, it spec.S) {
assert.Equal(output, expected)
})
})

// {
// OS: "linux",
// Arch: "arm",
// ArchVariant: "v6",
// }

when("#AppendSuffix", func() {
when("Arch is provided", func() {
when("Variant is provided", func() {

})
when("Tag is provided", func() {
// my.registry.com/my-repo/my-image:some-tag
})
when("Tag is NOT provided", func() {
// my.registry.com/my-repo/my-image
})
})

when("Arch is NOT provided", func() {
when("Tag is provided", func() {
// my.registry.com/my-repo/my-image:some-tag
})
when("Tag is NOT provided", func() {
// my.registry.com/my-repo/my-image
})
})
})
}
16 changes: 13 additions & 3 deletions pkg/client/create_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"context"
"fmt"
"github.com/buildpacks/pack/internal/name"
"sort"
"strings"

Expand Down Expand Up @@ -43,6 +44,10 @@ type CreateBuilderOptions struct {
// Requires BuilderName to be a valid registry location.
Publish bool

// Append [os]-[arch] suffix to the image tag when publishing a multi-arch to a registry
// Requires Publish to be true
AppendImageNameSuffix bool

// Buildpack registry name. Defines where all registry buildpacks will be pulled from.
Registry string

Expand Down Expand Up @@ -98,7 +103,7 @@ func (c *Client) createBuilderTarget(ctx context.Context, opts CreateBuilderOpti
return "", err
}

bldr, err := c.createBaseBuilder(ctx, opts, target)
bldr, err := c.createBaseBuilder(ctx, opts, target, multiArch)
if err != nil {
return "", errors.Wrap(err, "failed to create builder")
}
Expand Down Expand Up @@ -197,7 +202,7 @@ func (c *Client) validateRunImageConfig(ctx context.Context, opts CreateBuilderO
return nil
}

func (c *Client) createBaseBuilder(ctx context.Context, opts CreateBuilderOptions, target *dist.Target) (*builder.Builder, error) {
func (c *Client) createBaseBuilder(ctx context.Context, opts CreateBuilderOptions, target *dist.Target, multiArch bool) (*builder.Builder, error) {
baseImage, err := c.imageFetcher.Fetch(ctx, opts.Config.Build.Image, image.FetchOptions{Daemon: !opts.Publish, PullPolicy: opts.PullPolicy, Target: target})
if err != nil {
return nil, errors.Wrap(err, "fetch build image")
Expand All @@ -213,7 +218,12 @@ func (c *Client) createBaseBuilder(ctx context.Context, opts CreateBuilderOption
builderOpts = append(builderOpts, builder.WithLabels(opts.Labels))
}

bldr, err := builder.New(baseImage, opts.BuilderName, builderOpts...)
builderName := opts.BuilderName
if multiArch && opts.AppendImageNameSuffix {
builderName = name.AppendSuffix(builderName, *target)
}

bldr, err := builder.New(baseImage, builderName, builderOpts...)
if err != nil {
return nil, errors.Wrap(err, "invalid build-image")
}
Expand Down
11 changes: 10 additions & 1 deletion pkg/client/package_buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"context"
"fmt"
"github.com/buildpacks/pack/internal/name"
"path/filepath"

"github.com/pkg/errors"
Expand Down Expand Up @@ -47,6 +48,10 @@ type PackageBuildpackOptions struct {
// specified in the Name variable.
Publish bool

// Append [os]-[arch] suffix to the image tag when publishing a multi-arch to a registry
// Requires Publish to be true
AppendImageNameSuffix bool

// Strategy for updating images before packaging.
PullPolicy image.PullPolicy

Expand Down Expand Up @@ -192,7 +197,11 @@ func (c *Client) packageBuildpackTarget(ctx context.Context, opts PackageBuildpa
return digest, err
}
case FormatImage:
img, err := packageBuilder.SaveAsImage(opts.Name, opts.Publish, target, opts.Labels)
packageName := opts.Name
if multiArch && opts.AppendImageNameSuffix {
packageName = name.AppendSuffix(packageName, target)
}
img, err := packageBuilder.SaveAsImage(packageName, opts.Publish, target, opts.Labels)
if err != nil {
return digest, errors.Wrapf(err, "saving image")
}
Expand Down

0 comments on commit b999752

Please sign in to comment.