Skip to content

Commit

Permalink
Merge pull request #27 from ibuildthecloud/pull
Browse files Browse the repository at this point in the history
[ENHANCEMENT] Only pull image if the image is not found and always force remove containers (thanks @ibuildthecloud )
  • Loading branch information
iwilltry42 authored May 4, 2019
2 parents 6570d96 + 7c76f46 commit a0d9089
Showing 1 changed file with 46 additions and 65 deletions.
111 changes: 46 additions & 65 deletions cli/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,58 @@ import (
"os"
"time"

"github.com/docker/go-connections/nat"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
)

// createServer creates and starts a k3s server container
func createServer(verbose bool, image string, port string, args []string, env []string, name string, volumes []string) (string, error) {
log.Printf("Creating server using %s...\n", image)
func startContainer(verbose bool, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (string, error) {
ctx := context.Background()

docker, err := client.NewEnvClient()
if err != nil {
return "", fmt.Errorf("ERROR: couldn't create docker client\n%+v", err)
}

// pull the required docker image
reader, err := docker.ImagePull(ctx, image, types.ImagePullOptions{})
if err != nil {
return "", fmt.Errorf("ERROR: couldn't pull image %s\n%+v", image, err)
}
if verbose {
_, err := io.Copy(os.Stdout, reader)
resp, err := docker.ContainerCreate(ctx, config, hostConfig, networkingConfig, containerName)
if client.IsErrImageNotFound(err) {
log.Printf("Pulling image %s...\n", config.Image)
reader, err := docker.ImagePull(ctx, config.Image, types.ImagePullOptions{})
if err != nil {
log.Printf("WARNING: couldn't get docker output\n%+v", err)
return "", fmt.Errorf("ERROR: couldn't pull image %s\n%+v", config.Image, err)
}
defer reader.Close()
if verbose {
_, err := io.Copy(os.Stdout, reader)
if err != nil {
log.Printf("WARNING: couldn't get docker output\n%+v", err)
}
} else {
_, err := io.Copy(ioutil.Discard, reader)
if err != nil {
log.Printf("WARNING: couldn't get docker output\n%+v", err)
}
}
} else {
_, err := io.Copy(ioutil.Discard, reader)
resp, err = docker.ContainerCreate(ctx, config, hostConfig, networkingConfig, containerName)
if err != nil {
log.Printf("WARNING: couldn't get docker output\n%+v", err)
return "", fmt.Errorf("ERROR: couldn't create container after pull %s\n%+v", containerName, err)
}
} else if err != nil {
return "", fmt.Errorf("ERROR: couldn't create container %s\n%+v", containerName, err)
}

// configure container options (host/network configuration, labels, env vars, etc.)
if err := docker.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
return "", err
}

return resp.ID, nil
}

func createServer(verbose bool, image string, port string, args []string, env []string, name string, volumes []string) (string, error) {
log.Printf("Creating server using %s...\n", image)

containerLabels := make(map[string]string)
containerLabels["app"] = "k3d"
containerLabels["component"] = "server"
Expand Down Expand Up @@ -77,56 +94,31 @@ func createServer(verbose bool, image string, port string, args []string, env []

networkingConfig := &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
name: &network.EndpointSettings{
name: {
Aliases: []string{containerName},
},
},
}

// create the container
resp, err := docker.ContainerCreate(ctx, &container.Config{
config := &container.Config{
Image: image,
Cmd: append([]string{"server"}, args...),
ExposedPorts: nat.PortSet{
containerPort: struct{}{},
},
Env: env,
Labels: containerLabels,
}, hostConfig, networkingConfig, containerName)
}
id, err := startContainer(verbose, config, hostConfig, networkingConfig, containerName)
if err != nil {
return "", fmt.Errorf("ERROR: couldn't create container %s\n%+v", containerName, err)
}

// start the container
if err := docker.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
return "", fmt.Errorf("ERROR: couldn't start container %s\n%+v", containerName, err)
}

return resp.ID, nil

return id, nil
}

// createWorker creates/starts a k3s agent node that connects to the server
func createWorker(verbose bool, image string, args []string, env []string, name string, volumes []string, postfix string, serverPort string) (string, error) {
ctx := context.Background()
docker, err := client.NewEnvClient()
if err != nil {
return "", fmt.Errorf("ERROR: couldn't create docker client\n%+v", err)
}

// pull the required docker image
reader, err := docker.ImagePull(ctx, image, types.ImagePullOptions{})
if err != nil {
return "", fmt.Errorf("ERROR: couldn't pull image %s\n%+v", image, err)
}
if verbose {
_, err := io.Copy(os.Stdout, reader)
if err != nil {
log.Printf("WARNING: couldn't get docker output\n%+v", err)
}
}

// configure container options (host/network configuration, labels, env vars, etc.)
containerLabels := make(map[string]string)
containerLabels["app"] = "k3d"
containerLabels["component"] = "worker"
Expand All @@ -151,28 +143,24 @@ func createWorker(verbose bool, image string, args []string, env []string, name

networkingConfig := &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
name: &network.EndpointSettings{
name: {
Aliases: []string{containerName},
},
},
}

// create the container
resp, err := docker.ContainerCreate(ctx, &container.Config{
config := &container.Config{
Image: image,
Env: env,
Labels: containerLabels,
}, hostConfig, networkingConfig, containerName)
if err != nil {
return "", fmt.Errorf("ERROR: couldn't create container %s\n%+v", containerName, err)
}

// start the container
if err := docker.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
id, err := startContainer(verbose, config, hostConfig, networkingConfig, containerName)
if err != nil {
return "", fmt.Errorf("ERROR: couldn't start container %s\n%+v", containerName, err)
}

return resp.ID, nil
return id, nil
}

// removeContainer tries to rm a container, selected by Docker ID, and does a rm -f if it fails (e.g. if container is still running)
Expand All @@ -184,15 +172,8 @@ func removeContainer(ID string) error {
if err != nil {
return fmt.Errorf("ERROR: couldn't create docker client\n%+v", err)
}

// first, try a soft remove
if err := docker.ContainerRemove(ctx, ID, types.ContainerRemoveOptions{}); err != nil {

// if soft remove didn't succeed, force remove the container
log.Printf("WARNING: couldn't delete container [%s], trying a force remove now.", ID)
if err := docker.ContainerRemove(ctx, ID, types.ContainerRemoveOptions{Force: true}); err != nil {
return fmt.Errorf("FAILURE: couldn't delete container [%s] -> %+v", ID, err)
}
if err := docker.ContainerRemove(ctx, ID, types.ContainerRemoveOptions{Force: true}); err != nil {
return fmt.Errorf("FAILURE: couldn't delete container [%s] -> %+v", ID, err)
}
return nil
}

0 comments on commit a0d9089

Please sign in to comment.