diff --git a/cli/cluster.go b/cli/cluster.go index b43a773b..75cbad98 100644 --- a/cli/cluster.go +++ b/cli/cluster.go @@ -1,8 +1,10 @@ package run import ( + "bytes" "context" "fmt" + "io/ioutil" "log" "os" "path" @@ -90,6 +92,62 @@ func getClusterKubeConfigPath(cluster string) (string, error) { return path.Join(clusterDir, "kubeconfig.yaml"), err } +func createKubeConfigFile(cluster string) error { + ctx := context.Background() + docker, err := client.NewEnvClient() + if err != nil { + return err + } + + filters := filters.NewArgs() + filters.Add("label", "app=k3d") + filters.Add("label", fmt.Sprintf("cluster=%s", cluster)) + filters.Add("label", "component=server") + server, err := docker.ContainerList(ctx, types.ContainerListOptions{ + Filters: filters, + }) + + if err != nil { + return fmt.Errorf("Failed to get server container for cluster %s\n%+v", cluster, err) + } + + if len(server) == 0 { + return fmt.Errorf("No server container for cluster %s", cluster) + } + + // get kubeconfig file from container and read contents + reader, _, err := docker.CopyFromContainer(ctx, server[0].ID, "/output/kubeconfig.yaml") + if err != nil { + return fmt.Errorf("ERROR: couldn't copy kubeconfig.yaml from server container %s\n%+v", server[0].ID, err) + } + defer reader.Close() + + readBytes, err := ioutil.ReadAll(reader) + if err != nil { + return fmt.Errorf("ERROR: couldn't read kubeconfig from container\n%+v", err) + } + + // create destination kubeconfig file + destPath, err := getClusterKubeConfigPath(cluster) + if err != nil { + return err + } + + kubeconfigfile, err := os.Create(destPath) + if err != nil { + return fmt.Errorf("ERROR: couldn't create kubeconfig file %s\n%+v", destPath, err) + } + defer kubeconfigfile.Close() + + // write to file, skipping the first 512 bytes which contain file metadata and trimming any NULL characters + _, err = kubeconfigfile.Write(bytes.Trim(readBytes[512:], "\x00")) + if err != nil { + return fmt.Errorf("ERROR: couldn't write to kubeconfig.yaml\n%+v", err) + } + + return nil +} + // printClusters prints the names of existing clusters func printClusters() { clusters, err := getClusters(true, "") diff --git a/cli/commands.go b/cli/commands.go index 6b492fb2..e8f85ebb 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -9,15 +9,12 @@ import ( "context" "errors" "fmt" - "io/ioutil" "log" "os" "strconv" "strings" "time" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/urfave/cli" @@ -346,60 +343,29 @@ func ListClusters(c *cli.Context) error { // GetKubeConfig grabs the kubeconfig from the running cluster and prints the path to stdout func GetKubeConfig(c *cli.Context) error { - ctx := context.Background() - docker, err := client.NewEnvClient() - if err != nil { - return err - } - - filters := filters.NewArgs() - filters.Add("label", "app=k3d") - filters.Add("label", fmt.Sprintf("cluster=%s", c.String("name"))) - filters.Add("label", "component=server") - server, err := docker.ContainerList(ctx, types.ContainerListOptions{ - Filters: filters, - }) - - if err != nil { - return fmt.Errorf("Failed to get server container for cluster %s\n%+v", c.String("name"), err) - } - - if len(server) == 0 { - return fmt.Errorf("No server container for cluster %s", c.String("name")) - } - - // get kubeconfig file from container and read contents - reader, _, err := docker.CopyFromContainer(ctx, server[0].ID, "/output/kubeconfig.yaml") - if err != nil { - return fmt.Errorf("ERROR: couldn't copy kubeconfig.yaml from server container %s\n%+v", server[0].ID, err) - } - defer reader.Close() - - readBytes, err := ioutil.ReadAll(reader) - if err != nil { - return fmt.Errorf("ERROR: couldn't read kubeconfig from container\n%+v", err) - } - - // create destination kubeconfig file + cluster := c.String("name") destPath, err := getClusterKubeConfigPath(c.String("name")) if err != nil { return err } - kubeconfigfile, err := os.Create(destPath) - if err != nil { - return fmt.Errorf("ERROR: couldn't create kubeconfig file %s\n%+v", destPath, err) + if clusters, err := getClusters(false, cluster); err != nil || len(clusters) != 1 { + if err != nil { + return err + } + return fmt.Errorf("Cluster %s does not exist", cluster) } - defer kubeconfigfile.Close() - // write to file, skipping the first 512 bytes which contain file metadata and trimming any NULL characters - _, err = kubeconfigfile.Write(bytes.Trim(readBytes[512:], "\x00")) - if err != nil { - return fmt.Errorf("ERROR: couldn't write to kubeconfig.yaml\n%+v", err) + // If kubeconfig.yaml has not been created, generate it now. + if _, err := os.Stat(destPath); os.IsNotExist(err) { + if err = createKubeConfigFile(cluster); err != nil { + return err + } + } else { + return err } // output kubeconfig file path to stdout fmt.Println(destPath) - return nil }