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

feat: deprecate and replace zarf package inspect with child commands zarf package inspect definition|sbom|images #3416

Merged
merged 16 commits into from
Jan 28, 2025
4 changes: 3 additions & 1 deletion site/src/content/docs/commands/zarf_package_inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ zarf package inspect [ PACKAGE_SOURCE ] [flags]
```
-h, --help help for inspect
--list-images List images in the package (prints to stdout)
-s, --sbom View SBOM contents while inspecting the package
--sbom-out string Specify an output directory for the SBOMs from the inspected Zarf package
--skip-signature-validation Skip validating the signature of the Zarf package
```
Expand All @@ -48,4 +47,7 @@ zarf package inspect [ PACKAGE_SOURCE ] [flags]
### SEE ALSO

* [zarf package](/commands/zarf_package/) - Zarf package commands for creating, deploying, and inspecting packages
* [zarf package inspect definition](/commands/zarf_package_inspect_definition/) - Displays the 'zarf.yaml' definition for the specified package
* [zarf package inspect images](/commands/zarf_package_inspect_images/) - List all container images contained in the package
* [zarf package inspect sbom](/commands/zarf_package_inspect_sbom/) - Output the package SBOM (Software Bill Of Materials) to the specified directory

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: zarf package inspect definition
description: Zarf CLI command reference for <code>zarf package inspect definition</code>.
tableOfContents: false
---

<!-- Page generated by Zarf; DO NOT EDIT -->

## zarf package inspect definition

Displays the 'zarf.yaml' definition for the specified package

```
zarf package inspect definition [ PACKAGE_SOURCE ] [flags]
```

### Options

```
-h, --help help for definition
--skip-signature-validation Skip validating the signature of the Zarf package
```

### Options inherited from parent commands

```
-a, --architecture string Architecture for OCI images and Zarf packages
--insecure-skip-tls-verify Skip checking server's certificate for validity. This flag should only be used if you have a specific reason and accept the reduced security posture.
-k, --key string Path to public key file for validating signed packages
--log-format string [beta] Select a logging format. Defaults to 'console'. Valid options are: 'console', 'json', 'dev'
-l, --log-level string Log level when running Zarf. Valid options are: warn, info, debug, trace (default "info")
--no-color Disable colors in output
--no-log-file Disable log file creation
--no-progress Disable fancy UI progress bars, spinners, logos, etc
--oci-concurrency int Number of concurrent layer operations to perform when interacting with a remote package. (default 3)
--plain-http Force the connections over HTTP instead of HTTPS. This flag should only be used if you have a specific reason and accept the reduced security posture.
--tmpdir string Specify the temporary directory to use for intermediate files
--zarf-cache string Specify the location of the Zarf cache directory (default "~/.zarf-cache")
```

### SEE ALSO

* [zarf package inspect](/commands/zarf_package_inspect/) - Displays the definition of a Zarf package (runs offline)

44 changes: 44 additions & 0 deletions site/src/content/docs/commands/zarf_package_inspect_images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: zarf package inspect images
description: Zarf CLI command reference for <code>zarf package inspect images</code>.
tableOfContents: false
---

<!-- Page generated by Zarf; DO NOT EDIT -->

## zarf package inspect images

List all container images contained in the package

```
zarf package inspect images [ PACKAGE_SOURCE ] [flags]
```

### Options

```
-h, --help help for images
--skip-signature-validation Skip validating the signature of the Zarf package
```

### Options inherited from parent commands

```
-a, --architecture string Architecture for OCI images and Zarf packages
--insecure-skip-tls-verify Skip checking server's certificate for validity. This flag should only be used if you have a specific reason and accept the reduced security posture.
-k, --key string Path to public key file for validating signed packages
--log-format string [beta] Select a logging format. Defaults to 'console'. Valid options are: 'console', 'json', 'dev'
-l, --log-level string Log level when running Zarf. Valid options are: warn, info, debug, trace (default "info")
--no-color Disable colors in output
--no-log-file Disable log file creation
--no-progress Disable fancy UI progress bars, spinners, logos, etc
--oci-concurrency int Number of concurrent layer operations to perform when interacting with a remote package. (default 3)
--plain-http Force the connections over HTTP instead of HTTPS. This flag should only be used if you have a specific reason and accept the reduced security posture.
--tmpdir string Specify the temporary directory to use for intermediate files
--zarf-cache string Specify the location of the Zarf cache directory (default "~/.zarf-cache")
```

### SEE ALSO

