refactor column config

This commit is contained in:
Bradley Cicenas 2020-01-02 19:28:51 +00:00
parent c7a8bfa26f
commit fc9bd9e5ca
5 changed files with 162 additions and 136 deletions

138
config/columns.go Normal file
View File

@ -0,0 +1,138 @@
package config
import (
"strings"
)
// defaults
var defaultColumns = []Column{
Column{
Name: "status",
Label: "Status Indicator",
Enabled: true,
},
Column{
Name: "name",
Label: "Container Name",
Enabled: true,
},
Column{
Name: "id",
Label: "Container ID",
Enabled: true,
},
Column{
Name: "cpu",
Label: "CPU Usage",
Enabled: true,
},
Column{
Name: "mem",
Label: "Memory Usage",
Enabled: true,
},
Column{
Name: "net",
Label: "Network RX/TX",
Enabled: true,
},
Column{
Name: "io",
Label: "Disk IO Read/Write",
Enabled: true,
},
Column{
Name: "pids",
Label: "Container PID Count",
Enabled: true,
},
}
type Column struct {
Name string
Label string
Enabled bool
}
// ColumnsString returns an ordered and comma-delimited string of currently enabled Columns
func ColumnsString() string { return strings.Join(EnabledColumns(), ",") }
// EnabledColumns returns an ordered array of enabled column names
func EnabledColumns() (a []string) {
lock.RLock()
defer lock.RUnlock()
for _, col := range GlobalColumns {
if col.Enabled {
a = append(a, col.Name)
}
}
return a
}
// ColumnLeft moves the column with given name up one position, if possible
func ColumnLeft(name string) {
idx := colIndex(name)
if idx > 0 {
swapCols(idx, idx-1)
}
}
// ColumnRight moves the column with given name up one position, if possible
func ColumnRight(name string) {
idx := colIndex(name)
if idx < len(GlobalColumns)-1 {
swapCols(idx, idx+1)
}
}
// Set Column order and enabled status from one or more provided Column names
func SetColumns(names []string) {
var (
n int
curColStr = ColumnsString()
newColumns = make([]*Column, len(GlobalColumns))
)
lock.Lock()
// add enabled columns by name
for _, name := range names {
newColumns[n] = popColumn(name)
newColumns[n].Enabled = true
n++
}
// extend with omitted columns as disabled
for _, col := range GlobalColumns {
newColumns[n] = col
newColumns[n].Enabled = false
n++
}
GlobalColumns = newColumns
lock.Unlock()
log.Noticef("config change [columns]: %s -> %s", curColStr, ColumnsString())
}
func swapCols(i, j int) { GlobalColumns[i], GlobalColumns[j] = GlobalColumns[j], GlobalColumns[i] }
func popColumn(name string) *Column {
idx := colIndex(name)
if idx < 0 {
panic("no such column name: " + name)
}
col := GlobalColumns[idx]
GlobalColumns = append(GlobalColumns[:idx], GlobalColumns[idx+1:]...)
return col
}
// return index of column with given name, if any
func colIndex(name string) int {
for n, c := range GlobalColumns {
if c.Name == name {
return n
}
}
return -1
}

View File

