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