Little helper to run CNCF's k3s in Docker
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k3d/cli/container.go

176 lines
4.8 KiB

package run
import (
"context"
"fmt"
"io"
"io/ioutil"
"log"
"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"
)
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)
ctx := context.Background()
docker, err := client.NewEnvClient()
if err != nil {
return "", fmt.Errorf("ERROR: couldn't create docker client\n%+v", err)
}
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)
}
} else {
_, err := io.Copy(ioutil.Discard, reader)
if err != nil {
log.Printf("WARNING: couldn't get docker output\n%+v", err)
}
}
containerLabels := make(map[string]string)
containerLabels["app"] = "k3d"
containerLabels["component"] = "server"
containerLabels["created"] = time.Now().Format("2006-01-02 15:04:05")
containerLabels["cluster"] = name
containerName := fmt.Sprintf("k3d-%s-server", name)
containerPort := nat.Port(fmt.Sprintf("%s/tcp", port))
hostConfig := &container.HostConfig{
PortBindings: nat.PortMap{
containerPort: []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: port,
},
},
},
Privileged: true,
}
if len(volumes) > 0 && volumes[0] != "" {
hostConfig.Binds = volumes
}
networkingConfig := &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
name: &network.EndpointSettings{
Aliases: []string{containerName},
},
},
}
resp, err := docker.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: append([]string{"server"}, args...),
ExposedPorts: nat.PortSet{
containerPort: struct{}{},
},
Env: env,
Labels: containerLabels,
}, hostConfig, networkingConfig, containerName)
if err != nil {
return "", fmt.Errorf("ERROR: couldn't create container %s\n%+v", containerName, err)
}
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
}
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)
}
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)
}
}
containerLabels := make(map[string]string)
containerLabels["app"] = "k3d"
containerLabels["component"] = "worker"
containerLabels["created"] = time.Now().Format("2006-01-02 15:04:05")
containerLabels["cluster"] = name
containerName := fmt.Sprintf("k3d-%s-worker-%s", name, postfix)
env = append(env, fmt.Sprintf("K3S_URL=https://k3d-%s-server:%s", name, serverPort))
hostConfig := &container.HostConfig{
Tmpfs: map[string]string{
"/run": "",
"/var/run": "",
},
Privileged: true,
}
if len(volumes) > 0 && volumes[0] != "" {
hostConfig.Binds = volumes
}
networkingConfig := &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
name: &network.EndpointSettings{
Aliases: []string{containerName},
},
},
}
resp, err := docker.ContainerCreate(ctx, &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)
}
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
}
func removeContainer(ID string) error {
ctx := context.Background()
docker, err := client.NewEnvClient()
if err != nil {
return fmt.Errorf("ERROR: couldn't create docker client\n%+v", err)
}
if err := docker.ContainerRemove(ctx, ID, types.ContainerRemoveOptions{}); err != nil {
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)
}
}
return nil
}