package flatten import ( "context" "fmt" "log" v1 "github.com/google/go-containerregistry/pkg/v1" "edge-infra.dev/pkg/f8n/warehouse" "edge-infra.dev/pkg/f8n/warehouse/lift" "edge-infra.dev/pkg/f8n/warehouse/lift/cmd/internal" "edge-infra.dev/pkg/f8n/warehouse/oci" "edge-infra.dev/pkg/f8n/warehouse/oci/layout" "edge-infra.dev/pkg/f8n/warehouse/oci/mutate" "edge-infra.dev/pkg/f8n/warehouse/oci/name" "edge-infra.dev/pkg/lib/cli/rags" "edge-infra.dev/pkg/lib/cli/sink" ) // TODO(aw185176): allow overriding tag? func New(cfg lift.Config) *sink.Command { var ( packer = internal.NewPacker(cfg) push bool ) cmd := &sink.Command{ Use: "flatten [flags] ", Short: "flatten a package by removing composite packages", Flags: []*rags.Rag{ { Name: "push", Usage: "push flattened pallet to configured Warehouse registry", Value: &rags.Bool{Var: &push}, Short: "p", }, }, Extensions: []sink.Extension{packer}, Exec: func(_ context.Context, r sink.Run) error { switch len(r.Args()) { case 0: return fmt.Errorf("error: a package to flatten is required") case 1: // only valid number of r.Args() default: return fmt.Errorf("error: only one package can be provided") } if push && cfg.Repo == "" { return fmt.Errorf("error: oci repo is required for pushing\n" + "set one via the --warehouse-oci-repo flag or setting the " + "WAREHOUSE_OCI_REPO environment variable") } artifact, err := internal.ResolveArtifact(packer, r.Args()[0]) if err != nil { return err } if a, ok := artifact.(oci.Unwrapper); ok { artifact = a.Unwrap() } mt, err := artifact.MediaType() if err != nil { return err } if mt.IsImage() { log.Println("input is Image, which can't be flattened") return nil } // TODO(aw185176): smooth out these APIs idx, err := mutate.Flatten(artifact.(v1.ImageIndex)) if err != nil { return err } annos, err := oci.Annotations(idx) if err != nil { return err } ref, err := name.Tag(fmt.Sprintf("%s:squashed", annos[warehouse.AnnotationName])) if err != nil { return fmt.Errorf("failed to parse reference for flattened index: %w", err) } l, err := layout.New(cfg.Cache) if err != nil { return err } if err := l.Append(ref, idx); err != nil { return err } d, err := idx.Digest() if err != nil { return err } log.Printf("%s:squashed (%s)", annos[warehouse.AnnotationName], d) return nil }, } return cmd }