-
-
Notifications
You must be signed in to change notification settings - Fork 466
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from iwilltry42/development
Tested changes and improved error logs
- Loading branch information
Showing
6 changed files
with
332 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
package run | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"log" | ||
"os" | ||
"os/exec" | ||
"path" | ||
"strings" | ||
"time" | ||
|
||
"github.com/urfave/cli" | ||
) | ||
|
||
// CheckTools checks if the installed tools work correctly | ||
func CheckTools(c *cli.Context) error { | ||
log.Print("Checking docker...") | ||
cmd := "docker" | ||
args := []string{"version"} | ||
if err := runCommand(true, cmd, args...); err != nil { | ||
return fmt.Errorf("ERROR: checking docker failed\n%+v", err) | ||
} | ||
log.Println("SUCCESS: Checking docker succeeded") | ||
return nil | ||
} | ||
|
||
// CreateCluster creates a new single-node cluster container and initializes the cluster directory | ||
func CreateCluster(c *cli.Context) error { | ||
if c.IsSet("timeout") && !c.IsSet("wait") { | ||
return errors.New("Cannot use --timeout flag without --wait flag") | ||
} | ||
port := fmt.Sprintf("%s:%s", c.String("port"), c.String("port")) | ||
image := fmt.Sprintf("rancher/k3s:%s", c.String("version")) | ||
cmd := "docker" | ||
args := []string{ | ||
"run", | ||
"--name", c.String("name"), | ||
"-e", "K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml", | ||
"--publish", port, | ||
"--privileged", | ||
} | ||
extraArgs := []string{} | ||
if c.IsSet("volume") { | ||
extraArgs = append(extraArgs, "--volume", c.String("volume")) | ||
} | ||
if len(extraArgs) > 0 { | ||
args = append(args, extraArgs...) | ||
} | ||
args = append(args, | ||
"-d", | ||
image, | ||
"server", // cmd | ||
"--https-listen-port", c.String("port"), //args | ||
) | ||
log.Printf("Creating cluster [%s]", c.String("name")) | ||
if err := runCommand(true, cmd, args...); err != nil { | ||
return fmt.Errorf("ERROR: couldn't create cluster [%s]\n%+v", c.String("name"), err) | ||
} | ||
|
||
start := time.Now() | ||
timeout := time.Duration(c.Int("timeout")) * time.Second | ||
for c.IsSet("wait") { | ||
if timeout != 0 && !time.Now().After(start.Add(timeout)) { | ||
err := DeleteCluster(c) | ||
if err != nil { | ||
return err | ||
} | ||
return errors.New("Cluster creation exceeded specified timeout") | ||
} | ||
cmd := "docker" | ||
args = []string{ | ||
"logs", | ||
c.String("name"), | ||
} | ||
prog := exec.Command(cmd, args...) | ||
output, err := prog.CombinedOutput() | ||
if err != nil { | ||
return err | ||
} | ||
if strings.Contains(string(output), "Running kubelet") { | ||
break | ||
} | ||
|
||
time.Sleep(1 * time.Second) | ||
} | ||
|
||
createClusterDir(c.String("name")) | ||
log.Printf("SUCCESS: created cluster [%s]", c.String("name")) | ||
log.Printf(`You can now use the cluster with: | ||
export KUBECONFIG="$(%s get-kubeconfig --name='%s')" | ||
kubectl cluster-info`, os.Args[0], c.String("name")) | ||
return nil | ||
} | ||
|
||
// DeleteCluster removes the cluster container and its cluster directory | ||
func DeleteCluster(c *cli.Context) error { | ||
cmd := "docker" | ||
args := []string{"rm"} | ||
clusters := []string{} | ||
|
||
// operate on one or all clusters | ||
if !c.Bool("all") { | ||
clusters = append(clusters, c.String("name")) | ||
} else { | ||
clusterList, err := getClusterNames() | ||
if err != nil { | ||
return fmt.Errorf("ERROR: `--all` specified, but no clusters were found\n%+v", err) | ||
} | ||
clusters = append(clusters, clusterList...) | ||
} | ||
|
||
// remove clusters one by one instead of appending all names to the docker command | ||
// this allows for more granular error handling and logging | ||
for _, cluster := range clusters { | ||
log.Printf("Removing cluster [%s]", cluster) | ||
args = append(args, cluster) | ||
if err := runCommand(true, cmd, args...); err != nil { | ||
log.Printf("WARNING: couldn't delete cluster [%s], trying a force remove now.", cluster) | ||
args = args[:len(args)-1] // pop last element from list (name of cluster) | ||
args = append(args, "-f", cluster) | ||
if err := runCommand(true, cmd, args...); err != nil { | ||
log.Printf("FAILURE: couldn't delete cluster [%s] -> %+v", cluster, err) | ||
} | ||
args = args[:len(args)-1] // pop last element from list (-f flag) | ||
} | ||
deleteClusterDir(cluster) | ||
log.Printf("SUCCESS: removed cluster [%s]", cluster) | ||
args = args[:len(args)-1] // pop last element from list (name of last cluster) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// StopCluster stops a running cluster container (restartable) | ||
func StopCluster(c *cli.Context) error { | ||
cmd := "docker" | ||
args := []string{"stop"} | ||
clusters := []string{} | ||
|
||
// operate on one or all clusters | ||
if !c.Bool("all") { | ||
clusters = append(clusters, c.String("name")) | ||
} else { | ||
clusterList, err := getClusterNames() | ||
if err != nil { | ||
return fmt.Errorf("ERROR: `--all` specified, but no clusters were found\n%+v", err) | ||
} | ||
clusters = append(clusters, clusterList...) | ||
} | ||
|
||
// stop clusters one by one instead of appending all names to the docker command | ||
// this allows for more granular error handling and logging | ||
for _, cluster := range clusters { | ||
log.Printf("Stopping cluster [%s]", cluster) | ||
args = append(args, cluster) | ||
if err := runCommand(true, cmd, args...); err != nil { | ||
log.Printf("FAILURE: couldn't stop cluster [%s] -> %+v", cluster, err) | ||
} | ||
log.Printf("SUCCESS: stopped cluster [%s]", cluster) | ||
args = args[:len(args)-1] // pop last element from list (name of last cluster) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// StartCluster starts a stopped cluster container | ||
func StartCluster(c *cli.Context) error { | ||
cmd := "docker" | ||
args := []string{"start"} | ||
clusters := []string{} | ||
|
||
// operate on one or all clusters | ||
if !c.Bool("all") { | ||
clusters = append(clusters, c.String("name")) | ||
} else { | ||
clusterList, err := getClusterNames() | ||
if err != nil { | ||
return fmt.Errorf("ERROR: `--all` specified, but no clusters were found\n%+v", err) | ||
} | ||
clusters = append(clusters, clusterList...) | ||
} | ||
|
||
// start clusters one by one instead of appending all names to the docker command | ||
// this allows for more granular error handling and logging | ||
for _, cluster := range clusters { | ||
log.Printf("Starting cluster [%s]", cluster) | ||
args = append(args, cluster) | ||
if err := runCommand(true, cmd, args...); err != nil { | ||
log.Printf("FAILURE: couldn't start cluster [%s] -> %+v", cluster, err) | ||
} | ||
log.Printf("SUCCESS: started cluster [%s]", cluster) | ||
args = args[:len(args)-1] // pop last element from list (name of last cluster) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// ListClusters prints a list of created clusters | ||
func ListClusters(c *cli.Context) error { | ||
printClusters(c.Bool("all")) | ||
return nil | ||
} | ||
|
||
// GetKubeConfig grabs the kubeconfig from the running cluster and prints the path to stdout | ||
func GetKubeConfig(c *cli.Context) error { | ||
sourcePath := fmt.Sprintf("%s:/output/kubeconfig.yaml", c.String("name")) | ||
destPath, _ := getClusterDir(c.String("name")) | ||
cmd := "docker" | ||
args := []string{"cp", sourcePath, destPath} | ||
if err := runCommand(false, cmd, args...); err != nil { | ||
return fmt.Errorf("ERROR: Couldn't get kubeconfig for cluster [%s]\n%+v", c.String("name"), err) | ||
} | ||
fmt.Printf("%s\n", path.Join(destPath, "kubeconfig.yaml")) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
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() | ||
} |
Oops, something went wrong.