remove old subcommands

pull/300/head
iwilltry42 4 years ago
parent 9c65d7bac6
commit 594ead1428
No known key found for this signature in database
GPG Key ID: 7BA57AD1CFF16110
  1. 53
      cmd/create/create.go
  2. 408
      cmd/create/createCluster.go
  3. 133
      cmd/create/createNode.go
  4. 52
      cmd/delete/delete.go
  5. 105
      cmd/delete/deleteCluster.go
  6. 97
      cmd/delete/deleteNode.go
  7. 53
      cmd/get/get.go
  8. 128
      cmd/get/getCluster.go
  9. 116
      cmd/get/getKubeconfig.go
  10. 123
      cmd/get/getNode.go
  11. 52
      cmd/load/load.go
  12. 97
      cmd/load/loadImage.go
  13. 25
      cmd/root.go
  14. 52
      cmd/start/start.go
  15. 102
      cmd/start/startCluster.go
  16. 62
      cmd/start/startNode.go
  17. 52
      cmd/stop/stop.go
  18. 95
      cmd/stop/stopCluster.go
  19. 63
      cmd/stop/stopNode.go

@ -1,53 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package create
import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdCreate returns a new cobra command
func NewCmdCreate() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "create",
Short: "Create a resource [cluster, node].",
Long: `Create a resource [cluster, node].`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Errorln("Couldn't get help text")
log.Fatalln(err)
}
},
}
// add subcommands
cmd.AddCommand(NewCmdCreateCluster())
cmd.AddCommand(NewCmdCreateNode())
// add flags
// done
return cmd
}

