package main import ( "fmt" "os" "strings" diffapi "github.com/containerd/containerd/api/services/diff" snapshotapi "github.com/containerd/containerd/api/services/snapshot" "github.com/containerd/containerd/images" "github.com/containerd/containerd/log" "github.com/containerd/containerd/rootfs" diffservice "github.com/containerd/containerd/services/diff" snapshotservice "github.com/containerd/containerd/services/snapshot" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/urfave/cli" ) var rootfsCommand = cli.Command{ Name: "rootfs", Usage: "rootfs setups a rootfs", Subcommands: []cli.Command{ rootfsUnpackCommand, rootfsPrepareCommand, }, } var rootfsUnpackCommand = cli.Command{ Name: "unpack", Usage: "unpack applies layers from a manifest to a snapshot", ArgsUsage: "[flags] ", Flags: []cli.Flag{}, Action: func(clicontext *cli.Context) error { ctx, cancel := appContext() defer cancel() dgst, err := digest.Parse(clicontext.Args().First()) if err != nil { return err } log.G(ctx).Infof("unpacking layers from manifest %s", dgst.String()) cs, err := resolveContentStore(clicontext) if err != nil { return err } image := images.Image{ Target: ocispec.Descriptor{ MediaType: ocispec.MediaTypeImageManifest, Digest: dgst, }, } layers, err := getImageLayers(ctx, image, cs) if err != nil { log.G(ctx).WithError(err).Fatal("Failed to get rootfs layers") } conn, err := connectGRPC(clicontext) if err != nil { log.G(ctx).Fatal(err) } snapshotter := snapshotservice.NewSnapshotterFromClient(snapshotapi.NewSnapshotClient(conn)) applier := diffservice.NewDiffServiceFromClient(diffapi.NewDiffClient(conn)) chainID, err := rootfs.ApplyLayers(ctx, layers, snapshotter, applier) if err != nil { return err } log.G(ctx).Infof("chain ID: %s", chainID.String()) return nil }, } var rootfsPrepareCommand = cli.Command{ Name: "prepare", Usage: "prepare gets mount commands for digest", ArgsUsage: "[flags] ", Flags: []cli.Flag{}, Action: func(clicontext *cli.Context) error { ctx, cancel := appContext() defer cancel() if clicontext.NArg() != 2 { return cli.ShowSubcommandHelp(clicontext) } dgst, err := digest.Parse(clicontext.Args().Get(0)) if err != nil { return err } target := clicontext.Args().Get(1) log.G(ctx).Infof("preparing mounts %s", dgst.String()) conn, err := connectGRPC(clicontext) if err != nil { return err } snapshotter := snapshotservice.NewSnapshotterFromClient(snapshotapi.NewSnapshotClient(conn)) mounts, err := snapshotter.Prepare(ctx, target, dgst.String()) if err != nil { return err } for _, m := range mounts { fmt.Fprintf(os.Stdout, "mount -t %s %s %s -o %s\n", m.Type, m.Source, target, strings.Join(m.Options, ",")) } return nil }, }