diff --git a/cmd/policy/save.go b/cmd/policy/save.go index 6379670..05e0332 100644 --- a/cmd/policy/save.go +++ b/cmd/policy/save.go @@ -2,7 +2,7 @@ package main type SaveCmd struct { Policy string `arg:"" name:"policy" help:"Policy to save."` - File string `name:"file" short:"f" help:"Output file path" default:"bundle.tar.gz"` + File string `name:"file" short:"f" help:"Output file path, '-' is accepted for stdout" default:"bundle.tar.gz"` } func (c *SaveCmd) Run(g *Globals) error { diff --git a/pkg/app/save.go b/pkg/app/save.go index db7a192..f8f91db 100644 --- a/pkg/app/save.go +++ b/pkg/app/save.go @@ -4,12 +4,14 @@ import ( "io" "os" + v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "oras.land/oras-go/pkg/content" ) func (c *PolicyApp) Save(userRef, outputFile string) error { defer c.Cancel() + var o *os.File ref, err := c.calculatePolicyRef(userRef) if err != nil { @@ -33,30 +35,44 @@ func (c *PolicyApp) Save(userRef, outputFile string) error { return errors.Errorf("policy [%s] not found in the local store", ref) } - c.UI.Normal(). - WithStringValue("digest", refDescriptor.Digest.String()). - Msgf("Resolved ref [%s].", ref) + if outputFile == "-" { + o = os.Stdout + } else { + c.UI.Normal(). + WithStringValue("digest", refDescriptor.Digest.String()). + Msgf("Resolved ref [%s].", ref) + o, err = os.Create(outputFile) - reader, err := ociStore.ReaderAt(c.Context, refDescriptor) + if err != nil { + return errors.Wrapf(err, "failed to create output file [%s]", outputFile) + } + + defer func() { + err := o.Close() + if err != nil { + c.UI.Problem().WithErr(err).Msg("Failed to close policy bundle tarball.") + } + }() + } + + err = c.writePolicy(ociStore, &refDescriptor, o) if err != nil { - return errors.Wrap(err, "failed to open store reader") + return err } - defer func() { - err := reader.Close() - if err != nil { - c.UI.Problem().WithErr(err).Msg("Failed to close OCI policy reader.") - } - }() + return nil +} - o, err := os.Create(outputFile) +func (c *PolicyApp) writePolicy(ociStore *content.OCIStore, refDescriptor *v1.Descriptor, o *os.File) error { + reader, err := ociStore.ReaderAt(c.Context, *refDescriptor) if err != nil { - return errors.Wrapf(err, "failed to create output file [%s]", outputFile) + return errors.Wrap(err, "failed to open store reader") } + defer func() { - err := o.Close() + err := reader.Close() if err != nil { - c.UI.Problem().WithErr(err).Msg("Failed to close policy bundle tarball.") + c.UI.Problem().WithErr(err).Msg("Failed to close OCI policy reader.") } }() @@ -84,6 +100,5 @@ func (c *PolicyApp) Save(userRef, outputFile string) error { i += chunkSize } - return nil }