@ -1,408 +0,0 @@
/*Package create ...
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package create
import (
"fmt"
"os"
"runtime"
"time"
"github.com/spf13/cobra"
cliutil "github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
k3dCluster "github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/rancher/k3d/v3/version"
log "github.com/sirupsen/logrus"
)
const createClusterDescription = `
Create a new k3s cluster with containerized nodes (k3s in docker).
Every cluster will consist of at least 2 containers:
- 1 master node container (k3s)
- 1 loadbalancer container as the entrypoint to the cluster (nginx)
`
// NewCmdCreateCluster returns a new cobra command
func NewCmdCreateCluster() *cobra.Command {
createClusterOpts := &k3d.CreateClusterOpts{}
var updateKubeconfig, updateCurrentContext bool
// create new command
cmd := &cobra.Command{
Use: "cluster NAME",
Short: "Create a new k3s cluster in docker",
Long: createClusterDescription,
Args: cobra.RangeArgs(0, 1), // exactly one cluster name can be set (default: k3d.DefaultClusterName)
Run: func(cmd *cobra.Command, args []string) {
// parse args and flags
cluster := parseCreateClusterCmd(cmd, args, createClusterOpts)
// check if a cluster with that name exists already
if _, err := k3dCluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, cluster); err == nil {
log.Fatalf("Failed to create cluster '%s' because a cluster with that name already exists", cluster.Name)
}
// create cluster
if updateKubeconfig || updateCurrentContext {
log.Debugln("'--update-kubeconfig set: enabling wait-for-master")
cluster.CreateClusterOpts.WaitForMaster = true
}
if err := k3dCluster.CreateCluster(cmd.Context(), runtimes.SelectedRuntime, cluster); err != nil {
// rollback if creation failed
log.Errorln(err)
log.Errorln("Failed to create cluster >>> Rolling Back")
if err := k3dCluster.DeleteCluster(cmd.Context(), runtimes.SelectedRuntime, cluster); err != nil {
log.Errorln(err)
log.Fatalln("Cluster creation FAILED, also FAILED to rollback changes!")
}
log.Fatalln("Cluster creation FAILED, all changes have been rolled back!")
}
log.Infof("Cluster '%s' created successfully!", cluster.Name)
if updateKubeconfig || updateCurrentContext {
log.Debugf("Updating default kubeconfig with a new context for cluster %s", cluster.Name)
if _, err := k3dCluster.GetAndWriteKubeConfig(cmd.Context(), runtimes.SelectedRuntime, cluster, "", &k3dCluster.WriteKubeConfigOptions{UpdateExisting: true, OverwriteExisting: false, UpdateCurrentContext: updateCurrentContext}); err != nil {
log.Fatalln(err)
}
}
// print information on how to use the cluster with kubectl
log.Infoln("You can now use it like this:")
if updateKubeconfig && !updateCurrentContext {
fmt.Printf("kubectl config use-context %s\n", fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, cluster.Name))
} else if !updateCurrentContext {
if runtime.GOOS == "windows" {
fmt.Printf("$env:KUBECONFIG=(%s get kubeconfig %s)\n", os.Args[0], cluster.Name)
} else {
fmt.Printf("export KUBECONFIG=$(%s get kubeconfig %s)\n", os.Args[0], cluster.Name)
}
}
fmt.Println("kubectl cluster-info")
},
}
/*********
* Flags *
*********/
cmd.Flags().StringP("api-port", "a", "random", "Specify the Kubernetes API server port exposed on the LoadBalancer (Format: `--api-port [HOST:]HOSTPORT`)\n - Example: `k3d create -m 3 -a 0.0.0.0:6550`")
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().StringP("image", "i", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)), "Specify k3s image that you want to use for the nodes")
cmd.Flags().String("network", "", "Join an existing network")
cmd.Flags().String("token", "", "Specify a cluster token. By default, we generate one.")
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `--volume [SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d create -w 2 -v /my/path@worker[0,1] -v /tmp/test:/tmp/other@master[0]`")
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d create -w 2 -p 8080:80@worker[0] -p 8081@worker[1]`")
cmd.Flags().BoolVar(&createClusterOpts.WaitForMaster, "wait", true, "Wait for the master(s) to be ready before returning. Use '--timeout DURATION' to not wait forever.")
cmd.Flags().DurationVar(&createClusterOpts.Timeout, "timeout", 0*time.Second, "Rollback changes if cluster couldn't be created in specified duration.")
cmd.Flags().BoolVar(&updateKubeconfig, "update-kubeconfig", false, "Directly update the default kubeconfig with the new cluster's context")
cmd.Flags().BoolVar(&updateCurrentContext, "switch", false, "Directly switch the default kubeconfig's current-context to the new cluster's context (implies --update-kubeconfig)")
cmd.Flags().BoolVar(&createClusterOpts.DisableLoadBalancer, "no-lb", false, "Disable the creation of a LoadBalancer in front of the master nodes")
/* Image Importing */
cmd.Flags().BoolVar(&createClusterOpts.DisableImageVolume, "no-image-volume", false, "Disable the creation of a volume for importing images")
/* Multi Master Configuration */
// multi-master - datastore
// TODO: implement multi-master setups with external data store
// cmd.Flags().String("datastore-endpoint", "", "[WIP] Specify external datastore endpoint (e.g. for multi master clusters)")
/*
cmd.Flags().String("datastore-network", "", "Specify container network where we can find the datastore-endpoint (add a connection)")
// TODO: set default paths and hint, that one should simply mount the files using --volume flag
cmd.Flags().String("datastore-cafile", "", "Specify external datastore's TLS Certificate Authority (CA) file")
cmd.Flags().String("datastore-certfile", "", "Specify external datastore's TLS certificate file'")
cmd.Flags().String("datastore-keyfile", "", "Specify external datastore's TLS key file'")
*/
/* k3s */
cmd.Flags().StringArrayVar(&createClusterOpts.K3sServerArgs, "k3s-server-arg", nil, "Additional args passed to the `k3s server` command on master nodes (new flag per arg)")
cmd.Flags().StringArrayVar(&createClusterOpts.K3sAgentArgs, "k3s-agent-arg", nil, "Additional args passed to the `k3s agent` command on worker nodes (new flag per arg)")
/* Subcommands */
// done
return cmd
}
// parseCreateClusterCmd parses the command input into variables required to create a cluster
func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts *k3d.CreateClusterOpts) *k3d.Cluster {
/********************************
* Parse and validate arguments *
********************************/
clustername := k3d.DefaultClusterName
if len(args) != 0 {
clustername = args[0]
}
if err := cluster.CheckName(clustername); err != nil {
log.Fatal(err)
}
/****************************
* Parse and validate flags *
****************************/
// --image
image, err := cmd.Flags().GetString("image")
if err != nil {
log.Errorln("No image specified")
log.Fatalln(err)
}
if image == "latest" {
image = version.GetK3sVersion(true)
}
// --masters
masterCount, err := cmd.Flags().GetInt("masters")
if err != nil {
log.Fatalln(err)
}
// --workers
workerCount, err := cmd.Flags().GetInt("workers")
if err != nil {
log.Fatalln(err)
}
// --network
networkName, err := cmd.Flags().GetString("network")
if err != nil {
log.Fatalln(err)
}
network := k3d.ClusterNetwork{}
if networkName != "" {
network.Name = networkName
network.External = true
}
if networkName == "host" && (masterCount+workerCount) > 1 {
log.Fatalln("Can only run a single node in hostnetwork mode")
}
// --token
token, err := cmd.Flags().GetString("token")
if err != nil {
log.Fatalln(err)
}
// --timeout
if cmd.Flags().Changed("timeout") && createClusterOpts.Timeout <= 0*time.Second {
log.Fatalln("--timeout DURATION must be >= 1s")
}
// --api-port
apiPort, err := cmd.Flags().GetString("api-port")
if err != nil {
log.Fatalln(err)
}
// parse the port mapping
exposeAPI, err := cliutil.ParseAPIPort(apiPort)
if err != nil {
log.Fatalln(err)
}
if exposeAPI.Host == "" {
exposeAPI.Host = k3d.DefaultAPIHost
}
if exposeAPI.HostIP == "" {
exposeAPI.HostIP = k3d.DefaultAPIHost
}
if networkName == "host" {
// in hostNetwork mode, we're not going to map a hostport. Here it should always use 6443.
// Note that hostNetwork mode is super inflexible and since we don't change the backend port (on the container), it will only be one hostmode cluster allowed.
exposeAPI.Port = k3d.DefaultAPIPort
}
// --volume
volumeFlags, err := cmd.Flags().GetStringArray("volume")
if err != nil {
log.Fatalln(err)
}
// volumeFilterMap will map volume mounts to applied node filters
volumeFilterMap := make(map[string][]string, 1)
for _, volumeFlag := range volumeFlags {
// split node filter from the specified volume
volume, filters, err := cliutil.SplitFiltersFromFlag(volumeFlag)
if err != nil {
log.Fatalln(err)
}
// validate the specified volume mount and return it in SRC:DEST format
volume, err = cliutil.ValidateVolumeMount(runtimes.SelectedRuntime, volume)
if err != nil {
log.Fatalln(err)
}
// create new entry or append filter to existing entry
if _, exists := volumeFilterMap[volume]; exists {
volumeFilterMap[volume] = append(volumeFilterMap[volume], filters...)
} else {
volumeFilterMap[volume] = filters
}
}
// --port
portFlags, err := cmd.Flags().GetStringArray("port")
if err != nil {
log.Fatalln(err)
}
portFilterMap := make(map[string][]string, 1)
for _, portFlag := range portFlags {
// split node filter from the specified volume
portmap, filters, err := cliutil.SplitFiltersFromFlag(portFlag)
if err != nil {
log.Fatalln(err)
}
if len(filters) > 1 {
log.Fatalln("Can only apply a Portmap to one node")
}
// the same portmapping can't be applied to multiple nodes
// validate the specified volume mount and return it in SRC:DEST format
portmap, err = cliutil.ValidatePortMap(portmap)
if err != nil {
log.Fatalln(err)
}
// create new entry or append filter to existing entry
if _, exists := portFilterMap[portmap]; exists {
log.Fatalln("Same Portmapping can not be used for multiple nodes")
} else {
portFilterMap[portmap] = filters
}
}
log.Debugf("PortFilterMap: %+v", portFilterMap)
/********************
* *
* generate cluster *
* *
********************/
cluster := &k3d.Cluster{
Name: clustername,
Network: network,
Token: token,
CreateClusterOpts: createClusterOpts,
ExposeAPI: exposeAPI,
}
// generate list of nodes
cluster.Nodes = []*k3d.Node{}
// MasterLoadBalancer
if !createClusterOpts.DisableLoadBalancer {
cluster.MasterLoadBalancer = &k3d.Node{
Role: k3d.LoadBalancerRole,
}
}
/****************
* Master Nodes *
****************/
for i := 0; i < masterCount; i++ {
node := k3d.Node{
Role: k3d.MasterRole,
Image: image,
Args: createClusterOpts.K3sServerArgs,
MasterOpts: k3d.MasterOpts{},
}
// TODO: by default, we don't expose an API port: should we change that?
// -> if we want to change that, simply add the exposeAPI struct here
// first master node will be init node if we have more than one master specified but no external datastore
if i == 0 && masterCount > 1 {
node.MasterOpts.IsInit = true
cluster.InitNode = &node
}
// append node to list
cluster.Nodes = append(cluster.Nodes, &node)
}
/****************
* Worker Nodes *
****************/
for i := 0; i < workerCount; i++ {
node := k3d.Node{
Role: k3d.WorkerRole,
Image: image,
Args: createClusterOpts.K3sAgentArgs,
}
cluster.Nodes = append(cluster.Nodes, &node)
}
// append volumes
for volume, filters := range volumeFilterMap {
nodes, err := cliutil.FilterNodes(cluster.Nodes, filters)
if err != nil {
log.Fatalln(err)
}
for _, node := range nodes {
node.Volumes = append(node.Volumes, volume)
}
}
// append ports
nodeCount := masterCount + workerCount
nodeList := cluster.Nodes
if !createClusterOpts.DisableLoadBalancer {
nodeCount++
nodeList = append(nodeList, cluster.MasterLoadBalancer)
}
for portmap, filters := range portFilterMap {
if len(filters) == 0 && (nodeCount) > 1 {
log.Fatalf("Malformed portmapping '%s' lacks a node filter, but there is more than one node (including the loadbalancer, if there is any).", portmap)
}
nodes, err := cliutil.FilterNodes(nodeList, filters)
if err != nil {
log.Fatalln(err)
}
for _, node := range nodes {
node.Ports = append(node.Ports, portmap)
}
}
/**********************
* Utility Containers *
**********************/
// ...
return cluster
}

@ -1,133 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package create
import (
"fmt"
"time"
"github.com/spf13/cobra"
"github.com/rancher/k3d/v3/cmd/util"
k3dc "github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/rancher/k3d/v3/version"
log "github.com/sirupsen/logrus"
)
// NewCmdCreateNode returns a new cobra command
func NewCmdCreateNode() *cobra.Command {
createNodeOpts := k3d.CreateNodeOpts{}
// create new command
cmd := &cobra.Command{
Use: "node NAME",
Short: "Create a new k3s node in docker",
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) {
nodes, cluster := parseCreateNodeCmd(cmd, args)
if err := k3dc.AddNodesToCluster(cmd.Context(), runtimes.SelectedRuntime, nodes, cluster, createNodeOpts); err != nil {
log.Errorf("Failed to add nodes to cluster '%s'", cluster.Name)
log.Errorln(err)
}
},
}
// add flags
cmd.Flags().Int("replicas", 1, "Number of replicas of this node specification.")
cmd.Flags().String("role", string(k3d.WorkerRole), "Specify node role [master, worker]")
if err := cmd.RegisterFlagCompletionFunc("role", util.ValidArgsNodeRoles); err != nil {
log.Fatalln("Failed to register flag completion for '--role'", err)
}
cmd.Flags().StringP("cluster", "c", k3d.DefaultClusterName, "Select the cluster that the node shall connect to.")
if err := cmd.MarkFlagRequired("cluster"); err != nil {
log.Fatalln("Failed to mark required flag '--cluster'")
}
if err := cmd.RegisterFlagCompletionFunc("cluster", util.ValidArgsAvailableClusters); err != nil {
log.Fatalln("Failed to register flag completion for '--cluster'", err)
}
cmd.Flags().StringP("image", "i", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)), "Specify k3s image used for the node(s)")
cmd.Flags().BoolVar(&createNodeOpts.Wait, "wait", false, "Wait for the node(s) to be ready before returning.")
cmd.Flags().DurationVar(&createNodeOpts.Timeout, "timeout", 0*time.Second, "Maximum waiting time for '--wait' before canceling/returning.")
// done
return cmd
}
// parseCreateNodeCmd parses the command input into variables required to create a cluster
func parseCreateNodeCmd(cmd *cobra.Command, args []string) ([]*k3d.Node, *k3d.Cluster) {
// --replicas
replicas, err := cmd.Flags().GetInt("replicas")
if err != nil {
log.Errorln("No replica count specified")
log.Fatalln(err)
}
// --role
roleStr, err := cmd.Flags().GetString("role")
if err != nil {
log.Errorln("No node role specified")
log.Fatalln(err)
}
if _, ok := k3d.NodeRoles[roleStr]; !ok {
log.Fatalf("Unknown node role '%s'\n", roleStr)
}
role := k3d.NodeRoles[roleStr]
// --image
image, err := cmd.Flags().GetString("image")
if err != nil {
log.Errorln("No image specified")
log.Fatalln(err)
}
// --cluster
clusterName, err := cmd.Flags().GetString("cluster")
if err != nil {
log.Fatalln(err)
}
cluster := &k3d.Cluster{
Name: clusterName,
}
// generate list of nodes
nodes := []*k3d.Node{}
for i := 0; i < replicas; i++ {
node := &k3d.Node{
Name: fmt.Sprintf("%s-%s-%d", k3d.DefaultObjectNamePrefix, args[0], i),
Role: role,
Image: image,
Labels: map[string]string{
k3d.LabelRole: roleStr,
},
}
nodes = append(nodes, node)
}
return nodes, cluster
}

@ -1,52 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package delete
import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdDelete returns a new cobra command
func NewCmdDelete() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "delete",
Short: "Delete a resource [cluster, node].",
Long: `Delete a resource [cluster, node].`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Errorln("Couldn't get help text")
log.Fatalln(err)
}
},
}
// add subcommands
cmd.AddCommand(NewCmdDeleteCluster())
cmd.AddCommand(NewCmdDeleteNode())
// done
return cmd
}

@ -1,105 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package delete
import (
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdDeleteCluster returns a new cobra command
func NewCmdDeleteCluster() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "cluster (NAME | --all)",
Short: "Delete a cluster.",
Long: `Delete a cluster.`,
Args: cobra.MinimumNArgs(0), // 0 or n arguments; 0 only if --all is set
ValidArgsFunction: util.ValidArgsAvailableClusters,
Run: func(cmd *cobra.Command, args []string) {
clusters := parseDeleteClusterCmd(cmd, args)
if len(clusters) == 0 {
log.Infoln("No clusters found")
} else {
for _, c := range clusters {
if err := cluster.DeleteCluster(cmd.Context(), runtimes.SelectedRuntime, c); err != nil {
log.Fatalln(err)
}
log.Infoln("Removing cluster details from default kubeconfig")
if err := cluster.RemoveClusterFromDefaultKubeConfig(cmd.Context(), c); err != nil {
log.Warnln("Failed to remove cluster details from default kubeconfig")
log.Warnln(err)
}
log.Infof("Successfully deleted cluster %s!", c.Name)
}
}
},
}
// add subcommands
// add flags
cmd.Flags().BoolP("all", "a", false, "Delete all existing clusters")
// done
return cmd
}
// parseDeleteClusterCmd parses the command input into variables required to delete clusters
func parseDeleteClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
// --all
var clusters []*k3d.Cluster
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
return clusters
}
if len(args) < 1 {
log.Fatalln("Expecting at least one cluster name if `--all` is not set")
}
for _, name := range args {
cluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
if err != nil {
log.Fatalln(err)
}
clusters = append(clusters, cluster)
}
return clusters
}

@ -1,97 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package delete
import (
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdDeleteNode returns a new cobra command
func NewCmdDeleteNode() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "node (NAME | --all)",
Short: "Delete a node.",
Long: `Delete a node.`,
Args: cobra.MinimumNArgs(1), // at least one node has to be specified
ValidArgsFunction: util.ValidArgsAvailableNodes,
Run: func(cmd *cobra.Command, args []string) {
nodes := parseDeleteNodeCmd(cmd, args)
if len(nodes) == 0 {
log.Infoln("No nodes found")
} else {
for _, node := range nodes {
if err := cluster.DeleteNode(cmd.Context(), runtimes.SelectedRuntime, node); err != nil {
log.Fatalln(err)
}
}
}
},
}
// add subcommands
// add flags
cmd.Flags().BoolP("all", "a", false, "Delete all existing clusters")
// done
return cmd
}
// parseDeleteNodeCmd parses the command input into variables required to delete nodes
func parseDeleteNodeCmd(cmd *cobra.Command, args []string) []*k3d.Node {
// --all
var nodes []*k3d.Node
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
nodes, err = cluster.GetNodes(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
return nodes
}
if len(args) < 1 {
log.Fatalln("Expecting at least one node name if `--all` is not set")
}
for _, name := range args {
node, err := cluster.GetNode(cmd.Context(), runtimes.SelectedRuntime, &k3d.Node{Name: name})
if err != nil {
log.Fatalln(err)
}
nodes = append(nodes, node)
}
return nodes
}

@ -1,53 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package get
import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdGet returns a new cobra command
func NewCmdGet() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "get",
Short: "Get a resource [cluster, node, kubeconfig].",
Long: `Get a resource [cluster, node, kubeconfig].`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Errorln("Couldn't get help text")
log.Fatalln(err)
}
},
}
// add subcommands
cmd.AddCommand(NewCmdGetCluster())
cmd.AddCommand(NewCmdGetNode())
cmd.AddCommand(NewCmdGetKubeconfig())
// done
return cmd
}

@ -1,128 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package get
import (
"context"
"fmt"
"os"
"strings"
"github.com/rancher/k3d/v3/cmd/util"
k3cluster "github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/spf13/cobra"
log "github.com/sirupsen/logrus"
"github.com/liggitt/tabwriter"
)
// TODO : deal with --all flag to manage differentiate started cluster and stopped cluster like `docker ps` and `docker ps -a`
type clusterFlags struct {
noHeader bool
token bool
}
// NewCmdGetCluster returns a new cobra command
func NewCmdGetCluster() *cobra.Command {
clusterFlags := clusterFlags{}
// create new command
cmd := &cobra.Command{
Use: "cluster [NAME [NAME...]]",
Aliases: []string{"clusters"},
Short: "Get cluster(s)",
Long: `Get cluster(s).`,
Run: func(cmd *cobra.Command, args []string) {
clusters := buildClusterList(cmd.Context(), args)
PrintClusters(clusters, clusterFlags)
},
ValidArgsFunction: util.ValidArgsAvailableClusters,
}
// add flags
cmd.Flags().BoolVar(&clusterFlags.noHeader, "no-headers", false, "Disable headers")
cmd.Flags().BoolVar(&clusterFlags.token, "token", false, "Print k3s cluster token")
// add subcommands
// done
return cmd
}
func buildClusterList(ctx context.Context, args []string) []*k3d.Cluster {
var clusters []*k3d.Cluster
var err error
if len(args) == 0 {
// cluster name not specified : get all clusters
clusters, err = k3cluster.GetClusters(ctx, runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
} else {
for _, clusterName := range args {
// cluster name specified : get specific cluster
retrievedCluster, err := k3cluster.GetCluster(ctx, runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName})
if err != nil {
log.Fatalln(err)
}
clusters = append(clusters, retrievedCluster)
}
}
return clusters
}
// PrintPrintClusters : display list of cluster
func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) {
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths)
defer tabwriter.Flush()
if !flags.noHeader {
headers := []string{"NAME", "MASTERS", "WORKERS"} // TODO: getCluster: add status column
if flags.token {
headers = append(headers, "TOKEN")
}
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t"))
if err != nil {
log.Fatalln("Failed to print headers")
}
}
k3cluster.SortClusters(clusters)
for _, cluster := range clusters {
masterCount := cluster.MasterCount()
workerCount := cluster.WorkerCount()
if flags.token {
fmt.Fprintf(tabwriter, "%s\t%d\t%d\t%s\n", cluster.Name, masterCount, workerCount, cluster.Token)
} else {
fmt.Fprintf(tabwriter, "%s\t%d\t%d\n", cluster.Name, masterCount, workerCount)
}
}
}

@ -1,116 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package get
import (
"fmt"
"os"
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
log "github.com/sirupsen/logrus"
)
type getKubeconfigFlags struct {
all bool
output string
}
// NewCmdGetKubeconfig returns a new cobra command
func NewCmdGetKubeconfig() *cobra.Command {
writeKubeConfigOptions := cluster.WriteKubeConfigOptions{}
getKubeconfigFlags := getKubeconfigFlags{}
// create new command
cmd := &cobra.Command{
Use: "kubeconfig [CLUSTER [CLUSTER [...]] | --all]", // TODO: getKubeconfig: allow more than one cluster name or even --all
Short: "Get kubeconfig",
Long: `Get kubeconfig.`,
ValidArgsFunction: util.ValidArgsAvailableClusters,
Args: func(cmd *cobra.Command, args []string) error {
if (len(args) < 1 && !getKubeconfigFlags.all) || (len(args) > 0 && getKubeconfigFlags.all) {
return fmt.Errorf("Need to specify one or more cluster names *or* set `--all` flag")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
var clusters []*k3d.Cluster
var err error
// generate list of clusters
if getKubeconfigFlags.all {
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
} else {
for _, clusterName := range args {
retrievedCluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName})
if err != nil {
log.Fatalln(err)
}
clusters = append(clusters, retrievedCluster)
}
}
// get kubeconfigs from all clusters
errorGettingKubeconfig := false
for _, c := range clusters {
log.Debugf("Getting kubeconfig for cluster '%s'", c.Name)
if getKubeconfigFlags.output, err = cluster.GetAndWriteKubeConfig(cmd.Context(), runtimes.SelectedRuntime, c, getKubeconfigFlags.output, &writeKubeConfigOptions); err != nil {
log.Errorln(err)
errorGettingKubeconfig = true
}
}
// only print kubeconfig file path if output is not stdout ("-")
if getKubeconfigFlags.output != "-" {
fmt.Println(getKubeconfigFlags.output)
}
// return with non-zero exit code, if there was an error for one of the clusters
if errorGettingKubeconfig {
os.Exit(1)
}
},
}
// add flags
cmd.Flags().StringVarP(&getKubeconfigFlags.output, "output", "o", "", fmt.Sprintf("Define output [ - | FILE ] (default from $KUBECONFIG or %s", clientcmd.RecommendedHomeFile))
if err := cmd.MarkFlagFilename("output"); err != nil {
log.Fatalln("Failed to mark flag --output as filename")
}
cmd.Flags().BoolVarP(&writeKubeConfigOptions.UpdateExisting, "update", "u", true, "Update conflicting fields in existing KubeConfig")
cmd.Flags().BoolVarP(&writeKubeConfigOptions.UpdateCurrentContext, "switch", "s", false, "Switch to new context")
cmd.Flags().BoolVar(&writeKubeConfigOptions.OverwriteExisting, "overwrite", false, "[Careful!] Overwrite existing file, ignoring its contents")
cmd.Flags().BoolVarP(&getKubeconfigFlags.all, "all", "a", false, "Get kubeconfigs from all existing clusters")
// done
return cmd
}

@ -1,123 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package get
import (
"fmt"
"os"
"sort"
"strings"
"github.com/liggitt/tabwriter"
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/spf13/cobra"
log "github.com/sirupsen/logrus"
)
// NewCmdGetNode returns a new cobra command
func NewCmdGetNode() *cobra.Command {
// create new command
cmd := &cobra.Command{
Use: "node [NAME [NAME...]]",
Aliases: []string{"nodes"},
Short: "Get node(s)",
Long: `Get node(s).`,
Args: cobra.MinimumNArgs(0), // 0 or more; 0 = all
ValidArgsFunction: util.ValidArgsAvailableNodes,
Run: func(cmd *cobra.Command, args []string) {
nodes, headersOff := parseGetNodeCmd(cmd, args)
var existingNodes []*k3d.Node
if len(nodes) == 0 { // Option a) no name specified -> get all nodes
found, err := cluster.GetNodes(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
existingNodes = append(existingNodes, found...)
} else { // Option b) cluster name specified -> get specific cluster
for _, node := range nodes {
found, err := cluster.GetNode(cmd.Context(), runtimes.SelectedRuntime, node)
if err != nil {
log.Fatalln(err)
}
existingNodes = append(existingNodes, found)
}
}
// print existing clusters
printNodes(existingNodes, headersOff)
},
}
// add flags
cmd.Flags().Bool("no-headers", false, "Disable headers")
// add subcommands
// done
return cmd
}
func parseGetNodeCmd(cmd *cobra.Command, args []string) ([]*k3d.Node, bool) {
// --no-headers
headersOff, err := cmd.Flags().GetBool("no-headers")
if err != nil {
log.Fatalln(err)
}
// Args = node name
if len(args) == 0 {
return nil, headersOff
}
nodes := []*k3d.Node{}
for _, name := range args {
nodes = append(nodes, &k3d.Node{Name: name})
}
return nodes, headersOff
}
func printNodes(nodes []*k3d.Node, headersOff bool) {
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths)
defer tabwriter.Flush()
if !headersOff {
headers := []string{"NAME", "ROLE", "CLUSTER"} // TODO: add status
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t"))
if err != nil {
log.Fatalln("Failed to print headers")
}
}
sort.Slice(nodes, func(i, j int) bool {
return nodes[i].Name < nodes[j].Name
})
for _, node := range nodes {
fmt.Fprintf(tabwriter, "%s\t%s\t%s\n", strings.TrimPrefix(node.Name, "/"), string(node.Role), node.Labels[k3d.LabelClusterName])
}
}

@ -1,52 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package load
import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdLoad returns a new cobra command
func NewCmdLoad() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "load",
Short: "Load a resource [image] into a cluster.",
Long: `Load a resource [image] into a cluster.`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Errorln("Couldn't get help text")
log.Fatalln(err)
}
},
}
// add subcommands
cmd.AddCommand(NewCmdLoadImage())
// add flags
// done
return cmd
}

@ -1,97 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package load
import (
"github.com/spf13/cobra"
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/runtimes"
"github.com/rancher/k3d/v3/pkg/tools"
k3d "github.com/rancher/k3d/v3/pkg/types"
log "github.com/sirupsen/logrus"
)
// NewCmdLoadImage returns a new cobra command
func NewCmdLoadImage() *cobra.Command {
loadImageOpts := k3d.LoadImageOpts{}
// create new command
cmd := &cobra.Command{
Use: "image [IMAGE | ARCHIVE [IMAGE | ARCHIVE...]]",
Short: "Load an image from docker into a k3d cluster.",
Long: `Load an image from docker into a k3d cluster.`,
Aliases: []string{"images"},
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
images, clusters := parseLoadImageCmd(cmd, args)
log.Debugf("Load images [%+v] from runtime [%s] into clusters [%+v]", images, runtimes.SelectedRuntime, clusters)
for _, cluster := range clusters {
log.Infof("Loading images into '%s'", cluster.Name)
if err := tools.LoadImagesIntoCluster(cmd.Context(), runtimes.SelectedRuntime, images, &cluster, loadImageOpts); err != nil {
log.Errorf("Failed to load images into cluster '%s'", cluster.Name)
log.Errorln(err)
}
}
log.Info("DONE")
},
}
/*********
* Flags *
*********/
cmd.Flags().StringArrayP("cluster", "c", []string{k3d.DefaultClusterName}, "Select clusters to load the image to.")
if err := cmd.RegisterFlagCompletionFunc("cluster", util.ValidArgsAvailableClusters); err != nil {
log.Fatalln("Failed to register flag completion for '--cluster'", err)
}
cmd.Flags().BoolVarP(&loadImageOpts.KeepTar, "keep-tarball", "k", false, "Do not delete the tarball containing the saved images from the shared volume")
/* Subcommands */
// done
return cmd
}
// parseLoadImageCmd parses the command input into variables required to create a cluster
func parseLoadImageCmd(cmd *cobra.Command, args []string) ([]string, []k3d.Cluster) {
// --cluster
clusterNames, err := cmd.Flags().GetStringArray("cluster")
if err != nil {
log.Fatalln(err)
}
clusters := []k3d.Cluster{}
for _, clusterName := range clusterNames {
clusters = append(clusters, k3d.Cluster{Name: clusterName})
}
// images
images := args
if len(images) == 0 {
log.Fatalln("No images specified!")
}
return images, clusters
}

@ -31,15 +31,9 @@ import (
"github.com/spf13/cobra"
"github.com/rancher/k3d/v3/cmd/cluster"
"github.com/rancher/k3d/v3/cmd/create"
"github.com/rancher/k3d/v3/cmd/delete"
"github.com/rancher/k3d/v3/cmd/get"
"github.com/rancher/k3d/v3/cmd/image"
"github.com/rancher/k3d/v3/cmd/kubeconfig"
"github.com/rancher/k3d/v3/cmd/load"
"github.com/rancher/k3d/v3/cmd/node"
"github.com/rancher/k3d/v3/cmd/start"
"github.com/rancher/k3d/v3/cmd/stop"
"github.com/rancher/k3d/v3/pkg/runtimes"
"github.com/rancher/k3d/v3/version"
@ -95,20 +89,11 @@ func init() {
rootCmd.Flags().BoolVar(&flags.version, "version", false, "Show k3d and default k3s version")
// add subcommands
if os.Getenv("K3D_NEW_SYNTAX") == "1" {
rootCmd.AddCommand(cluster.NewCmdCluster())
rootCmd.AddCommand(kubeconfig.NewCmdKubeconfig())
rootCmd.AddCommand(node.NewCmdNode())
rootCmd.AddCommand(image.NewCmdImage())
} else {
rootCmd.AddCommand(NewCmdCompletion())
rootCmd.AddCommand(create.NewCmdCreate())
rootCmd.AddCommand(delete.NewCmdDelete())
rootCmd.AddCommand(get.NewCmdGet())
rootCmd.AddCommand(stop.NewCmdStop())
rootCmd.AddCommand(start.NewCmdStart())
rootCmd.AddCommand(load.NewCmdLoad())
}
rootCmd.AddCommand(NewCmdCompletion())
rootCmd.AddCommand(cluster.NewCmdCluster())
rootCmd.AddCommand(kubeconfig.NewCmdKubeconfig())
rootCmd.AddCommand(node.NewCmdNode())
rootCmd.AddCommand(image.NewCmdImage())
rootCmd.AddCommand(&cobra.Command{
Use: "version",

@ -1,52 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package start
import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdStart returns a new cobra command
func NewCmdStart() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "start",
Short: "Start a resource [cluster, node].",
Long: `Start a resource [cluster, node].`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Errorln("Couldn't get help text")
log.Fatalln(err)
}
},
}
// add subcommands
cmd.AddCommand(NewCmdStartCluster())
cmd.AddCommand(NewCmdStartNode())
// done
return cmd
}

@ -1,102 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package start
import (
"time"
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
"github.com/rancher/k3d/v3/pkg/types"
"github.com/spf13/cobra"
k3d "github.com/rancher/k3d/v3/pkg/types"
log "github.com/sirupsen/logrus"
)
// NewCmdStartCluster returns a new cobra command
func NewCmdStartCluster() *cobra.Command {
startClusterOpts := types.StartClusterOpts{}
// create new command
cmd := &cobra.Command{
Use: "cluster (NAME [NAME...] | --all)",
Short: "Start an existing k3d cluster",
Long: `Start an existing k3d cluster`,
ValidArgsFunction: util.ValidArgsAvailableClusters,
Run: func(cmd *cobra.Command, args []string) {
clusters := parseStartClusterCmd(cmd, args)
if len(clusters) == 0 {
log.Infoln("No clusters found")
} else {
for _, c := range clusters {
if err := cluster.StartCluster(cmd.Context(), runtimes.SelectedRuntime, c, startClusterOpts); err != nil {
log.Fatalln(err)
}
}
}
},
}
// add flags
cmd.Flags().BoolP("all", "a", false, "Start all existing clusters")
cmd.Flags().BoolVar(&startClusterOpts.WaitForMaster, "wait", false, "Wait for the master(s) (and loadbalancer) to be ready before returning.")
cmd.Flags().DurationVar(&startClusterOpts.Timeout, "timeout", 0*time.Second, "Maximum waiting time for '--wait' before canceling/returning.")
// add subcommands
// done
return cmd
}
// parseStartClusterCmd parses the command input into variables required to start clusters
func parseStartClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
// --all
var clusters []*k3d.Cluster
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
return clusters
}
if len(args) < 1 {
log.Fatalln("Expecting at least one cluster name if `--all` is not set")
}
for _, name := range args {
cluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
if err != nil {
log.Fatalln(err)
}
clusters = append(clusters, cluster)
}
return clusters
}

@ -1,62 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package start
import (
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
"github.com/spf13/cobra"
log "github.com/sirupsen/logrus"
)
// NewCmdStartNode returns a new cobra command
func NewCmdStartNode() *cobra.Command {
// create new command
cmd := &cobra.Command{
Use: "node NAME", // TODO: startNode: allow one or more names or --all
Short: "Start an existing k3d node",
Long: `Start an existing k3d node.`,
ValidArgsFunction: util.ValidArgsAvailableNodes,
Run: func(cmd *cobra.Command, args []string) {
node := parseStartNodeCmd(cmd, args)
if err := runtimes.SelectedRuntime.StartNode(cmd.Context(), node); err != nil {
log.Fatalln(err)
}
},
}
// done
return cmd
}
// parseStartNodeCmd parses the command input into variables required to start a node
func parseStartNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
// node name // TODO: startNode: allow node filters, e.g. `k3d start nodes mycluster@worker` to start all worker nodes of cluster 'mycluster'
if len(args) == 0 || len(args[0]) == 0 {
log.Fatalln("No node name given")
}
return &k3d.Node{Name: args[0]}
}

@ -1,52 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package stop
import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// NewCmdStop returns a new cobra command
func NewCmdStop() *cobra.Command {
// create new cobra command
cmd := &cobra.Command{
Use: "stop",
Short: "Stop a resource [cluster, node].",
Long: `Stop a resource [cluster, node].`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Errorln("Couldn't get help text")
log.Fatalln(err)
}
},
}
// add subcommands
cmd.AddCommand(NewCmdStopCluster())
cmd.AddCommand(NewCmdStopNode())
// done
return cmd
}

@ -1,95 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package stop
import (
"github.com/spf13/cobra"
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/cluster"
"github.com/rancher/k3d/v3/pkg/runtimes"
k3d "github.com/rancher/k3d/v3/pkg/types"
log "github.com/sirupsen/logrus"
)
// NewCmdStopCluster returns a new cobra command
func NewCmdStopCluster() *cobra.Command {
// create new command
cmd := &cobra.Command{
Use: "cluster (NAME [NAME...] | --all)",
Short: "Stop an existing k3d cluster",
Long: `Stop an existing k3d cluster.`,
ValidArgsFunction: util.ValidArgsAvailableClusters,
Run: func(cmd *cobra.Command, args []string) {
clusters := parseStopClusterCmd(cmd, args)
if len(clusters) == 0 {
log.Infoln("No clusters found")
} else {
for _, c := range clusters {
if err := cluster.StopCluster(cmd.Context(), runtimes.SelectedRuntime, c); err != nil {
log.Fatalln(err)
}
}
}
},
}
// add flags
cmd.Flags().BoolP("all", "a", false, "Start all existing clusters")
// add subcommands
// done
return cmd
}
// parseStopClusterCmd parses the command input into variables required to start clusters
func parseStopClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
// --all
var clusters []*k3d.Cluster
if all, err := cmd.Flags().GetBool("all"); err != nil {
log.Fatalln(err)
} else if all {
clusters, err = cluster.GetClusters(cmd.Context(), runtimes.SelectedRuntime)
if err != nil {
log.Fatalln(err)
}
return clusters
}
if len(args) < 1 {
log.Fatalln("Expecting at least one cluster name if `--all` is not set")
}
for _, name := range args {
cluster, err := cluster.GetCluster(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
if err != nil {
log.Fatalln(err)
}
clusters = append(clusters, cluster)
}
return clusters
}

@ -1,63 +0,0 @@
/*
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package stop
import (
"github.com/rancher/k3d/v3/cmd/util"
"github.com/rancher/k3d/v3/pkg/runtimes"
"github.com/spf13/cobra"
k3d "github.com/rancher/k3d/v3/pkg/types"
log "github.com/sirupsen/logrus"
)
// NewCmdStopNode returns a new cobra command
func NewCmdStopNode() *cobra.Command {
// create new command
cmd := &cobra.Command{
Use: "node NAME", // TODO: stopNode: allow one or more names or --all",
Short: "Stop an existing k3d node",
Long: `Stop an existing k3d node.`,
ValidArgsFunction: util.ValidArgsAvailableNodes,
Run: func(cmd *cobra.Command, args []string) {
node := parseStopNodeCmd(cmd, args)
if err := runtimes.SelectedRuntime.StopNode(cmd.Context(), node); err != nil {
log.Fatalln(err)
}
},
}
// done
return cmd
}
// parseStopNodeCmd parses the command input into variables required to stop a node
func parseStopNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
// node name // TODO: allow node filters, e.g. `k3d stop nodes mycluster@worker` to stop all worker nodes of cluster 'mycluster'
if len(args) == 0 || len(args[0]) == 0 {
log.Fatalln("No node name given")
}
return &k3d.Node{Name: args[0]}
}
Loading…
Cancel
Save