Skip to content

Commit

Permalink
Add package-buildpack arg for OS
Browse files Browse the repository at this point in the history
- Important for publish scenarios to not depend on daemon

Signed-off-by: Micah Young <[email protected]>
  • Loading branch information
Micah Young committed Oct 13, 2020
1 parent ba9942f commit 5bfd35d
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 38 deletions.
28 changes: 21 additions & 7 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,18 @@ func testWithoutSpecificBuilderRequirement(

when("--publish", func() {
it("publishes image to registry", func() {
h.SkipIf(t, !pack.Supports("package-buildpack --os"), "os not supported")

nestedPackageName := registryConfig.RepoName("test/package-" + h.RandString(10))

nestedPackage := buildpacks.NewPackageImage(
t,
pack,
nestedPackageName,
simplePackageConfigPath,
buildpacks.WithPublish(),
buildpacks.WithRequiredBuildpacks(buildpacks.SimpleLayers),
buildpacks.WithPublish(),
buildpacks.WithOS(dockerHostOS()),
)
buildpackManager.PrepareBuildpacks(tmpDir, nestedPackage)
defer h.DockerRmi(dockerCli, nestedPackageName)
Expand All @@ -344,6 +347,7 @@ func testWithoutSpecificBuilderRequirement(
"package-buildpack", packageName,
"-c", aggregatePackageToml,
"--publish",
"--os", dockerHostOS(),
)
defer h.DockerRmi(dockerCli, packageName)
assertions.NewOutputAssertionManager(t, output).ReportsPackagePublished(packageName)
Expand Down Expand Up @@ -535,8 +539,10 @@ func testWithoutSpecificBuilderRequirement(
pack,
packageFileLocation,
pack.FixtureManager().FixtureLocation("package_for_build_cmd.toml"),
buildpacks.FolderSimpleLayersParent,
buildpacks.FolderSimpleLayers,
buildpacks.WithRequiredBuildpacks(
buildpacks.FolderSimpleLayersParent,
buildpacks.FolderSimpleLayers,
),
)

buildpackManager.PrepareBuildpacks(tmpDir, packageFile)
Expand Down Expand Up @@ -1242,8 +1248,8 @@ func testAcceptance(

it.Before(func() {
h.SkipUnless(t,
pack.Supports("package-buildpack"),
"--buildpack does not accept buildpackage unless package-buildpack is supported",
pack.Supports("package-buildpack --os"),
"--buildpack does not accept buildpackage unless package-buildpack --os is supported",
)
})

Expand Down Expand Up @@ -1291,6 +1297,11 @@ func testAcceptance(
var tmpDir string

it.Before(func() {
h.SkipUnless(t,
pack.Supports("package-buildpack --os"),
"--buildpack does not accept buildpackage unless package-buildpack --os is supported",
)

var err error
tmpDir, err = ioutil.TempDir("", "package-file")
assert.Nil(err)
Expand All @@ -1311,8 +1322,11 @@ func testAcceptance(
pack,
packageFileLocation,
pack.FixtureManager().FixtureLocation("package_for_build_cmd.toml"),
buildpacks.FolderSimpleLayersParent,
buildpacks.FolderSimpleLayers,
buildpacks.WithRequiredBuildpacks(
buildpacks.FolderSimpleLayersParent,
buildpacks.FolderSimpleLayers,
),
buildpacks.WithOS(dockerHostOS()),
)

buildpackManager.PrepareBuildpacks(tmpDir, packageFile)
Expand Down
26 changes: 26 additions & 0 deletions acceptance/buildpacks/modifiers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package buildpacks

type Modifiable interface {
SetOS(string)
SetPublish()
SetBuildpacks([]TestBuildpack)
}
type PackageModifier func(p Modifiable)

func WithRequiredBuildpacks(buildpacks ...TestBuildpack) PackageModifier {
return func(p Modifiable) {
p.SetBuildpacks(buildpacks)
}
}

func WithPublish() PackageModifier {
return func(p Modifiable) {
p.SetPublish()
}
}

func WithOS(osVal string) PackageModifier {
return func(p Modifiable) {
p.SetOS(osVal)
}
}
32 changes: 26 additions & 6 deletions acceptance/buildpacks/package_file_buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,37 @@ type PackageFile struct {
destination string
sourceConfigLocation string
buildpacks []TestBuildpack
os string
}

func (p *PackageFile) SetOS(os string) {
p.os = os
}

func (p *PackageFile) SetBuildpacks(buildpacks []TestBuildpack) {
p.buildpacks = buildpacks
}

func (p *PackageFile) SetPublish() {}

func NewPackageFile(
t *testing.T,
pack *invoke.PackInvoker,
destination, configLocation string,
buildpacks ...TestBuildpack,
modifiers ...PackageModifier,
) PackageFile {

return PackageFile{
p := PackageFile{
testObject: t,
pack: pack,
destination: destination,
sourceConfigLocation: configLocation,
buildpacks: buildpacks,
}
for _, mod := range modifiers {
mod(&p)
}

return p
}

func (p PackageFile) Prepare(sourceDir, _ string) error {
Expand All @@ -59,13 +74,18 @@ func (p PackageFile) Prepare(sourceDir, _ string) error {
configLocation := filepath.Join(tmpDir, "package.toml")
h.CopyFile(p.testObject, p.sourceConfigLocation, configLocation)

output := p.pack.RunSuccessfully(
"package-buildpack",
packArgs := []string{
p.destination,
"--no-color",
"-c", configLocation,
"--format", "file",
)
}

if p.os != "" {
packArgs = append(packArgs, "--os", p.os)
}

output := p.pack.RunSuccessfully("package-buildpack", packArgs...)

if !strings.Contains(output, fmt.Sprintf("Successfully created package '%s'", p.destination)) {
return errors.New("failed to create package")
Expand Down
23 changes: 13 additions & 10 deletions acceptance/buildpacks/package_image_buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,26 @@ type PackageImage struct {
sourceConfigLocation string
buildpacks []TestBuildpack
publish bool
os string
}

type PackageImageModifier func(p *PackageImage)
func (p *PackageImage) SetOS(os string) {
p.os = os
}

func WithRequiredBuildpacks(buildpacks ...TestBuildpack) PackageImageModifier {
return func(p *PackageImage) {
p.buildpacks = buildpacks
}
func (p *PackageImage) SetBuildpacks(buildpacks []TestBuildpack) {
p.buildpacks = buildpacks
}

func WithPublish() PackageImageModifier {
return func(p *PackageImage) {
p.publish = true
}
func (p *PackageImage) SetPublish() {
p.publish = true
}

func NewPackageImage(
t *testing.T,
pack *invoke.PackInvoker,
name, configLocation string,
modifiers ...PackageImageModifier,
modifiers ...PackageModifier,
) PackageImage {
p := PackageImage{
testObject: t,
Expand Down Expand Up @@ -90,6 +89,10 @@ func (p PackageImage) Prepare(sourceDir, _ string) error {
packArgs = append(packArgs, "--publish")
}

if p.os != "" {
packArgs = append(packArgs, "--os", p.os)
}

output := p.pack.RunSuccessfully("package-buildpack", packArgs...)

assertOutput := assertions.NewOutputAssertionManager(p.testObject, output)
Expand Down
9 changes: 6 additions & 3 deletions internal/commands/package_buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
type PackageBuildpackFlags struct {
PackageTomlPath string
Format string
OS string
Publish bool
NoPull bool
Policy string
Expand Down Expand Up @@ -56,7 +57,7 @@ func PackageBuildpack(logger logging.Logger, client BuildpackPackager, packageCo
logger.Warn("Flag --package-config has been deprecated, please use --config instead")
}

config, err := packageConfigReader.Read(flags.PackageTomlPath)
cfg, err := packageConfigReader.Read(flags.PackageTomlPath)
if err != nil {
return errors.Wrap(err, "reading config")
}
Expand All @@ -65,7 +66,8 @@ func PackageBuildpack(logger logging.Logger, client BuildpackPackager, packageCo
if err := client.PackageBuildpack(cmd.Context(), pack.PackageBuildpackOptions{
Name: name,
Format: flags.Format,
Config: config,
OS: flags.OS,
Config: cfg,
Publish: flags.Publish,
PullPolicy: pullPolicy,
}); err != nil {
Expand All @@ -84,7 +86,8 @@ func PackageBuildpack(logger logging.Logger, client BuildpackPackager, packageCo
cmd.Flags().StringVarP(&flags.PackageTomlPath, "config", "c", "", "Path to package TOML config (required)")

cmd.Flags().StringVarP(&flags.Format, "format", "f", "", `Format to save package as ("image" or "file")`)
cmd.Flags().BoolVar(&flags.Publish, "publish", false, `Publish to registry (applies to "--image" only)`)
cmd.Flags().BoolVar(&flags.Publish, "publish", false, `Publish to registry (applies to "--format=image" only)`)
cmd.Flags().StringVar(&flags.OS, "os", "", `The operating system of the package OCI image ("linux" or "windows"). If unset, local images will match the daemon OS, otherwise default to "linux"`)
cmd.Flags().StringVar(&flags.Policy, "pull-policy", "", "Pull policy to use. Accepted values are always, never, and if-not-present. The default is always")
// TODO: Remove --no-pull flag after v0.13.0 released. See https://github.com/buildpacks/pack/issues/775
cmd.Flags().BoolVar(&flags.NoPull, "no-pull", false, "Skip pulling packages before use")
Expand Down
46 changes: 34 additions & 12 deletions package_buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package pack
import (
"context"

"github.com/pkg/errors"

"github.com/buildpacks/pack/config"
"github.com/buildpacks/pack/internal/layer"

"github.com/pkg/errors"

pubbldpkg "github.com/buildpacks/pack/buildpackage"
"github.com/buildpacks/pack/internal/buildpackage"
"github.com/buildpacks/pack/internal/dist"
Expand All @@ -31,6 +31,9 @@ type PackageBuildpackOptions struct {
// Type of output format, The options are the either the const FormatImage, or FormatFile.
Format string

// Type of OCI image to generate in the image or file. The options are "windows" or "linux"
OS string

// Defines the Buildpacks configuration.
Config pubbldpkg.Config

Expand All @@ -44,22 +47,26 @@ type PackageBuildpackOptions struct {

// PackageBuildpack packages buildpack(s) into either an image or file.
func (c *Client) PackageBuildpack(ctx context.Context, opts PackageBuildpackOptions) error {
info, err := c.docker.Info(ctx)
if err != nil {
return errors.Wrap(err, "getting docker info")
if opts.Format == "" {
opts.Format = FormatImage
}

if opts.OS == "" {
osType, err := c.defaultOSType(ctx, opts.Publish, opts.Format)
if err != nil {
return errors.Wrap(err, "daemon OS cannot be detected")
}

opts.OS = osType
}

writerFactory, err := layer.NewWriterFactory(info.OSType)
writerFactory, err := layer.NewWriterFactory(opts.OS)
if err != nil {
return errors.Wrap(err, "creating layer writer factory")
}

packageBuilder := buildpackage.NewBuilder(c.imageFactory)

if opts.Format == "" {
opts.Format = FormatImage
}

bpURI := opts.Config.Buildpack.URI
if bpURI == "" {
return errors.New("buildpack URI must be provided")
Expand Down Expand Up @@ -121,11 +128,26 @@ func (c *Client) PackageBuildpack(ctx context.Context, opts PackageBuildpackOpti

switch opts.Format {
case FormatFile:
return packageBuilder.SaveAsFile(opts.Name, info.OSType)
return packageBuilder.SaveAsFile(opts.Name, opts.OS)
case FormatImage:
_, err = packageBuilder.SaveAsImage(opts.Name, opts.Publish, info.OSType)
_, err = packageBuilder.SaveAsImage(opts.Name, opts.Publish, opts.OS)
return errors.Wrapf(err, "saving image")
default:
return errors.Errorf("unknown format: %s", style.Symbol(opts.Format))
}
}

func (c *Client) defaultOSType(ctx context.Context, publish bool, format string) (string, error) {
if publish || format == FormatFile {
c.logger.Warnf(`buildpackage OS unspecified - defaulting to "linux"`)

return "linux", nil
}

info, err := c.docker.Info(ctx)
if err != nil {
return "", err
}

return info.OSType, nil
}

0 comments on commit 5bfd35d

Please sign in to comment.