From 4795c993ee979829d66a43c47a6fc9975f037d78 Mon Sep 17 00:00:00 2001 From: Avi Deitcher Date: Tue, 18 May 2021 20:27:24 +0300 Subject: [PATCH] Add support for cache export Signed-off-by: Avi Deitcher --- src/cmd/linuxkit/cache.go | 3 ++ src/cmd/linuxkit/cache_export.go | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/cmd/linuxkit/cache_export.go diff --git a/src/cmd/linuxkit/cache.go b/src/cmd/linuxkit/cache.go index 51065e013..a933d5fec 100644 --- a/src/cmd/linuxkit/cache.go +++ b/src/cmd/linuxkit/cache.go @@ -15,6 +15,7 @@ func cacheUsage() { fmt.Printf("Supported commands are\n") // Please keep these in alphabetical order fmt.Printf(" clean\n") + fmt.Printf(" export\n") fmt.Printf(" ls\n") fmt.Printf("\n") fmt.Printf("'options' are the backend specific options.\n") @@ -33,6 +34,8 @@ func cache(args []string) { cacheClean(args[1:]) case "ls": cacheList(args[1:]) + case "export": + cacheExport(args[1:]) case "help", "-h", "-help", "--help": cacheUsage() os.Exit(0) diff --git a/src/cmd/linuxkit/cache_export.go b/src/cmd/linuxkit/cache_export.go new file mode 100644 index 000000000..9f5ada8c1 --- /dev/null +++ b/src/cmd/linuxkit/cache_export.go @@ -0,0 +1,71 @@ +package main + +import ( + "flag" + "io" + "os" + "runtime" + + "github.com/containerd/containerd/reference" + cachepkg "github.com/linuxkit/linuxkit/src/cmd/linuxkit/cache" + "github.com/linuxkit/linuxkit/src/cmd/linuxkit/util" + log "github.com/sirupsen/logrus" +) + +func cacheExport(args []string) { + fs := flag.NewFlagSet("export", flag.ExitOnError) + + cacheDir := fs.String("cache", defaultLinuxkitCache(), "Directory for caching and finding cached image") + arch := fs.String("arch", runtime.GOARCH, "Architecture to resolve an index to an image, if the provided image name is an index") + outfile := fs.String("outfile", "", "Path to file to save output, '-' for stdout") + + if err := fs.Parse(args); err != nil { + log.Fatal("Unable to parse args") + } + + // get the requested images + if fs.NArg() < 1 { + log.Fatal("At least one image name is required") + } + names := fs.Args() + name := names[0] + fullname := util.ReferenceExpand(name) + + p, err := cachepkg.NewProvider(*cacheDir) + if err != nil { + log.Fatalf("unable to read a local cache: %v", err) + } + desc, err := p.FindDescriptor(fullname) + if err != nil { + log.Fatalf("unable to find image named %s: %v", name, err) + } + ref, err := reference.Parse(fullname) + if err != nil { + log.Fatalf("invalid image name %s: %v", name, err) + } + + src := p.NewSource(&ref, *arch, desc) + reader, err := src.V1TarReader() + if err != nil { + log.Fatalf("error getting reader for image %s: %v", name, err) + } + defer reader.Close() + + // try to write the output file + var w io.Writer + switch { + case outfile == nil, *outfile == "": + log.Fatal("'outfile' flag is required") + case *outfile == "-": + w = os.Stdout + default: + f, err := os.OpenFile(*outfile, os.O_CREATE|os.O_RDWR, 0644) + if err != nil { + log.Fatalf("unable to open %s: %v", *outfile, err) + } + defer f.Close() + w = f + } + + io.Copy(w, reader) +}