diff --git a/README.md b/README.md index b027ae47..4bd81595 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This repository is based on [@zeerorg](https://github.com/zeerorg/)'s [zeerorg/k - [docker](https://docs.docker.com/install/) -## Install +## Get You have several options there: @@ -21,7 +21,7 @@ You have several options there: - wget: `wget -q -O - https://raw.githubusercontent.com/rancher/k3d/master/install.sh | bash` - curl: `curl -s https://raw.githubusercontent.com/rancher/k3d/master/install.sh | bash` - Grab a release from the [release tab](https://github.com/rancher/k3d/releases) and install it yourself. -- Via go: `go install github.com/rancher/k3d` +- Via go: `go install github.com/rancher/k3d` (**Note**: this will give you unreleased/bleeding-edge changes) or... @@ -32,7 +32,7 @@ or... - 'make install-tools' to make sure required go packages are installed 3. Inside the repo run - `make build` to build for your current system - - `go install` to install it to your `GOPATH` + - `go install` to install it to your `GOPATH` (**Note**: this will give you unreleased/bleeding-edge changes) - `make build-cross` to build for all systems ## Usage diff --git a/cli/commands.go b/cli/commands.go index 1ffa7769..956c26d1 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -23,6 +23,8 @@ import ( "github.com/urfave/cli" ) +const defaultRegistry = "docker.io" + // CheckTools checks if the docker API server is responding func CheckTools(c *cli.Context) error { log.Print("Checking docker...") @@ -43,6 +45,28 @@ func CheckTools(c *cli.Context) error { // CreateCluster creates a new single-node cluster container and initializes the cluster directory func CreateCluster(c *cli.Context) error { + if err := CheckClusterName(c.String("name")); err != nil { + return err + } + + // define image + image := c.String("image") + if c.IsSet("version") { + // TODO: --version to be deprecated + log.Println("[WARNING] The `--version` flag will be deprecated soon, please use `--image rancher/k3s:` instead") + if c.IsSet("image") { + // version specified, custom image = error (to push deprecation of version flag) + log.Fatalln("[ERROR] Please use `--image :` instead of --image and --version") + } else { + // version specified, default image = ok (until deprecation of version flag) + image = fmt.Sprintf("%s:%s", strings.Split(image, ":")[0], c.String("version")) + } + } + if len(strings.Split(image, "/")) <= 2 { + // fallback to default registry + image = fmt.Sprintf("%s/%s", defaultRegistry, image) + } + // create cluster network networkID, err := createClusterNetwork(c.String("name")) if err != nil { @@ -81,7 +105,7 @@ func CreateCluster(c *cli.Context) error { log.Printf("Creating cluster [%s]", c.String("name")) dockerID, err := createServer( c.GlobalBool("verbose"), - fmt.Sprintf("docker.io/rancher/k3s:%s", c.String("version")), + image, c.String("port"), k3sServerArgs, env, @@ -144,7 +168,7 @@ func CreateCluster(c *cli.Context) error { for i := 0; i < c.Int("workers"); i++ { workerID, err := createWorker( c.GlobalBool("verbose"), - fmt.Sprintf("docker.io/rancher/k3s:%s", c.String("version")), + image, k3sWorkerArgs, env, c.String("name"), diff --git a/cli/util.go b/cli/util.go index 66d0ba2b..1688c57b 100644 --- a/cli/util.go +++ b/cli/util.go @@ -1,6 +1,7 @@ package run import ( + "fmt" "math/rand" "strings" "time" @@ -36,3 +37,35 @@ func GenerateRandomString(n int) string { return sb.String() } + +/*** Cluster Name Validation ***/ +const clusterNameMaxSize int = 35 + +// CheckClusterName ensures that a cluster name is also a valid host name according to RFC 1123. +// We further restrict the length of the cluster name to maximum 'clusterNameMaxSize' +// so that we can construct the host names based on the cluster name, and still stay +// within the 64 characters limit. +func CheckClusterName(name string) error { + if len(name) > clusterNameMaxSize { + return fmt.Errorf("[ERROR] Cluster name is too long") + } + + if name[0] == '-' || name[len(name)-1] == '-' { + return fmt.Errorf("[ERROR] Cluster name can not start or end with - (dash)") + } + + for _, c := range name { + switch { + case '0' <= c && c <= '9': + case 'a' <= c && c <= 'z': + case 'A' <= c && c <= 'Z': + case c == '-': + break + default: + return fmt.Errorf("[ERROR] Cluster name contains characters other than 'Aa-Zz', '0-9' or '-'") + + } + } + + return nil +} diff --git a/main.go b/main.go index aa3e40a9..94d70519 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "os" @@ -9,6 +10,10 @@ import ( "github.com/urfave/cli" ) +// defaultK3sImage specifies the default image being used for server and workers +const defaultK3sImage = "docker.io/rancher/k3s" +const defaultK3sClusterName string = "k3s-default" + // main represents the CLI application func main() { @@ -48,7 +53,7 @@ func main() { Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", - Value: "k3s_default", + Value: defaultK3sClusterName, Usage: "Set a name for the cluster", }, cli.StringFlag{ @@ -60,8 +65,8 @@ func main() { Usage: "publish k3s node ports to the host (Docker notation: `ip:public:private/proto`, use multiple options to expose more ports)", }, cli.StringFlag{ + // TODO: to be deprecated Name: "version", - Value: version.GetK3sVersion(), Usage: "Choose the k3s image version", }, cli.IntFlag{ @@ -78,6 +83,11 @@ func main() { Name: "wait, w", Usage: "Wait for the cluster to come up before returning", }, + cli.StringFlag{ + Name: "image, i", + Usage: "Specify a k3s image (Format: /:)", + Value: fmt.Sprintf("%s:%s", defaultK3sImage, version.GetK3sVersion()), + }, cli.StringSliceFlag{ Name: "server-arg, x", Usage: "Pass an additional argument to k3s server (new flag per argument)", @@ -102,7 +112,7 @@ func main() { Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", - Value: "k3s_default", + Value: defaultK3sClusterName, Usage: "name of the cluster", }, cli.BoolFlag{ @@ -119,7 +129,7 @@ func main() { Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", - Value: "k3s_default", + Value: defaultK3sClusterName, Usage: "Name of the cluster", }, cli.BoolFlag{ @@ -136,7 +146,7 @@ func main() { Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", - Value: "k3s_default", + Value: defaultK3sClusterName, Usage: "Name of the cluster", }, cli.BoolFlag{ @@ -166,7 +176,7 @@ func main() { Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", - Value: "k3s_default", + Value: defaultK3sClusterName, Usage: "Name of the cluster", }, cli.BoolFlag{