* [zarf package inspect](/commands/zarf_package_inspect/) - Displays the definition of a Zarf package (runs offline)

45 changes: 45 additions & 0 deletions site/src/content/docs/commands/zarf_package_inspect_sbom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
title: zarf package inspect sbom
description: Zarf CLI command reference for <code>zarf package inspect sbom</code>.
tableOfContents: false
---

<!-- Page generated by Zarf; DO NOT EDIT -->

## zarf package inspect sbom

Output the package SBOM (Software Bill Of Materials) to the specified directory

```
zarf package inspect sbom [ PACKAGE ] [flags]
```

### Options

```
-h, --help help for sbom
--output string Specify an output directory for the SBOMs from the created Zarf package
--skip-signature-validation Skip validating the signature of the Zarf package
```

### Options inherited from parent commands

```
-a, --architecture string Architecture for OCI images and Zarf packages
--insecure-skip-tls-verify Skip checking server's certificate for validity. This flag should only be used if you have a specific reason and accept the reduced security posture.
-k, --key string Path to public key file for validating signed packages
--log-format string [beta] Select a logging format. Defaults to 'console'. Valid options are: 'console', 'json', 'dev'
-l, --log-level string Log level when running Zarf. Valid options are: warn, info, debug, trace (default "info")
--no-color Disable colors in output
--no-log-file Disable log file creation
--no-progress Disable fancy UI progress bars, spinners, logos, etc
--oci-concurrency int Number of concurrent layer operations to perform when interacting with a remote package. (default 3)
--plain-http Force the connections over HTTP instead of HTTPS. This flag should only be used if you have a specific reason and accept the reduced security posture.
--tmpdir string Specify the temporary directory to use for intermediate files
--zarf-cache string Specify the location of the Zarf cache directory (default "~/.zarf-cache")
```

### SEE ALSO

* [zarf package inspect](/commands/zarf_package_inspect/) - Displays the definition of a Zarf package (runs offline)

