Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add pack extension --help #1601

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) {
rootCmd.AddCommand(commands.Build(logger, cfg, packClient))
rootCmd.AddCommand(commands.NewBuilderCommand(logger, cfg, packClient))
rootCmd.AddCommand(commands.NewBuildpackCommand(logger, cfg, packClient, buildpackage.NewConfigReader()))
rootCmd.AddCommand(commands.NewExtensionCommand(logger, cfg, packClient, buildpackage.NewConfigReader()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this line should be move inside the statement if cfg.Experimental on line 100. I believe the extensions is actually an experimental feature.

rootCmd.AddCommand(commands.NewConfigCommand(logger, cfg, cfgPath, packClient))
rootCmd.AddCommand(commands.InspectImage(logger, imagewriter.NewFactory(), cfg, packClient))
rootCmd.AddCommand(commands.NewStackCommand(logger))
Expand Down
6 changes: 6 additions & 0 deletions internal/build/lifecycle_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ func (l *LifecycleExecution) Create(ctx context.Context, buildCache, launchCache
If(l.opts.SBOMDestinationDir != "", WithPostContainerRunOperations(
EnsureVolumeAccess(l.opts.Builder.UID(), l.opts.Builder.GID(), l.os, l.layersVolume, l.appVolume),
CopyOutTo(l.mountPaths.sbomDir(), l.opts.SBOMDestinationDir))),
If(l.opts.ReportDestinationDir != "", WithPostContainerRunOperations(
EnsureVolumeAccess(l.opts.Builder.UID(), l.opts.Builder.GID(), l.os, l.layersVolume, l.appVolume),
CopyOutTo(l.mountPaths.reportPath(), l.opts.ReportDestinationDir))),
If(l.opts.Interactive, WithPostContainerRunOperations(
EnsureVolumeAccess(l.opts.Builder.UID(), l.opts.Builder.GID(), l.os, l.layersVolume, l.appVolume),
CopyOut(l.opts.Termui.ReadLayers, l.mountPaths.layersDir(), l.mountPaths.appDir()))),
Expand Down Expand Up @@ -652,6 +655,9 @@ func (l *LifecycleExecution) Export(ctx context.Context, buildCache, launchCache
If(l.opts.SBOMDestinationDir != "", WithPostContainerRunOperations(
EnsureVolumeAccess(l.opts.Builder.UID(), l.opts.Builder.GID(), l.os, l.layersVolume, l.appVolume),
CopyOutTo(l.mountPaths.sbomDir(), l.opts.SBOMDestinationDir))),
If(l.opts.ReportDestinationDir != "", WithPostContainerRunOperations(
EnsureVolumeAccess(l.opts.Builder.UID(), l.opts.Builder.GID(), l.os, l.layersVolume, l.appVolume),
CopyOutTo(l.mountPaths.reportPath(), l.opts.ReportDestinationDir))),
If(l.opts.Interactive, WithPostContainerRunOperations(
EnsureVolumeAccess(l.opts.Builder.UID(), l.opts.Builder.GID(), l.os, l.layersVolume, l.appVolume),
CopyOut(l.opts.Termui.ReadLayers, l.mountPaths.layersDir(), l.mountPaths.appDir()))),
Expand Down
27 changes: 27 additions & 0 deletions internal/build/lifecycle_execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,21 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {
})
})

when("report destination directory is provided", func() {
lifecycleOps = append(lifecycleOps, func(opts *build.LifecycleOptions) {
opts.ReportDestinationDir = "a-destination-dir"
})

it("provides copy-sbom-func as a post container operation", func() {
h.AssertEq(t, fakePhase.CleanupCallCount, 1)
h.AssertEq(t, fakePhase.RunCallCount, 1)

h.AssertEq(t, len(configProvider.PostContainerRunOps()), 2)
h.AssertFunctionName(t, configProvider.PostContainerRunOps()[0], "EnsureVolumeAccess")
h.AssertFunctionName(t, configProvider.PostContainerRunOps()[1], "CopyOut")
})
})

when("--creation-time", func() {
when("platform < 0.9", func() {
platformAPI = api.MustParse("0.8")
Expand Down Expand Up @@ -1970,6 +1985,18 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {
})
})

when("report destination directory is provided", func() {
lifecycleOps = append(lifecycleOps, func(opts *build.LifecycleOptions) {
opts.ReportDestinationDir = "a-destination-dir"
})

it("provides copy-sbom-func as a post container operation", func() {
h.AssertEq(t, len(configProvider.PostContainerRunOps()), 2)
h.AssertFunctionName(t, configProvider.PostContainerRunOps()[0], "EnsureVolumeAccess")
h.AssertFunctionName(t, configProvider.PostContainerRunOps()[1], "CopyOut")
})
})

when("--creation-time", func() {
when("platform < 0.9", func() {
platformAPI = api.MustParse("0.8")
Expand Down
59 changes: 30 additions & 29 deletions internal/build/lifecycle_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,35 +67,36 @@ func init() {
}

type LifecycleOptions struct {
AppPath string
Image name.Reference
Builder Builder
BuilderImage string // differs from Builder.Name() and Builder.Image().Name() in that it includes the registry context
LifecycleImage string
RunImage string
ProjectMetadata platform.ProjectMetadata
ClearCache bool
Publish bool
TrustBuilder bool
UseCreator bool
Interactive bool
Termui Termui
DockerHost string
Cache cache.CacheOpts
CacheImage string
HTTPProxy string
HTTPSProxy string
NoProxy string
Network string
AdditionalTags []string
Volumes []string
DefaultProcessType string
FileFilter func(string) bool
Workspace string
GID int
PreviousImage string
SBOMDestinationDir string
CreationTime *time.Time
AppPath string
Image name.Reference
Builder Builder
BuilderImage string // differs from Builder.Name() and Builder.Image().Name() in that it includes the registry context
LifecycleImage string
RunImage string
ProjectMetadata platform.ProjectMetadata
ClearCache bool
Publish bool
TrustBuilder bool
UseCreator bool
Interactive bool
Termui Termui
DockerHost string
Cache cache.CacheOpts
CacheImage string
HTTPProxy string
HTTPSProxy string
NoProxy string
Network string
AdditionalTags []string
Volumes []string
DefaultProcessType string
FileFilter func(string) bool
Workspace string
GID int
PreviousImage string
ReportDestinationDir string
SBOMDestinationDir string
CreationTime *time.Time
}

func NewLifecycleExecutor(logger logging.Logger, docker client.CommonAPIClient) *LifecycleExecutor {
Expand Down
4 changes: 4 additions & 0 deletions internal/build/mount_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func (m mountPaths) projectPath() string {
return m.join(m.layersDir(), "project-metadata.toml")
}

func (m mountPaths) reportPath() string {
return m.join(m.layersDir(), "report.toml")
}

func (m mountPaths) appDirName() string {
return m.workspace
}
Expand Down
55 changes: 29 additions & 26 deletions internal/commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,33 @@ import (
)

type BuildFlags struct {
Publish bool
ClearCache bool
TrustBuilder bool
Interactive bool
DockerHost string
CacheImage string
Cache cache.CacheOpts
AppPath string
Builder string
Registry string
RunImage string
Policy string
Network string
DescriptorPath string
DefaultProcessType string
LifecycleImage string
Env []string
EnvFiles []string
Buildpacks []string
Volumes []string
AdditionalTags []string
Workspace string
GID int
PreviousImage string
SBOMDestinationDir string
DateTime string
Publish bool
ClearCache bool
TrustBuilder bool
Interactive bool
DockerHost string
CacheImage string
Cache cache.CacheOpts
AppPath string
Builder string
Registry string
RunImage string
Policy string
Network string
DescriptorPath string
DefaultProcessType string
LifecycleImage string
Env []string
EnvFiles []string
Buildpacks []string
Volumes []string
AdditionalTags []string
Workspace string
GID int
PreviousImage string
SBOMDestinationDir string
ReportDestinationDir string
DateTime string
}

// Build an image from source code
Expand Down Expand Up @@ -171,6 +172,7 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob
PreviousImage: flags.PreviousImage,
Interactive: flags.Interactive,
SBOMDestinationDir: flags.SBOMDestinationDir,
ReportDestinationDir: flags.ReportDestinationDir,
CreationTime: dateTime,
}); err != nil {
return errors.Wrap(err, "failed to build")
Expand Down Expand Up @@ -238,6 +240,7 @@ This option may set DOCKER_HOST environment variable for the build container if
cmd.Flags().IntVar(&buildFlags.GID, "gid", 0, `Override GID of user's group in the stack's build and run images. The provided value must be a positive number`)
cmd.Flags().StringVar(&buildFlags.PreviousImage, "previous-image", "", "Set previous image to a particular tag reference, digest reference, or (when performing a daemon build) image ID")
cmd.Flags().StringVar(&buildFlags.SBOMDestinationDir, "sbom-output-dir", "", "Path to export SBoM contents.\nOmitting the flag will yield no SBoM content.")
cmd.Flags().StringVar(&buildFlags.ReportDestinationDir, "report-output-dir", "", "Path to export build report.toml.\nOmitting the flag yield no report file.")
cmd.Flags().BoolVar(&buildFlags.Interactive, "interactive", false, "Launch a terminal UI to depict the build process")
if !cfg.Experimental {
cmd.Flags().MarkHidden("interactive")
Expand Down
29 changes: 29 additions & 0 deletions internal/commands/extension.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package commands

import (
"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/pkg/logging"
)

func NewExtensionCommand(logger logging.Logger, cfg config.Config, client PackClient, packageConfigReader PackageConfigReader) *cobra.Command {
cmd := &cobra.Command{
Use: "extension",
Aliases: []string{"extensions"},
Short: "Interact with extensions",
RunE: nil,
}

cmd.AddCommand(ExtensionInspect(logger, cfg, client))
// client and packageConfigReader to be passed later on
cmd.AddCommand(ExtensionPackage(logger, cfg))
// client to be passed later on
cmd.AddCommand(ExtensionNew(logger))
cmd.AddCommand(ExtensionPull(logger, cfg, client))
cmd.AddCommand(ExtensionRegister(logger, cfg, client))
cmd.AddCommand(ExtensionYank(logger, cfg, client))

AddHelpFlag(cmd, "extension")
return cmd
}
41 changes: 41 additions & 0 deletions internal/commands/extension_inspect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package commands

import (
"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/pkg/logging"
)

type ExtensionInspectFlags struct {
Depth int
Registry string
Verbose bool
}

func ExtensionInspect(logger logging.Logger, cfg config.Config, client PackClient) *cobra.Command {
var flags ExtensionInspectFlags
cmd := &cobra.Command{
Use: "inspect <extension-name>",
Args: cobra.ExactArgs(1),
Short: "Show information about an extension",
Example: "pack extension inspect <example-extension>",
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
extensionName := args[0]
registry := flags.Registry
if registry == "" {
// fix registry for extension
}

return extensionInspect(logger, extensionName, registry, flags, cfg, client)
}),
}
// flags will be added here
AddHelpFlag(cmd, "inspect")
return cmd
}

func extensionInspect(logger logging.Logger, extensionName, registry string, flags ExtensionInspectFlags, cfg config.Config, client PackClient) error {
// logic to inspect extension
return nil
}
36 changes: 36 additions & 0 deletions internal/commands/extension_new.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package commands

import (
"github.com/spf13/cobra"

"github.com/buildpacks/pack/pkg/logging"
)

// ExtensionNewFlags define flags provided to the ExtensionNew command
type ExtensionNewFlags struct {
API string
Path string
Stacks []string
Version string
}

// extensioncreator type to be added here and argument also to be added in the function

// ExtensionNew generates the scaffolding of an extension
func ExtensionNew(logger logging.Logger) *cobra.Command {
cmd := &cobra.Command{
Use: "new <id>",
Short: "Creates basic scaffolding of an extension.",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
Example: "pack extension new <example-extension>",
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
// logic will go here
return nil
}),
}

// flags will go here

AddHelpFlag(cmd, "new")
return cmd
}
38 changes: 38 additions & 0 deletions internal/commands/extension_package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package commands

import (
"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/config"
"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
}

// Packager and PackageConfigReader to be added here and argument also to be added in the function

// ExtensionPackage packages (a) extension(s) into OCI format, based on a package config
func ExtensionPackage(logger logging.Logger, cfg config.Config) *cobra.Command {
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
return nil
}),
}

// flags will be added here

AddHelpFlag(cmd, "package")
return cmd
}
Loading