Skip to content

Commit

Permalink
Merge pull request #1661 from itsdarshankumar/extension-package
Browse files Browse the repository at this point in the history
Extension package
  • Loading branch information
jkutner authored Mar 31, 2023
2 parents 18662b2 + 3e75a40 commit 52127f7
Show file tree
Hide file tree
Showing 15 changed files with 980 additions and 30 deletions.
19 changes: 17 additions & 2 deletions buildpackage/config_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const defaultOS = "linux"
// Config encapsulates the possible configuration options for buildpackage creation.
type Config struct {
Buildpack dist.BuildpackURI `toml:"buildpack"`
Extension dist.BuildpackURI `toml:"extension"`
Dependencies []dist.ImageOrURI `toml:"dependencies"`
Platform dist.Platform `toml:"platform"`
}
Expand All @@ -32,6 +33,17 @@ func DefaultConfig() Config {
}
}

func DefaultExtensionConfig() Config {
return Config{
Extension: dist.BuildpackURI{
URI: ".",
},
Platform: dist.Platform{
OS: defaultOS,
},
}
}

// NewConfigReader returns an instance of ConfigReader. It does not take any parameters.
func NewConfigReader() *ConfigReader {
return &ConfigReader{}
Expand Down Expand Up @@ -61,8 +73,11 @@ func (r *ConfigReader) Read(path string) (Config, error) {
)
}

if packageConfig.Buildpack.URI == "" {
return packageConfig, errors.Errorf("missing %s configuration", style.Symbol("buildpack.uri"))
if packageConfig.Buildpack.URI == "" && packageConfig.Extension.URI == "" {
if packageConfig.Buildpack.URI == "" {
return packageConfig, errors.Errorf("missing %s configuration", style.Symbol("buildpack.uri"))
}
return packageConfig, errors.Errorf("missing %s configuration", style.Symbol("extension.uri"))
}

if packageConfig.Platform.OS == "" {
Expand Down
29 changes: 29 additions & 0 deletions buildpackage/config_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/sclevine/spec/report"

"github.com/buildpacks/pack/buildpackage"
"github.com/buildpacks/pack/pkg/dist"
h "github.com/buildpacks/pack/testhelpers"
)

Expand All @@ -33,6 +34,34 @@ func testBuildpackageConfigReader(t *testing.T, when spec.G, it spec.S) {
os.RemoveAll(tmpDir)
})

it("returns default buildpack config", func() {
expected := buildpackage.Config{
Buildpack: dist.BuildpackURI{
URI: ".",
},
Platform: dist.Platform{
OS: "linux",
},
}
actual := buildpackage.DefaultConfig()

h.AssertEq(t, actual, expected)
})

it("returns default extension config", func() {
expected := buildpackage.Config{
Extension: dist.BuildpackURI{
URI: ".",
},
Platform: dist.Platform{
OS: "linux",
},
}
actual := buildpackage.DefaultExtensionConfig()

h.AssertEq(t, actual, expected)
})

