pkg/executables/docker.go (125 lines of code) (raw):
package executables
import (
"context"
"fmt"
"strconv"
"strings"
"github.com/aws/eks-anywhere/pkg/logger"
)
// Temporary: Curated packages dev and prod accounts are currently hard coded
// This is because there is no mechanism to extract these values as of now.
const (
dockerPath = "docker"
defaultRegistry = "public.ecr.aws"
packageProdDomain = "783794618700.dkr.ecr.us-west-2.amazonaws.com"
packageDevDomain = "067575901363.dkr.ecr.us-west-2.amazonaws.com"
)
type Docker struct {
Executable
}
func NewDocker(executable Executable) *Docker {
return &Docker{Executable: executable}
}
func (d *Docker) GetDockerLBPort(ctx context.Context, clusterName string) (port string, err error) {
clusterLBName := fmt.Sprintf("%s-lb", clusterName)
if stdout, err := d.Execute(ctx, "port", clusterLBName, "6443/tcp"); err != nil {
return "", err
} else {
return strings.Split(stdout.String(), ":")[1], nil
}
}
func (d *Docker) PullImage(ctx context.Context, image string) error {
logger.V(2).Info("Pulling docker image", "image", image)
if _, err := d.Execute(ctx, "pull", image); err != nil {
return err
} else {
return nil
}
}
func (d *Docker) Version(ctx context.Context) (int, error) {
cmdOutput, err := d.Execute(ctx, "version", "--format", "{{.Client.Version}}")
if err != nil {
return 0, fmt.Errorf("please check if docker is installed and running %v", err)
}
dockerVersion := strings.TrimSpace(cmdOutput.String())
versionSplit := strings.Split(dockerVersion, ".")
installedMajorVersion := versionSplit[0]
installedMajorVersionInt, err := strconv.Atoi(installedMajorVersion)
if err != nil {
return 0, err
}
return installedMajorVersionInt, nil
}
func (d *Docker) AllocatedMemory(ctx context.Context) (uint64, error) {
cmdOutput, err := d.Execute(ctx, "info", "--format", "'{{json .MemTotal}}'")
if err != nil {
return 0, fmt.Errorf("please check if docker is installed and running %v", err)
}
totalMemory := cmdOutput.String()
totalMemory = totalMemory[1 : len(totalMemory)-2]
return strconv.ParseUint(totalMemory, 10, 64)
}
func (d *Docker) TagImage(ctx context.Context, image string, endpoint string) error {
replacer := strings.NewReplacer(defaultRegistry, endpoint, packageProdDomain, endpoint, packageDevDomain, endpoint)
localImage := replacer.Replace(image)
logger.Info("Tagging image", "image", image, "local image", localImage)
if _, err := d.Execute(ctx, "tag", image, localImage); err != nil {
return err
}
return nil
}
func (d *Docker) PushImage(ctx context.Context, image string, endpoint string) error {
replacer := strings.NewReplacer(defaultRegistry, endpoint, packageProdDomain, endpoint, packageDevDomain, endpoint)
localImage := replacer.Replace(image)
logger.Info("Pushing", "image", localImage)
if _, err := d.Execute(ctx, "push", localImage); err != nil {
return err
}
return nil
}
func (d *Docker) Login(ctx context.Context, endpoint, username, password string) error {
params := []string{"login", endpoint, "--username", username, "--password-stdin"}
logger.Info(fmt.Sprintf("Logging in to docker registry %s", endpoint))
_, err := d.ExecuteWithStdin(ctx, []byte(password), params...)
return err
}
func (d *Docker) LoadFromFile(ctx context.Context, filepath string) error {
if _, err := d.Execute(ctx, "load", "-i", filepath); err != nil {
return fmt.Errorf("loading images from file: %v", err)
}
return nil
}
func (d *Docker) SaveToFile(ctx context.Context, filepath string, images ...string) error {
params := make([]string, 0, 3+len(images))
params = append(params, "save", "-o", filepath)
params = append(params, images...)
if _, err := d.Execute(ctx, params...); err != nil {
return fmt.Errorf("saving images to file: %v", err)
}
return nil
}
func (d *Docker) Run(ctx context.Context, image string, name string, cmd []string, flags ...string) error {
params := []string{"run", "-d", "-i"}
params = append(params, flags...)
params = append(params, "--name", name, image)
params = append(params, cmd...)
if _, err := d.Execute(ctx, params...); err != nil {
return fmt.Errorf("running docker container %s with image %s: %v", name, image, err)
}
return nil
}
func (d *Docker) ForceRemove(ctx context.Context, name string) error {
params := []string{"rm", "-f", name}
if _, err := d.Execute(ctx, params...); err != nil {
return fmt.Errorf("force removing docker container %s: %v", name, err)
}
return nil
}
// CheckContainerExistence checks whether a Docker container with the provided name exists
// It returns true if a container with the name exists, false if it doesn't and an error if it encounters some other error.
func (d *Docker) CheckContainerExistence(ctx context.Context, name string) (bool, error) {
params := []string{"container", "inspect", name}
_, err := d.Execute(ctx, params...)
if err == nil {
return true, nil
} else if strings.Contains(err.Error(), "No such container") {
return false, nil
}
return false, fmt.Errorf("checking if a docker container with name %s exists: %v", name, err)
}