dive-zfs/dive/image/podman/resolver_linux.go
2019-10-08 10:14:46 -04:00

131 lines
2.7 KiB
Go

package podman
import (
"bufio"
"context"
"fmt"
"github.com/containers/libpod/libpod"
"github.com/wagoodman/dive/dive/image"
"github.com/wagoodman/dive/dive/image/docker"
"io/ioutil"
"os"
)
type resolver struct{}
func NewResolver() *resolver {
return &resolver{}
}
func (r *resolver) Build(args []string) (*image.Image, error) {
id, err := buildImageFromCli(args)
if err != nil {
return nil, err
}
return r.Fetch(id)
}
func (r *resolver) Fetch(id string) (*image.Image, error) {
// todo: there are still a number of bugs remaining with this approach --stick with the docker archive for now
// img, err := r.resolveFromDisk(id)
// if err == nil {
// return img, err
// }
img, err := r.resolveFromDockerArchive(id)
if err == nil {
return img, err
}
return nil, fmt.Errorf("unable to resolve image '%s'", id)
}
// func (r *resolver) resolveFromDisk(id string) (*image.Image, error) {
// var img *ImageDirectoryRef
// var err error
//
// runtime, err := libpod.NewRuntime(context.TODO())
// if err != nil {
// return nil, err
// }
//
// images, err := runtime.ImageRuntime().GetImages()
// if err != nil {
// return nil, err
// }
//
// ImageLoop:
// for _, candidateImage := range images {
// for _, name := range candidateImage.Names() {
// if name == id {
// img, err = NewImageDirectoryRef(candidateImage)
// if err != nil {
// return nil, err
// }
// break ImageLoop
// }
// }
// }
//
// if img == nil {
// return nil, fmt.Errorf("could not find image by name: '%s'", id)
// }
//
// return img.ToImage()
// }
func (r *resolver) resolveFromDockerArchive(id string) (*image.Image, error) {
path, err := r.fetchDockerArchive(id)
if err != nil {
return nil, err
}
defer os.Remove(path)
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
img, err := docker.NewImageArchive(ioutil.NopCloser(bufio.NewReader(file)))
if err != nil {
return nil, err
}
return img.ToImage()
}
func (r *resolver) fetchDockerArchive(id string) (string, error) {
var err error
var ctx = context.Background()
runtime, err := libpod.NewRuntime(ctx)
if err != nil {
return "", err
}
images, err := runtime.ImageRuntime().GetImages()
if err != nil {
return "", err
}
for _, item := range images {
for _, name := range item.Names() {
if name == id {
file, err := ioutil.TempFile(os.TempDir(), "dive-resolver-tar")
if err != nil {
return "", err
}
err = item.Save(ctx, "dive-export", "docker-archive", file.Name(), []string{}, false, false)
if err != nil {
return "", err
}
return file.Name(), nil
}
}
}
return "", fmt.Errorf("image could not be found")
}