it("returns correct config when provided toml file is valid", func() {
configFile := filepath.Join(tmpDir, "package.toml")

Expand Down
6 changes: 5 additions & 1 deletion internal/commands/buildpack_package.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ func BuildpackPackage(logger logging.Logger, cfg config.Config, packager Buildpa
if flags.Publish {
action = "published"
}
location := "docker daemon"
if flags.Format == client.FormatFile {
location = "file"
}

logger.Infof("Successfully %s package %s", action, style.Symbol(name))
logger.Infof("Successfully %s package %s and saved to %s", action, style.Symbol(name), location)
return nil
}),
}
Expand Down
1 change: 1 addition & 0 deletions internal/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type PackClient interface {
CreateBuilder(context.Context, client.CreateBuilderOptions) error
NewBuildpack(context.Context, client.NewBuildpackOptions) error
PackageBuildpack(ctx context.Context, opts client.PackageBuildpackOptions) error
PackageExtension(ctx context.Context, opts client.PackageBuildpackOptions) error
Build(context.Context, client.BuildOptions) error
RegisterBuildpack(context.Context, client.RegisterBuildpackOptions) error
YankBuildpack(client.YankBuildpackOptions) error
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func NewExtensionCommand(logger logging.Logger, cfg config.Config, client PackCl

cmd.AddCommand(ExtensionInspect(logger, cfg, client))
// client and packageConfigReader to be passed later on
cmd.AddCommand(ExtensionPackage(logger, cfg))
cmd.AddCommand(ExtensionPackage(logger, cfg, client, packageConfigReader))
// client to be passed later on
cmd.AddCommand(ExtensionNew(logger))
cmd.AddCommand(ExtensionPull(logger, cfg, client))
Expand Down
97 changes: 87 additions & 10 deletions internal/commands/extension_package.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,115 @@
package commands

import (
"context"
"path/filepath"

"github.com/pkg/errors"
"github.com/spf13/cobra"

pubbldpkg "github.com/buildpacks/pack/buildpackage"
"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/image"
"github.com/buildpacks/pack/pkg/logging"
)

// ExtensionPackageFlags define flags provided to the ExtensionPackage command
type ExtensionPackageFlags struct {
PackageTomlPath string
Format string
Publish bool
Policy string
ExtensionRegistry string
Path string
PackageTomlPath string
Format string
Publish bool
Policy string
}

// Packager and PackageConfigReader to be added here and argument also to be added in the function
// ExtensionPackager packages extensions
type ExtensionPackager interface {
PackageExtension(ctx context.Context, options client.PackageBuildpackOptions) error
}

// ExtensionPackage packages (a) extension(s) into OCI format, based on a package config
func ExtensionPackage(logger logging.Logger, cfg config.Config) *cobra.Command {
func ExtensionPackage(logger logging.Logger, cfg config.Config, packager ExtensionPackager, packageConfigReader PackageConfigReader) *cobra.Command {
var flags ExtensionPackageFlags
cmd := &cobra.Command{
Use: "package <name> --config <config-path>",
Short: "Package an extension in OCI format",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
// logic will be added here
if err := validateExtensionPackageFlags(&flags); err != nil {
return err
}

stringPolicy := flags.Policy
if stringPolicy == "" {
stringPolicy = cfg.PullPolicy
}

pullPolicy, err := image.ParsePullPolicy(stringPolicy)
if err != nil {
return errors.Wrap(err, "parsing pull policy")
}

exPackageCfg := pubbldpkg.DefaultExtensionConfig()
relativeBaseDir := ""
if flags.PackageTomlPath != "" {
exPackageCfg, err = packageConfigReader.Read(flags.PackageTomlPath)
if err != nil {
return errors.Wrap(err, "reading config")
}

relativeBaseDir, err = filepath.Abs(filepath.Dir(flags.PackageTomlPath))
if err != nil {
return errors.Wrap(err, "getting absolute path for config")
}
}
name := args[0]
if flags.Format == client.FormatFile {
switch ext := filepath.Ext(name); ext {
case client.CNBExtension:
case "":
name += client.CNBExtension
default:
logger.Warnf("%s is not a valid extension for a packaged extension. Packaged extensions must have a %s extension", style.Symbol(ext), style.Symbol(client.CNBExtension))
}
}

if err := packager.PackageExtension(cmd.Context(), client.PackageBuildpackOptions{
RelativeBaseDir: relativeBaseDir,
Name: name,
Format: flags.Format,
Config: exPackageCfg,
Publish: flags.Publish,
PullPolicy: pullPolicy,
}); err != nil {
return err
}
action := "created"
if flags.Publish {
action = "published"
}
location := "docker daemon"
if flags.Format == client.FormatFile {
location = "file"
}

logger.Infof("Successfully %s package %s and saved to %s", action, style.Symbol(name), location)
return nil
}),
}

// flags will be added here

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 to registry (applies to "--format=image" only)`)
cmd.Flags().StringVar(&flags.Policy, "pull-policy", "", "Pull policy to use. Accepted values are always, never, and if-not-present. The default is always")
AddHelpFlag(cmd, "package")
return cmd
}

func validateExtensionPackageFlags(p *ExtensionPackageFlags) error {
if p.Publish && p.Policy == image.PullNever.String() {
return errors.Errorf("--publish and --pull-policy=never cannot be used together. The --publish flag requires the use of remote images.")
}
return nil
}
Loading

0 comments on commit 52127f7

Please sign in to comment.