mirror of https://github.com/k3d-io/k3d
commit
5e28779339
@ -0,0 +1,175 @@ |
||||
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 |
||||
} |
@ -0,0 +1,59 @@ |
||||
package run |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"log" |
||||
|
||||
"github.com/docker/docker/api/types/filters" |
||||
|
||||
"github.com/docker/docker/api/types" |
||||
"github.com/docker/docker/client" |
||||
) |
||||
|
||||
func createClusterNetwork(clusterName 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) |
||||
} |
||||
|
||||
resp, err := docker.NetworkCreate(ctx, clusterName, types.NetworkCreate{ |
||||
Labels: map[string]string{ |
||||
"app": "k3d", |
||||
"cluster": clusterName, |
||||
}, |
||||
}) |
||||
if err != nil { |
||||
return "", fmt.Errorf("ERROR: couldn't create network\n%+v", err) |
||||
} |
||||
|
||||
return resp.ID, nil |
||||
} |
||||
|
||||
func deleteClusterNetwork(clusterName string) error { |
||||
ctx := context.Background() |
||||
docker, err := client.NewEnvClient() |
||||
if err != nil { |
||||
return fmt.Errorf("ERROR: couldn't create docker client\n%+v", err) |
||||
} |
||||
|
||||
filters := filters.NewArgs() |
||||
filters.Add("label", "app=k3d") |
||||
filters.Add("label", fmt.Sprintf("cluster=%s", clusterName)) |
||||
|
||||
networks, err := docker.NetworkList(ctx, types.NetworkListOptions{ |
||||
Filters: filters, |
||||
}) |
||||
if err != nil { |
||||
return fmt.Errorf("ERROR: couldn't find network for cluster %s\n%+v", clusterName, err) |
||||
} |
||||
|
||||
for _, network := range networks { |
||||
if err := docker.NetworkRemove(ctx, network.ID); err != nil { |
||||
log.Printf("WARNING: couldn't remove network for cluster %s\n%+v", clusterName, err) |
||||
continue |
||||
} |
||||
} |
||||
return nil |
||||
} |
@ -1,18 +0,0 @@ |
||||
package run |
||||
|
||||
import ( |
||||
"log" |
||||
"os" |
||||
"os/exec" |
||||
) |
||||
|
||||
// runCommand accepts the name and args and runs the specified command
|
||||
func runCommand(verbose bool, name string, args ...string) error { |
||||
if verbose { |
||||
log.Printf("Running command: %+v", append([]string{name}, args...)) |
||||
} |
||||
cmd := exec.Command(name, args...) |
||||
cmd.Stdout = os.Stdout |
||||
cmd.Stderr = os.Stderr |
||||
return cmd.Run() |
||||
} |
@ -0,0 +1,37 @@ |
||||
package run |
||||
|
||||
import ( |
||||
"math/rand" |
||||
"strings" |
||||
"time" |
||||
) |
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |
||||
const ( |
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||
) |
||||
|
||||
var src = rand.NewSource(time.Now().UnixNano()) |
||||
|
||||
// GenerateRandomString thanks to https://stackoverflow.com/a/31832326/6450189
|
||||
func GenerateRandomString(n int) string { |
||||
|
||||
sb := strings.Builder{} |
||||
sb.Grow(n) |
||||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; { |
||||
if remain == 0 { |
||||
cache, remain = src.Int63(), letterIdxMax |
||||
} |
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) { |
||||
sb.WriteByte(letterBytes[idx]) |
||||
i-- |
||||
} |
||||
cache >>= letterIdxBits |
||||
remain-- |
||||
} |
||||
|
||||
return sb.String() |
||||
} |
Loading…
Reference in new issue