180 changes: 154 additions & 26 deletions src/cmd/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func NewPackageCommand() *cobra.Command {
cmd.AddCommand(NewPackageCreateCommand(v))
cmd.AddCommand(NewPackageDeployCommand(v))
cmd.AddCommand(NewPackageMirrorResourcesCommand(v))
cmd.AddCommand(NewPackageInspectCommand())
cmd.AddCommand(NewPackageInspectCommand(v))
cmd.AddCommand(NewPackageRemoveCommand(v))
cmd.AddCommand(NewPackageListCommand())
cmd.AddCommand(NewPackagePublishCommand(v))
Expand Down Expand Up @@ -345,7 +345,7 @@ func (o *PackageMirrorResourcesOptions) Run(cmd *cobra.Command, args []string) (
type PackageInspectOptions struct{}

// NewPackageInspectCommand creates the `package inspect` sub-command.
func NewPackageInspectCommand() *cobra.Command {
func NewPackageInspectCommand(v *viper.Viper) *cobra.Command {
o := &PackageInspectOptions{}
cmd := &cobra.Command{
Use: "inspect [ PACKAGE_SOURCE ]",
Expand All @@ -357,7 +357,10 @@ func NewPackageInspectCommand() *cobra.Command {
RunE: o.Run,
}

cmd.Flags().BoolVarP(&pkgConfig.InspectOpts.ViewSBOM, "sbom", "s", false, lang.CmdPackageInspectFlagSbom)
cmd.AddCommand(NewPackageInspectSBOMCommand(v))
cmd.AddCommand(NewPackageInspectImagesCommand())
cmd.AddCommand(NewPackageInspectDefinitionCommand())

cmd.Flags().StringVar(&pkgConfig.InspectOpts.SBOMOutputDir, "sbom-out", "", lang.CmdPackageInspectFlagSbomOut)
cmd.Flags().BoolVar(&pkgConfig.InspectOpts.ListImages, "list-images", false, lang.CmdPackageInspectFlagListImages)
cmd.Flags().BoolVar(&pkgConfig.PkgOpts.SkipSignatureValidation, "skip-signature-validation", false, lang.CmdPackageFlagSkipSignatureValidation)
Expand All @@ -376,47 +379,172 @@ func (o *PackageInspectOptions) PreRun(_ *cobra.Command, _ []string) {
// Run performs the execution of 'package inspect' sub-command.
func (o *PackageInspectOptions) Run(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
logger.From(ctx).Warn("Direct usage of inspect is deprecated and will be removed in a future release. Inspect is now a parent command. Use 'zarf package inspect definition|sbom|images' instead.")

if pkgConfig.InspectOpts.ListImages && (pkgConfig.InspectOpts.SBOMOutputDir != "" || pkgConfig.InspectOpts.ViewSBOM) {
if pkgConfig.InspectOpts.ListImages && (pkgConfig.InspectOpts.SBOMOutputDir != "") {
return fmt.Errorf("cannot use --sbom or --sbom-out and --list-images at the same time")
}

// NOTE(mkcp): Gets user input with message
if pkgConfig.InspectOpts.SBOMOutputDir != "" {
sbomOpts := PackageInspectSBOMOptions{
SkipSignatureValidation: pkgConfig.PkgOpts.SkipSignatureValidation,
SBOMOutputDir: pkgConfig.InspectOpts.SBOMOutputDir,
}
return sbomOpts.Run(cmd, args)
}

if pkgConfig.InspectOpts.ListImages {
imagesOpts := PackageInspectImagesOptions{
SkipSignatureValidation: pkgConfig.PkgOpts.SkipSignatureValidation,
}
return imagesOpts.Run(cmd, args)
}

definitionOpts := PackageInspectDefinitionOptions{
SkipSignatureValidation: pkgConfig.PkgOpts.SkipSignatureValidation,
}
return definitionOpts.Run(cmd, args)
Copy link
Contributor

Choose a reason for hiding this comment

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

Good stuff 👍

}

// PackageInspectSBOMOptions holds the command-line options for 'package inspect sbom' sub-command.
type PackageInspectSBOMOptions struct {
SkipSignatureValidation bool
SBOMOutputDir string
}

// NewPackageInspectSBOMCommand creates the `package inspect sbom` sub-command.
func NewPackageInspectSBOMCommand(v *viper.Viper) *cobra.Command {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as in #3413 about exporting these functions.

o := &PackageInspectSBOMOptions{}
cmd := &cobra.Command{
Use: "sbom [ PACKAGE ]",
Short: "Output the package SBOM (Software Bill Of Materials) to the specified directory",
Args: cobra.MaximumNArgs(1),
RunE: o.Run,
}

cmd.Flags().BoolVar(&o.SkipSignatureValidation, "skip-signature-validation", false, lang.CmdPackageFlagSkipSignatureValidation)
Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't implemented that bit yet, but ideally you want to have NewPackageInspectSBOMOptions function which folks can invoke and get default options for a command. Then when you wire your flags here instead of providing defaults directly, you're just using the field from options struct.

A nice example of that is in kubectl api-resources command. Notice how NewAPIResourceOptions is passed with IO streams, and then each flag is automatically wired to the default value of a particular options.

The main benefit of such an approach is that you have only a single source of truth wrt defaults.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went ahead and implemented this

Copy link
Contributor

Choose a reason for hiding this comment

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

Great!

cmd.Flags().StringVar(&o.SBOMOutputDir, "output", v.GetString(common.VPkgCreateSbomOutput), lang.CmdPackageCreateFlagSbomOut)

return cmd
}

// Run performs the execution of 'package inspect sbom' sub-command.
func (o *PackageInspectSBOMOptions) Run(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
src, err := choosePackage(ctx, args)
if err != nil {
return err
}

cluster, _ := cluster.NewCluster() //nolint:errcheck
inspectOpt := packager2.ZarfInspectOptions{
loadOpt := packager2.LoadOptions{
Source: src,
SkipSignatureValidation: pkgConfig.PkgOpts.SkipSignatureValidation,
Cluster: cluster,
ListImages: pkgConfig.InspectOpts.ListImages,
ViewSBOM: pkgConfig.InspectOpts.ViewSBOM,
SBOMOutputDir: pkgConfig.InspectOpts.SBOMOutputDir,
SkipSignatureValidation: o.SkipSignatureValidation,
Filter: filters.Empty(),
PublicKeyPath: pkgConfig.PkgOpts.PublicKeyPath,
}
layout, err := packager2.LoadPackage(ctx, loadOpt)
if err != nil {
return err
}
outputPath, err := layout.GetSBOM(o.SBOMOutputDir)
if err != nil {
return err
}
outputPath, err = filepath.Abs(outputPath)
if err != nil {
logger.From(ctx).Warn("SBOM successfully extracted, couldn't get output path", "error", err)
}
logger.From(ctx).Info("SBOM successfully extracted", "path", outputPath)
return nil
}

if pkgConfig.InspectOpts.ListImages {
output, err := packager2.InspectList(ctx, inspectOpt)
// PackageInspectImagesOptions holds the command-line options for 'package inspect images' sub-command.
type PackageInspectImagesOptions struct {
SkipSignatureValidation bool
}

// NewPackageInspectImagesCommand creates the `inspect images` sub-command.
func NewPackageInspectImagesCommand() *cobra.Command {
o := PackageInspectImagesOptions{}
cmd := &cobra.Command{
Use: "images [ PACKAGE_SOURCE ]",
Short: "List all container images contained in the package",
Args: cobra.MaximumNArgs(1),
RunE: o.Run,
}

cmd.Flags().BoolVar(&o.SkipSignatureValidation, "skip-signature-validation", false, lang.CmdPackageFlagSkipSignatureValidation)

return cmd
}

// Run performs the execution of 'package inspect images' sub-command.
func (o *PackageInspectImagesOptions) Run(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

src, err := choosePackage(ctx, args)
if err != nil {
return err
}

cluster, _ := cluster.NewCluster() //nolint:errcheck
Copy link
Contributor

Choose a reason for hiding this comment

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

Whenever explicitly ignoring error it's good to explain why you're doing so. I'm guessing that since this is only showing the contents of the file we don't care about the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We actually don't know at this point yet if a cluster is needed, which is why we avoid the error. Added context in comments


pkg, err := packager2.GetPackageFromSourceOrCluster(ctx, cluster, src, o.SkipSignatureValidation, pkgConfig.PkgOpts.PublicKeyPath)
if err != nil {
return err
}
var imageList []string
for _, component := range pkg.Components {
imageList = append(imageList, component.Images...)
}
if imageList == nil {
return fmt.Errorf("failed listing images: 0 images found in package")
}
imageList = helpers.Unique(imageList)
for _, image := range imageList {
_, err := fmt.Fprintln(os.Stdout, "-", image)
if err != nil {
return fmt.Errorf("failed to inspect package: %w", err)
}
for _, image := range output {
_, err := fmt.Fprintln(os.Stdout, "-", image)
if err != nil {
return err
}
return err
}
return nil
}
return nil
}

// PackageInspectDefinitionOptions holds the command-line options for 'package inspect definition' sub-command.
type PackageInspectDefinitionOptions struct {
SkipSignatureValidation bool
}

// NewPackageInspectDefinitionCommand creates the `package inspect definition` sub-command.
func NewPackageInspectDefinitionCommand() *cobra.Command {
o := PackageInspectDefinitionOptions{}
cmd := &cobra.Command{
Use: "definition [ PACKAGE_SOURCE ]",
Short: "Displays the 'zarf.yaml' definition for the specified package",
Args: cobra.MaximumNArgs(1),
RunE: o.Run,
}

cmd.Flags().BoolVar(&o.SkipSignatureValidation, "skip-signature-validation", false, lang.CmdPackageFlagSkipSignatureValidation)

return cmd
}

output, err := packager2.Inspect(ctx, inspectOpt)
// Run performs the execution of 'package inspect definition' sub-command.
func (o *PackageInspectDefinitionOptions) Run(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

src, err := choosePackage(ctx, args)
if err != nil {
return err
}

cluster, _ := cluster.NewCluster() //nolint:errcheck

pkg, err := packager2.GetPackageFromSourceOrCluster(ctx, cluster, src, o.SkipSignatureValidation, pkgConfig.PkgOpts.PublicKeyPath)
if err != nil {
return fmt.Errorf("failed to inspect package: %w", err)
return err
}
err = utils.ColorPrintYAML(output, nil, false)
err = utils.ColorPrintYAML(pkg, nil, false)
if err != nil {
return err
}
Expand Down
1 change: 0 additions & 1 deletion src/config/lang/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ $ zarf package mirror-resources <your-package.tar.zst> \
CmdPackageMirrorFlagComponents = "Comma-separated list of components to mirror. This list will be respected regardless of a component's 'required' or 'default' status. Globbing component names with '*' and deselecting components with a leading '-' are also supported."
CmdPackageMirrorFlagNoChecksum = "Turns off the addition of a checksum to image tags (as would be used by the Zarf Agent) while mirroring images."

CmdPackageInspectFlagSbom = "View SBOM contents while inspecting the package"
CmdPackageInspectFlagSbomOut = "Specify an output directory for the SBOMs from the inspected Zarf package"
CmdPackageInspectFlagListImages = "List images in the package (prints to stdout)"

Expand Down
Loading
Loading