@ -16,17 +16,18 @@ var (
type File struct {
Options map[string]string `toml:"options"`
Toggles map[string]bool `toml:"toggles"`
Widgets []Widget `toml:"widget"`
}
func exportConfig() File {
// update columns param from working config
Update("columns", ColumnsString())
lock.RLock()
defer lock.RUnlock()
c := File{
Options: make(map[string]string),
Toggles: make(map[string]bool),
Widgets: make([]Widget, len(GlobalWidgets)),
}
for _, p := range GlobalParams {
@ -35,9 +36,6 @@ func exportConfig() File {
for _, sw := range GlobalSwitches {
c.Toggles[sw.Key] = sw.Val
}
for n, w := range GlobalWidgets {
c.Widgets[n] = *w
}
return c
}
@ -54,15 +52,21 @@ func Read() error {
if _, err := toml.DecodeFile(path, &config); err != nil {
return err
}
for k, v := range config.Options {
Update(k, v)
}
for k, v := range config.Toggles {
UpdateSwitch(k, v)
}
for _, w := range config.Widgets {
UpdateWidget(strings.ToLower(w.Name), w.Enabled)
// set working column config, if provided
colStr := GetVal("columns")
if len(colStr) > 0 {
var colNames []string
for _, s := range strings.Split(colStr, ",") {
colNames = append(colNames, strings.TrimSpace(s))
}
SetColumns(colNames)
}
return nil

View File

@ -11,7 +11,7 @@ import (
var (
GlobalParams []*Param
GlobalSwitches []*Switch
GlobalWidgets []*Widget
GlobalColumns []*Column
lock sync.RWMutex
log = logging.Init()
)
@ -19,15 +19,16 @@ var (
func Init() {
for _, p := range defaultParams {
GlobalParams = append(GlobalParams, p)
log.Infof("loaded default config param: %s: %s", quote(p.Key), quote(p.Val))
log.Infof("loaded default config param [%s]: %s", quote(p.Key), quote(p.Val))
}
for _, s := range defaultSwitches {
GlobalSwitches = append(GlobalSwitches, s)
log.Infof("loaded default config switch: %s: %t", quote(s.Key), s.Val)
log.Infof("loaded default config switch [%s]: %t", quote(s.Key), s.Val)
}
for _, w := range defaultWidgets {
GlobalWidgets = append(GlobalWidgets, w)
log.Infof("loaded default widget: %s: %t", quote(w.Name), w.Enabled)
for _, c := range defaultColumns {
x := c
GlobalColumns = append(GlobalColumns, &x)
log.Infof("loaded default widget config [%s]: %t", quote(x.Name), x.Enabled)
}
}

View File

@ -17,6 +17,11 @@ var defaultParams = []*Param{
Val: "sh",
Label: "Shell",
},
&Param{
Key: "columns",
Val: "status,name,id,cpu,mem,net,io,pids",
Label: "Enabled Columns",
},
}
type Param struct {

View File

@ -1,122 +0,0 @@
package config
import (
"strings"
)
// defaults
var defaultWidgets = []*Widget{
&Widget{
Name: "status",
Enabled: true,
},
&Widget{
Name: "name",
Enabled: true,
},
&Widget{
Name: "id",
Enabled: true,
},
&Widget{
Name: "cpu",
Enabled: true,
},
&Widget{
Name: "mem",
Enabled: true,
},
&Widget{
Name: "net",
Enabled: true,
},
&Widget{
Name: "io",
Enabled: true,
},
&Widget{
Name: "pids",
Enabled: true,
},
}
type Widget struct {
Name string
Enabled bool
}
// GetWidget returns a Widget by name
func GetWidget(name string) *Widget {
lock.RLock()
defer lock.RUnlock()
for _, w := range GlobalWidgets {
if w.Name == name {
return w
}
}
log.Errorf("widget name not found: %s", name)
return &Widget{} // default
}
// Widgets returns a copy of all configurable Widgets, in order
func Widgets() []Widget {
a := make([]Widget, len(GlobalWidgets))
lock.RLock()
defer lock.RUnlock()
for n, w := range GlobalWidgets {
a[n] = *w
}
return a
}
// EnabledWidgets returns an ordered array of enabled widget names
func EnabledWidgets() (a []string) {
for _, w := range Widgets() {
if w.Enabled {
a = append(a, w.Name)
}
}
return a
}
func UpdateWidget(name string, enabled bool) {
w := GetWidget(name)
oldVal := w.Enabled
log.Noticef("config change [%s-enabled]: %t -> %t", name, oldVal, enabled)
lock.Lock()
defer lock.Unlock()
w.Enabled = enabled
}
func ToggleWidgetEnabled(name string) {
w := GetWidget(name)
newVal := !w.Enabled
log.Noticef("config change [%s-enabled]: %t -> %t", name, w.Enabled, newVal)
lock.Lock()
defer lock.Unlock()
w.Enabled = newVal
}
// UpdateWidgets replaces existing ordered widgets with those provided
func UpdateWidgets(newWidgets []Widget) {
oldOrder := widgetNames()
lock.Lock()
for n, w := range newWidgets {
GlobalWidgets[n] = &w
}
lock.Unlock()
log.Noticef("config change [widget-order]: %s -> %s", oldOrder, widgetNames())
}
func widgetNames() string {
a := make([]string, len(GlobalWidgets))
for n, w := range Widgets() {
a[n] = w.Name
}
return strings.Join(a, ", ")
}