58 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			58 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package docker
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"path/filepath"
 | |
| )
 | |
| 
 | |
| type IClient interface {
 | |
| 	Save(imageName, dest string) (string, error)
 | |
| }
 | |
| 
 | |
| var ErrDockerClientSave = errors.New("unable to save image into tar")
 | |
| 
 | |
| // Client is a simple Docker client wrapping the local Docker daemon.
 | |
| // It does not use the Docker API but instead shell command and collect the output.
 | |
| //
 | |
| // NOTE: for now, it's ok, it only needs one command so, no need to add a fat dedicated
 | |
| // library with full Docker client API.
 | |
| type Client struct{}
 | |
| 
 | |
| var _ IClient = (*Client)(nil)
 | |
| 
 | |
| func NewClient() Client {
 | |
| 	return Client{}
 | |
| }
 | |
| 
 | |
| // Save saves the `imageName` (tag included) in tar format in the target directory: `dest`.
 | |
| // The `dest` directory must exist with correct permissions.
 | |
| func (c *Client) Save(imageName, dest string) (string, error) {
 | |
| 	destInfo, err := os.Stat(dest)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("unable to stat file, dir=%s, err=%v", dest, err)
 | |
| 	}
 | |
| 
 | |
| 	if !destInfo.IsDir() {
 | |
| 		return "", fmt.Errorf("dest file must be a directory, dir=%s, err=%v", dest, err)
 | |
| 	}
 | |
| 
 | |
| 	tarFile := fmt.Sprintf("%s.tar", imageName)
 | |
| 
 | |
| 	cmd := exec.Command("docker", "save", "-o", tarFile, imageName)
 | |
| 	cmd.Dir = dest
 | |
| 	if _, err := cmd.Output(); err != nil {
 | |
| 		return "", fmt.Errorf(
 | |
| 			"%w, dir=%s, image=%s, err=%v",
 | |
| 			ErrDockerClientSave,
 | |
| 			dest,
 | |
| 			imageName,
 | |
| 			err,
 | |
| 		)
 | |
| 	}
 | |
| 
 | |
| 	return filepath.Join(dest, tarFile), nil
 | |
| }
 | 
