2020-02-06 11:47:45 +02:00
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util"
|
|
|
|
"github.com/google/go-containerregistry/pkg/legacy/tarball"
|
|
|
|
"github.com/google/go-containerregistry/pkg/name"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Client defines an docker client object
|
|
|
|
type Client struct {
|
|
|
|
imageName string
|
|
|
|
registryURL string
|
|
|
|
localPath string
|
|
|
|
includeLayers bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// ClientOptions defines the options to be set on the client
|
|
|
|
type ClientOptions struct {
|
|
|
|
ImageName string
|
|
|
|
RegistryURL string
|
|
|
|
LocalPath string
|
|
|
|
IncludeLayers bool
|
|
|
|
}
|
|
|
|
|
|
|
|
//Download interface for download an image to a local path
|
|
|
|
type Download interface {
|
|
|
|
GetImageSource() (string, error)
|
|
|
|
DownloadImageToPath(imageSource, filePath string) (pkgutil.Image, error)
|
2020-02-06 12:14:11 +02:00
|
|
|
TarImage(writer io.Writer, image pkgutil.Image) error
|
2020-02-06 11:47:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetOptions sets options used for the docker client
|
|
|
|
func (c *Client) SetOptions(options ClientOptions) {
|
|
|
|
c.imageName = options.ImageName
|
|
|
|
c.registryURL = options.RegistryURL
|
|
|
|
c.includeLayers = options.IncludeLayers
|
|
|
|
c.localPath = options.LocalPath
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
daemonPrefix = "daemon://"
|
|
|
|
remotePrefix = "remote://"
|
|
|
|
)
|
|
|
|
|
|
|
|
//GetImageSource get the image source from client attributes (localPath, imageName, registryURL)
|
|
|
|
func (c *Client) GetImageSource() (string, error) {
|
|
|
|
|
|
|
|
imageSource := c.imageName
|
|
|
|
|
|
|
|
if len(c.registryURL) > 0 && len(c.localPath) <= 0 {
|
|
|
|
registry := c.registryURL
|
|
|
|
|
2021-08-17 15:52:18 +02:00
|
|
|
url, err := url.Parse(c.registryURL)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed to parse registryURL %v: %w", c.registryURL, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
//remove protocol from registryURL to get registry
|
2020-02-06 11:47:45 +02:00
|
|
|
if len(url.Scheme) > 0 {
|
|
|
|
registry = strings.Replace(c.registryURL, fmt.Sprintf("%v://", url.Scheme), "", 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.HasSuffix(registry, "/") {
|
|
|
|
imageSource = fmt.Sprintf("%v%v%v", remotePrefix, registry, c.imageName)
|
|
|
|
} else {
|
|
|
|
imageSource = fmt.Sprintf("%v%v/%v", remotePrefix, registry, c.imageName)
|
|
|
|
}
|
|
|
|
} else if len(c.localPath) > 0 {
|
|
|
|
imageSource = c.localPath
|
|
|
|
if !pkgutil.IsTar(c.localPath) {
|
|
|
|
imageSource = fmt.Sprintf("%v%v", daemonPrefix, c.localPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(imageSource) <= 0 {
|
2020-10-05 17:46:44 +02:00
|
|
|
return imageSource, fmt.Errorf("no image found for the parameters: (Name: %v, Registry: %v, local Path: %v)", c.imageName, c.registryURL, c.localPath)
|
2020-02-06 11:47:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return imageSource, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//DownloadImageToPath download the image to the specified path
|
|
|
|
func (c *Client) DownloadImageToPath(imageSource, filePath string) (pkgutil.Image, error) {
|
|
|
|
|
|
|
|
return pkgutil.GetImage(imageSource, c.includeLayers, filePath)
|
|
|
|
}
|
|
|
|
|
|
|
|
//TarImage write a tar from the given image
|
|
|
|
func (c *Client) TarImage(writer io.Writer, image pkgutil.Image) error {
|
|
|
|
|
|
|
|
reference, err := name.ParseReference(image.Digest.String(), name.WeakValidation)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = tarball.Write(reference, image.Image, writer)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|