specify role, image and labels

pull/227/head
iwilltry42 5 years ago
parent 2217048daf
commit 43eb626b0c
  1. 4
      cmd/create/createCluster.go
  2. 41
      cmd/create/createNode.go
  3. 2
      go.mod
  4. 38
      pkg/cluster/node.go
  5. 34
      pkg/runtimes/containerd/container.go
  6. 9
      pkg/runtimes/docker/container.go
  7. 23
      pkg/types/types.go

@ -49,8 +49,10 @@ func NewCmdCreateCluster() *cobra.Command {
}
// add flags
cmd.Flags().StringP("api-port", "a", "6443", "Specify the Kubernetes cluster API server port (Format: `--api-port [host:]port`")
cmd.Flags().StringP("api-port", "a", "6443", "Specify the Kubernetes API server port (Format: `--api-port [host:]port`")
cmd.Flags().IntP("masters", "m", 1, "Specify how many masters you want to create")
cmd.Flags().IntP("workers", "w", 0, "Specify how many workers you want to create")
cmd.Flags().String("config", "", "Specify a cluster configuration file") // TODO: to implement
// add subcommands

@ -42,40 +42,67 @@ func NewCmdCreateNode() *cobra.Command {
Long: `Create a new containerized k3s node (k3s in docker).`,
Args: cobra.ExactArgs(1), // exactly one name accepted // TODO: if not specified, inherit from cluster that the node shall belong to, if that is specified
Run: func(cmd *cobra.Command, args []string) {
runtime, nodes := parseCreateNodeCmd(cmd, args)
cluster.CreateNodes(nodes, runtime)
cluster.CreateNodes(parseCreateNodeCmd(cmd, args))
},
}
// add flags
cmd.Flags().Int("replicas", 1, "Number of replicas of this node specification.")
cmd.Flags().String("role", "worker", "Specify node role [master, worker]")
cmd.Flags().StringP("cluster", "c", "", "Select the cluster that the node shall connect to.")
cmd.Flags().String("image", k3d.DefaultK3sImageRepo, "Specify k3s image used for the node(s)")
// done
return cmd
}
// parseCreateNodeCmd parses the command input into variables required to create a cluster
func parseCreateNodeCmd(cmd *cobra.Command, args []string) (runtimes.Runtime, []*k3d.Node) {
func parseCreateNodeCmd(cmd *cobra.Command, args []string) ([]*k3d.Node, runtimes.Runtime) {
// --runtime
rt, err := cmd.Flags().GetString("runtime")
if err != nil {
log.Fatalln("Runtime not defined")
log.Fatalln("No runtime specified")
}
runtime, err := runtimes.GetRuntime(rt)
if err != nil {
log.Fatalln(err)
}
// --replicas
replicas, err := cmd.Flags().GetInt("replicas")
if err != nil {
log.Errorln("Failed to parse flag '--replicas'")
log.Errorln("No replica count specified")
log.Fatalln(err)
}
// --role
role, err := cmd.Flags().GetString("role")
if err != nil {
log.Errorln("No node role specified")
log.Fatalln(err)
}
if _, ok := k3d.DefaultK3dRoles[role]; !ok {
log.Fatalf("Unknown node role '%s'\n", role)
}
// --image
image, err := cmd.Flags().GetString("image")
if err != nil {
log.Errorln("No image specified")
log.Fatalln(err)
}
// generate list of nodes
nodes := []*k3d.Node{}
for i := 0; i < replicas; i++ {
nodes = append(nodes, &k3d.Node{Name: fmt.Sprintf("%s-%d", args[0], i)})
node := &k3d.Node{
Name: fmt.Sprintf("%s-%s-%d", k3d.DefaultObjectNamePrefix, args[0], i),
Role: role,
Image: image,
}
nodes = append(nodes, node)
}
return runtime, nodes
return nodes, runtime
}

@ -21,7 +21,6 @@ require (
github.com/google/go-cmp v0.3.0 // indirect
github.com/gorilla/mux v1.7.3 // indirect
github.com/imdario/mergo v0.3.7 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
@ -29,7 +28,6 @@ require (
github.com/opencontainers/runtime-spec v1.0.1 // indirect
github.com/sirupsen/logrus v1.4.2
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.3.2
github.com/stretchr/testify v1.4.0 // indirect
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
go.etcd.io/bbolt v1.3.3 // indirect

@ -23,6 +23,8 @@ THE SOFTWARE.
package cluster
import (
"fmt"
k3drt "github.com/rancher/k3d/pkg/runtimes"
k3dContainerd "github.com/rancher/k3d/pkg/runtimes/containerd"
k3dDocker "github.com/rancher/k3d/pkg/runtimes/docker"
@ -40,17 +42,40 @@ func CreateNodes(nodes []*k3d.Node, runtime k3drt.Runtime) { // TODO: pass `--at
}
// CreateNode creates a new containerized k3s node
func CreateNode(nodeSpec *k3d.Node, runtime k3drt.Runtime) error {
log.Debugf("Creating node from spec\n%+v", nodeSpec)
if err := runtime.CreateNode(nodeSpec); err != nil {
log.Error(err)
func CreateNode(node *k3d.Node, runtime k3drt.Runtime) error {
log.Debugf("Creating node from spec\n%+v", node)
/*
* CONFIGURATION
*/
// global node configuration (applies for any node role)
node.Labels = k3d.DefaultObjectLabels
// specify options depending on node role
if node.Role == "worker" { // TODO: check here AND in CLI or only here?
node.Cmd = []string{"agent"}
node.Labels["role"] = "worker"
} else if node.Role == "master" {
node.Cmd = []string{"server"}
node.Labels["role"] = "master"
} else {
return fmt.Errorf("Unknown node role '%s'", node.Role)
}
/*
* CREATION
*/
if err := runtime.CreateNode(node); err != nil {
return err
}
log.Debugln("...success")
return nil
}
// DeleteNode deletes an existing node
func DeleteNode(nodeSpec *k3d.Node, runtimeChoice string) error {
func DeleteNode(node *k3d.Node, runtimeChoice string) error {
var runtime k3drt.Runtime
if runtimeChoice == "docker" {
runtime = k3dDocker.Docker{}
@ -58,9 +83,10 @@ func DeleteNode(nodeSpec *k3d.Node, runtimeChoice string) error {
runtime = k3dContainerd.Containerd{}
}
if err := runtime.DeleteNode(nodeSpec); err != nil {
if err := runtime.DeleteNode(node); err != nil {
log.Error(err)
}
log.Infoln("Deleted", node.Name)
log.Debugln("...success")
return nil
}

@ -32,8 +32,10 @@ import (
)
// CreateNode creates a new k3d node
func (d Containerd) CreateNode(nodeSpec *k3d.Node) error {
func (d Containerd) CreateNode(node *k3d.Node) error {
log.Debugln("containerd.CreateNode...")
// create containerd client
ctx := context.Background()
clientOpts := []containerd.ClientOpt{
containerd.WithDefaultNamespace("k3d"),
@ -43,26 +45,38 @@ func (d Containerd) CreateNode(nodeSpec *k3d.Node) error {
log.Errorln("Failed to create containerd client")
return err
}
// create container
newContainerOpts := []containerd.NewContainerOpts{
func(ctx context.Context, _ *containerd.Client, c *containers.Container) error {
c.Image = "docker.io/nginx:latest"
c.Labels = map[string]string{
"runtime": "containerd",
}
c.Image = node.Image
c.Labels = node.Labels
return nil
},
}
resp, err := client.NewContainer(ctx, "test-containerd", newContainerOpts...)
container, err := client.NewContainer(ctx, node.Name, newContainerOpts...)
if err != nil {
log.Errorln("Couldn't create container")
return err
}
log.Infoln("Created container with ID", resp.ID())
/*
// start container
task, err := container.NewTask(ctx, cio.NewCreator()) // TODO: how the hell does this work?
if err != nil {
log.Errorln("Failed to create task in container", container.ID)
return err
}
task.Start(ctx)
*/
log.Infoln("Created container with ID", container.ID())
return nil
}
// DeleteNode deletes an existing k3d node
func (d Containerd) DeleteNode(nodeSpec *k3d.Node) error {
func (d Containerd) DeleteNode(node *k3d.Node) error {
log.Debugln("containerd.DeleteNode...")
ctx := context.Background()
clientOpts := []containerd.ClientOpt{
@ -74,9 +88,9 @@ func (d Containerd) DeleteNode(nodeSpec *k3d.Node) error {
return err
}
container, err := client.LoadContainer(ctx, nodeSpec.Name)
container, err := client.LoadContainer(ctx, node.Name)
if err != nil {
log.Errorln("Couldn't load container", nodeSpec.Name)
log.Errorln("Couldn't load container", node.Name)
return err
}
if err = container.Delete(ctx, []containerd.DeleteOpts{}...); err != nil {

@ -35,7 +35,7 @@ import (
)
// CreateNode creates a new container
func (d Docker) CreateNode(nodeSpec *k3d.Node) error {
func (d Docker) CreateNode(node *k3d.Node) error {
log.Debugln("docker.CreateNode...")
ctx := context.Background() // TODO: check how kind handles contexts
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
@ -44,11 +44,12 @@ func (d Docker) CreateNode(nodeSpec *k3d.Node) error {
}
containerConfig := container.Config{
Cmd: []string{"sh"},
Image: "nginx",
Cmd: node.Cmd,
Image: node.Image,
Labels: node.Labels,
}
resp, err := docker.ContainerCreate(ctx, &containerConfig, &container.HostConfig{}, &network.NetworkingConfig{}, nodeSpec.Name)
resp, err := docker.ContainerCreate(ctx, &containerConfig, &container.HostConfig{}, &network.NetworkingConfig{}, node.Name)
if err != nil {
log.Error("Couldn't create container")
return err

@ -36,7 +36,10 @@ const DefaultClusterNameMaxLength = 32
const DefaultK3sImageRepo = "docker.io/rancher/k3s"
// DefaultObjectNamePrefix defines the name prefix for every object created by k3d
const DefaultObjectNamePrefix = "k3d-"
const DefaultObjectNamePrefix = "k3d"
// DefaultK3dRoles defines the roles available for nodes
var DefaultK3dRoles = map[string]bool{"master": true, "worker": true}
// DefaultObjectLabels specifies a set of labels that will be attached to k3d objects by default
var DefaultObjectLabels = map[string]string{
@ -53,14 +56,16 @@ type Cluster struct {
// Node describes a k3d node
type Node struct {
Name string `yaml:"name" json:"name,omitempty"`
Role string `yaml:"role" json:"role,omitempty"`
Image string `yaml:"image" json:"image,omitempty"`
Volumes []string `yaml:"volumes" json:"volumes,omitempty"`
Env []string `yaml:"env" json:"env,omitempty"`
Args []string `yaml:"extra_args" json:"extraArgs,omitempty"`
Ports []string `yaml:"port_mappings" json:"portMappings,omitempty"` // TODO: make a struct out of this?
Restart bool `yaml:"restart" json:"restart,omitempty"`
Name string `yaml:"name" json:"name,omitempty"`
Role string `yaml:"role" json:"role,omitempty"`
Image string `yaml:"image" json:"image,omitempty"`
Volumes []string `yaml:"volumes" json:"volumes,omitempty"`
Env []string `yaml:"env" json:"env,omitempty"`
Cmd []string // filled automatically depending on role (master: cmd='server'; worker: cmd='agent')
Args []string `yaml:"extra_args" json:"extraArgs,omitempty"`
Ports []string `yaml:"port_mappings" json:"portMappings,omitempty"` // TODO: make a struct out of this?
Restart bool `yaml:"restart" json:"restart,omitempty"`
Labels map[string]string // filled automatically
}
// Network describes a container network used by k3d clusters

Loading…
Cancel
Save