mirror of https://github.com/kubernetes/kops.git
Support `kops get/edit instancegroup`
This lets us start to manage instancegroups through the CLI Issue #66
This commit is contained in:
parent
8f12f3e4fe
commit
992a3e7d7f
|
@ -11,8 +11,6 @@ import (
|
|||
"path/filepath"
|
||||
)
|
||||
|
||||
var editorEnvs = []string{"KUBE_EDITOR", "EDITOR"}
|
||||
|
||||
type EditClusterCmd struct {
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"bytes"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/editor"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type EditInstanceGroupCmd struct {
|
||||
}
|
||||
|
||||
var editInstanceGroupCmd EditInstanceGroupCmd
|
||||
|
||||
func init() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "instancegroup",
|
||||
Aliases: []string{"instancegroups", "ig"},
|
||||
Short: "Edit instancegroup",
|
||||
Long: `Edit an instancegroup configuration.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
glog.Exitf("Specify name of instance group to edit")
|
||||
}
|
||||
if len(args) != 1 {
|
||||
glog.Exitf("Can only edit one instance group at a time!")
|
||||
}
|
||||
err := editInstanceGroupCmd.Run(args[0])
|
||||
if err != nil {
|
||||
glog.Exitf("%v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
editCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
func (c *EditInstanceGroupCmd) Run(groupName string) error {
|
||||
stateStore, err := rootCommand.StateStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
edit = editor.NewDefaultEditor(editorEnvs)
|
||||
)
|
||||
|
||||
ext := "yaml"
|
||||
|
||||
raw, err := stateStore.VFSPath().Join("instancegroup", groupName).ReadFile()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading instancegroup file: %v", err)
|
||||
}
|
||||
|
||||
// launch the editor
|
||||
edited, file, err := edit.LaunchTempFile(fmt.Sprintf("%s-edit-", filepath.Base(os.Args[0])), ext, bytes.NewReader(raw))
|
||||
defer func() {
|
||||
if file != "" {
|
||||
os.Remove(file)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error launching editor: %v", err)
|
||||
}
|
||||
|
||||
if bytes.Equal(edited, raw) {
|
||||
fmt.Fprintln(os.Stderr, "Edit cancelled, no changes made.")
|
||||
return nil
|
||||
}
|
||||
|
||||
err = stateStore.VFSPath().Join("instancegroup", groupName).WriteFile(edited)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing instancegroup file: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package main
|
||||
|
||||
var editorEnvs = []string{"KUBE_EDITOR", "EDITOR"}
|
|
@ -0,0 +1,92 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/golang/glog"
|
||||
"io"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"reflect"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
// Table renders tables to stdout
|
||||
type Table struct {
|
||||
columns []string
|
||||
getters []reflect.Value
|
||||
}
|
||||
|
||||
// AddColumn registers an available column for formatting
|
||||
func (t *Table) AddColumn(name string, getter interface{}) {
|
||||
getterVal := reflect.ValueOf(getter)
|
||||
|
||||
t.columns = append(t.columns, name)
|
||||
t.getters = append(t.getters, getterVal)
|
||||
}
|
||||
|
||||
// Render writes the items in a table, to out
|
||||
func (t *Table) Render(items interface{}, out io.Writer) error {
|
||||
itemsValue := reflect.ValueOf(items)
|
||||
if itemsValue.Kind() != reflect.Slice {
|
||||
glog.Fatal("unexpected kind for items: ", itemsValue.Kind())
|
||||
}
|
||||
|
||||
length := itemsValue.Len()
|
||||
|
||||
var b bytes.Buffer
|
||||
w := new(tabwriter.Writer)
|
||||
|
||||
// Format in tab-separated columns with a tab stop of 8.
|
||||
w.Init(out, 0, 8, 0, '\t', tabwriter.StripEscape)
|
||||
|
||||
writeHeader := true
|
||||
if writeHeader {
|
||||
for i, c := range t.columns {
|
||||
if i != 0 {
|
||||
b.WriteByte('\t')
|
||||
}
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
b.WriteString(c)
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
|
||||
_, err := w.Write(b.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to output: %v", err)
|
||||
}
|
||||
b.Reset()
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
item := itemsValue.Index(i)
|
||||
|
||||
for j := range t.columns {
|
||||
if j != 0 {
|
||||
b.WriteByte('\t')
|
||||
}
|
||||
|
||||
getter := t.getters[j]
|
||||
var args []reflect.Value
|
||||
args = append(args, item)
|
||||
fvs := getter.Call(args)
|
||||
fv := fvs[0]
|
||||
|
||||
s := fi.ValueAsString(fv)
|
||||
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
b.WriteString(s)
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
|
||||
_, err := w.Write(b.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to output: %v", err)
|
||||
}
|
||||
b.Reset()
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,16 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"bytes"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kops/upup/pkg/api"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"os"
|
||||
"reflect"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
type GetClustersCmd struct {
|
||||
|
@ -20,8 +15,8 @@ var getClustersCmd GetClustersCmd
|
|||
|
||||
func init() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "cluster",
|
||||
Aliases: []string{"clusters"},
|
||||
Use: "clusters",
|
||||
Aliases: []string{"cluster"},
|
||||
Short: "get clusters",
|
||||
Long: `List or get clusters.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
@ -41,14 +36,6 @@ func (c *GetClustersCmd) Run() error {
|
|||
return err
|
||||
}
|
||||
|
||||
columns := []string{}
|
||||
fields := []func(*api.Cluster) string{}
|
||||
|
||||
columns = append(columns, "NAME")
|
||||
fields = append(fields, func(c *api.Cluster) string {
|
||||
return c.Name
|
||||
})
|
||||
|
||||
var clusters []*api.Cluster
|
||||
|
||||
for _, clusterName := range clusterNames {
|
||||
|
@ -58,82 +45,17 @@ func (c *GetClustersCmd) Run() error {
|
|||
}
|
||||
|
||||
// TODO: Faster if we don't read groups...
|
||||
// We probably can just have a comand which directly reads all cluster config files
|
||||
// We probably can just have a command which directly reads all cluster config files
|
||||
cluster, _, err := api.ReadConfig(stateStore)
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
if len(clusters) == 0 {
|
||||
return nil
|
||||
}
|
||||
return WriteTable(clusters, columns, fields)
|
||||
}
|
||||
|
||||
func WriteTable(items interface{}, columns []string, fields interface{}) error {
|
||||
itemsValue := reflect.ValueOf(items)
|
||||
if itemsValue.Kind() != reflect.Slice {
|
||||
glog.Fatal("unexpected kind for items in WriteTable: ", itemsValue.Kind())
|
||||
}
|
||||
fieldsValue := reflect.ValueOf(fields)
|
||||
if fieldsValue.Kind() != reflect.Slice {
|
||||
glog.Fatal("unexpected kind for fields in WriteTable: ", fieldsValue.Kind())
|
||||
}
|
||||
|
||||
length := itemsValue.Len()
|
||||
|
||||
var b bytes.Buffer
|
||||
w := new(tabwriter.Writer)
|
||||
|
||||
// Format in tab-separated columns with a tab stop of 8.
|
||||
w.Init(os.Stdout, 0, 8, 0, '\t', tabwriter.StripEscape)
|
||||
|
||||
writeHeader := true
|
||||
if writeHeader {
|
||||
for i, c := range columns {
|
||||
if i != 0 {
|
||||
b.WriteByte('\t')
|
||||
}
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
b.WriteString(c)
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
|
||||
_, err := w.Write(b.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to output: %v", err)
|
||||
}
|
||||
b.Reset()
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
item := itemsValue.Index(i)
|
||||
|
||||
for j := range columns {
|
||||
if j != 0 {
|
||||
b.WriteByte('\t')
|
||||
}
|
||||
|
||||
fieldFunc := fieldsValue.Index(j)
|
||||
var args []reflect.Value
|
||||
args = append(args, item)
|
||||
fvs := fieldFunc.Call(args)
|
||||
fv := fvs[0]
|
||||
|
||||
s := fi.ValueAsString(fv)
|
||||
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
b.WriteString(s)
|
||||
b.WriteByte(tabwriter.Escape)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
|
||||
_, err := w.Write(b.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to output: %v", err)
|
||||
}
|
||||
b.Reset()
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
|
||||
t := &Table{}
|
||||
t.AddColumn("NAME", func(c *api.Cluster) string {
|
||||
return c.Name
|
||||
})
|
||||
return t.Render(clusters, os.Stdout)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kops/upup/pkg/api"
|
||||
)
|
||||
|
||||
type GetInstanceGroupsCmd struct {
|
||||
}
|
||||
|
||||
var getInstanceGroupsCmd GetInstanceGroupsCmd
|
||||
|
||||
func init() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "instancegroups",
|
||||
Aliases: []string{"instancegroup", "ig"},
|
||||
Short: "get instancegroups",
|
||||
Long: `List or get InstanceGroups.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := getInstanceGroupsCmd.Run()
|
||||
if err != nil {
|
||||
glog.Exitf("%v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
func (c *GetInstanceGroupsCmd) Run() error {
|
||||
stateStore, err := rootCommand.StateStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, instancegroups, err := api.ReadConfig(stateStore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(instancegroups) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
t := &Table{}
|
||||
t.AddColumn("NAME", func(c *api.InstanceGroup) string {
|
||||
return c.Name
|
||||
})
|
||||
return t.Render(instancegroups, os.Stdout)
|
||||
}
|
Loading…
Reference in New Issue