Skip to content

Commit

Permalink
feat(fleetctl): User-defined columns in list-machines
Browse files Browse the repository at this point in the history
  • Loading branch information
bcwaldon committed May 26, 2014
1 parent 09d5587 commit f34ed83
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 29 deletions.
100 changes: 71 additions & 29 deletions fleetctl/list_machines.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,88 @@ import (
"github.com/coreos/fleet/machine"
)

var cmdListMachines = &Command{
Name: "list-machines",
Summary: "Enumerate the current hosts in the cluster",
Usage: "[-l|--full] [--no-legend]",
Description: `Lists all active machines within the cluster. Previously active machines will
not appear in this list.
For easily parsable output, you can remove the column headers:
fleetctl list-machines --no-legend
Output the list without truncation:
fleetctl list-machines --full`,
Run: runListMachines,
}
const (
defaultListMachinesFields = "machine,ip,metadata"
)

var (
listMachinesFieldsFlag string
cmdListMachines = &Command{
Name: "list-machines",
Summary: "Enumerate the current hosts in the cluster",
Usage: "[-l|--full] [--no-legend]",
Description: `Lists all active machines within the cluster. Previously active machines will
not appear in this list.
For easily parsable output, you can remove the column headers:
fleetctl list-machines --no-legend
Output the list without truncation:
fleetctl list-machines --full`,
Run: runListMachines,
}

listMachinesFields = map[string]machineToField{
"machine": func(ms *machine.MachineState, full bool) string {
return machineIDLegend(*ms, full)
},
"ip": func(ms *machine.MachineState, full bool) string {
ip := ms.PublicIP
if len(ip) == 0 {
ip = "-"
}
return ip
},
"metadata": func(ms *machine.MachineState, full bool) string {
metadata := "-"
if len(ms.Metadata) != 0 {
metadata = formatMetadata(ms.Metadata)
}
return metadata
},
}
)

type machineToField func(ms *machine.MachineState, full bool) string

func init() {
cmdListMachines.Flags.BoolVar(&sharedFlags.Full, "full", false, "Do not ellipsize fields on output")
cmdListMachines.Flags.BoolVar(&sharedFlags.Full, "l", false, "Shorthand for --full")
cmdListMachines.Flags.BoolVar(&sharedFlags.NoLegend, "no-legend", false, "Do not print a legend (column headers)")
cmdListMachines.Flags.StringVar(&listMachinesFieldsFlag, "fields", defaultListMachinesFields, fmt.Sprintf("Columns to print for each Machine. Valid fields are %q", strings.Join(machineToFieldKeys(listMachinesFields), ",")))
}

func runListMachines(args []string) (exit int) {
if !sharedFlags.NoLegend {
fmt.Fprintln(out, "MACHINE\tIP\tMETADATA")
if listMachinesFieldsFlag == "" {
fmt.Fprintf(os.Stderr, "Must define output format\n")
return 1
}

cols := strings.Split(listMachinesFieldsFlag, ",")
for _, s := range cols {
if _, ok := listMachinesFields[s]; !ok {
fmt.Fprintf(os.Stderr, "Invalid key in output format: %q\n", s)
return 1
}
}

machines, sortable, err := findAllMachines()
if err != nil {
fmt.Fprintf(os.Stderr, "Error retrieving list of active machines: %v\n", err)
return 1
}
for _, m := range sortable {
mach := machines[m]

ml := machineIDLegend(mach, sharedFlags.Full)

ip := mach.PublicIP
if len(ip) == 0 {
ip = "-"
}
if !sharedFlags.NoLegend {
fmt.Fprintln(out, strings.ToUpper(strings.Join(cols, "\t")))
}

metadata := "-"
if len(mach.Metadata) != 0 {
metadata = formatMetadata(mach.Metadata)
for _, name := range sortable {
var f []string
ms := machines[name]
for _, c := range cols {
f = append(f, listMachinesFields[c](&ms, sharedFlags.Full))
}

fmt.Fprintf(out, "%s\t%s\t%s\n", ml, ip, metadata)
fmt.Fprintln(out, strings.Join(f, "\t"))
}

out.Flush()
Expand Down Expand Up @@ -91,3 +126,10 @@ func findAllMachines() (machines map[string]machine.MachineState, sortable sort.

return
}

func machineToFieldKeys(m map[string]machineToField) (keys []string) {
for k, _ := range m {
keys = append(keys, k)
}
return
}
41 changes: 41 additions & 0 deletions fleetctl/list_machines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/coreos/fleet/machine"
"github.com/coreos/fleet/registry"
"github.com/coreos/fleet/resource"
)

func newTestRegistryForListMachines() registry.Registry {
Expand Down Expand Up @@ -38,3 +39,43 @@ func TestGetAllMachines(t *testing.T) {
t.Errorf("Expected to find mnopqr as the last machine, but it was %s\n", sortable[2])
}
}

func TestListMachinesFieldsToStrings(t *testing.T) {
id := "4d389537d9d14bdabe8be54a9c29f68d"
ip := "192.0.2.1"
metadata := map[string]string{
"foo": "bar",
"ping": "pong",
}
ver := "v9.9.9"
res := resource.ResourceTuple{10, 1024, 1024}

ms := &machine.MachineState{id, ip, metadata, ver, res}

val := listMachinesFields["machine"](ms, false)
assertEqual(t, "machine", "4d389537...", val)

val = listMachinesFields["machine"](ms, true)
assertEqual(t, "machine", "4d389537d9d14bdabe8be54a9c29f68d", val)

val = listMachinesFields["ip"](ms, false)
assertEqual(t, "ip", "192.0.2.1", val)

val = listMachinesFields["metadata"](ms, false)
assertEqual(t, "metadata", "foo=bar, ping=pong", val)
}

func TestListMachinesFieldsEmpty(t *testing.T) {
id := "4d389537d9d14bdabe8be54a9c29f68d"
ip := ""
metadata := map[string]string{}
ver := "v9.9.9"
res := resource.ResourceTuple{10, 1024, 1024}

ms := &machine.MachineState{id, ip, metadata, ver, res}

for _, tt := range []string{"ip", "metadata"} {
f := listMachinesFields[tt](ms, false)
assertEqual(t, tt, "-", f)
}
}

0 comments on commit f34ed83

Please sign in to comment.