Skip to content

Commit bfc7a65

Browse files
committed
[OCONF-184] Use tableWriter
1 parent 7d329c2 commit bfc7a65

1 file changed

Lines changed: 105 additions & 29 deletions

File tree

coconut/configuration/configuration.go

Lines changed: 105 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
package configuration
2828

2929
import (
30+
"github.com/fatih/color"
31+
"github.com/olekukonko/tablewriter"
3032
"github.com/spf13/cobra"
3133
"github.com/spf13/viper"
3234
"github.com/briandowns/spinner"
@@ -35,6 +37,7 @@ import (
3537
"io"
3638
"github.com/sirupsen/logrus"
3739
"os"
40+
"sort"
3841
"github.com/AliceO2Group/Control/common/logger"
3942
"fmt"
4043
"strings"
@@ -64,6 +67,15 @@ const (
6467
logicError = iota // Logic/Output error
6568
)
6669

70+
var(
71+
white = color.New(color.FgHiWhite).SprintFunc()
72+
blue = color.New(color.FgHiBlue).SprintFunc()
73+
green = color.New(color.FgHiGreen).SprintFunc()
74+
yellow = color.New(color.FgHiYellow).SprintFunc()
75+
red = color.New(color.FgHiRed).SprintFunc()
76+
grey = color.New(color.FgWhite).SprintFunc()
77+
)
78+
6779
func WrapCall(call ConfigurationCall) RunFunc {
6880
return func(cmd *cobra.Command, args []string) {
6981
endpoint := viper.GetString("config_endpoint")
@@ -267,7 +279,7 @@ func History(cfg *configuration.ConsulSource, cmd *cobra.Command, args []string,
267279

268280
if len(args) < 1 || len(args) > 2 {
269281
err = errors.New(fmt.Sprintf(" accepts between 0 and 3 arg(s), but received %d", len(args)))
270-
return err, 1
282+
return err, invalidArgs
271283
}
272284
switch len(args) {
273285
case 1:
@@ -279,49 +291,47 @@ func History(cfg *configuration.ConsulSource, cmd *cobra.Command, args []string,
279291
component = splitCom[0]
280292
entry = splitCom[1]
281293
} else {
282-
return errors.New(fmt.Sprintf("Component and Entry name cannot contain `/ or `@`")), 1
294+
return errors.New(fmt.Sprintf("Component and Entry name cannot contain `/ or `@`")), invalidArgs
283295
}
284296
case 2:
285297
if IsInputSingleValidWord(args[0]) && IsInputSingleValidWord(args[1]) {
286298
component = args[0]
287299
entry = args[1]
288300
} else {
289-
return errors.New(fmt.Sprintf("Component and Entry name cannot contain `/ or `@`")), 1
301+
return errors.New(fmt.Sprintf("Component and Entry name cannot contain `/ or `@`")), invalidArgs
290302
}
291303
}
292304
key = componentsPath + component + "/" + entry
293-
keys, err := cfg.GetKeysByPrefix(key, "")
294-
if err != nil {
295-
return errors.New(fmt.Sprintf("Could not query ConsulSource")), 2
296-
}
305+
var keys sort.StringSlice
306+
keys , err = cfg.GetKeysByPrefix(key, "")
297307

298308
if len(keys) == 0 {
299-
return errors.New(fmt.Sprintf("No data was found")), 2
309+
return errors.New(fmt.Sprintf("No data was found")), emptyData
300310
} else {
301-
for index := range keys {
302-
var value = keys[index]
303-
value = strings.TrimPrefix(value , componentsPath)
304-
index2 := strings.LastIndex(value, "/")
305-
timetsamo := value[index2+1:]
306-
i, err := strconv.ParseInt(timetsamo, 10, 64)
307-
if err != nil {
308-
panic(err)
309-
}
310-
tm := time.Unix(i, 0)
311-
value = value[:index2] + string("@") + value[index2+1:] + " " + tm.Format(time.RFC822)
312-
keys[index] = value
313-
}
314311
if entry != "" {
315-
312+
sort.Sort(sort.Reverse(keys))
313+
drawTableHistoryConfigs([]string{}, keys, 0, o)
316314
} else {
317-
//tree
315+
maxLen := GetMaxLenOfKey(keys)
316+
var currentKeys sort.StringSlice
317+
for _, value := range keys {
318+
_, currentEntry, _ := GetComponentEntryTimestamp(value)
319+
if currentEntry != entry {
320+
if entry != "" {
321+
fmt.Fprintln(o, "- " + entry)
322+
sort.Sort(sort.Reverse(currentKeys))
323+
drawTableHistoryConfigs([]string{}, currentKeys,maxLen, o)
324+
}
325+
currentKeys = []string{value}
326+
entry = currentEntry
327+
} else {
328+
currentKeys = append(currentKeys, value)
329+
}
330+
}
331+
fmt.Fprintln(o, "- " + entry)
332+
drawTableHistoryConfigs([]string{}, currentKeys,maxLen, o)
318333
}
319334
}
320-
output, err := formatListOutput(cmd, keys)
321-
if err != nil {
322-
return err, 4
323-
}
324-
fmt.Fprintln(o, string(output))
325335
return nil, 0
326336
}
327337

@@ -348,10 +358,36 @@ func IsInputNameValid(input string) bool {
348358
return InputRegex.MatchString(input)
349359
}
350360

361+
func GetMapOfKeysAndTimestamps(keys []string)(map[string]string, error, int) {
362+
configMap := make(map[string]string)
363+
for index := range keys {
364+
var value = keys[index]
365+
value = strings.TrimPrefix(value , componentsPath)
366+
indexOfTimestamp := strings.LastIndex(value, "/")
367+
timestamp, err := GetTimestampInFormat(value[indexOfTimestamp+1:], time.RFC822)
368+
if err != nil {
369+
return nil, err, logicError
370+
}
371+
value = value[:indexOfTimestamp] + string("@") + value[indexOfTimestamp+1:]
372+
configMap[value] = timestamp
373+
}
374+
return configMap, nil, 0
375+
}
376+
351377
func IsInputSingleValidWord(input string) bool {
352378
return !strings.Contains(input, "/") && !strings.Contains(input, "@")
353379
}
354380

381+
// Method to parse a timestamp in the specified format
382+
func GetTimestampInFormat(timestamp string, timeFormat string)(string, error){
383+
timeStampAsInt, err := strconv.ParseInt(timestamp, 10, 64)
384+
if err != nil {
385+
return "", errors.New(fmt.Sprintf("Unable to identify timestamp"))
386+
}
387+
tm := time.Unix(timeStampAsInt, 0)
388+
return tm.Format(timeFormat), nil
389+
}
390+
355391
// Method to return the latest timestamp for a specified component & entry
356392
// If no keys were passed an error and code exit 3 will be returned
357393
func GetLatestTimestamp(keys []string, component string, entry string)(timestamp string, err error, code int) {
@@ -406,4 +442,44 @@ func GetListOfComponentsAndOrWithTimestamps(keys []string, keyPrefix string, use
406442
}
407443
}
408444
return components, nil, nonZero
409-
}
445+
}
446+
447+
func drawTableHistoryConfigs(headers []string, history []string, max int, o io.Writer) {
448+
table := tablewriter.NewWriter(o)
449+
if len(headers) > 0 {
450+
table.SetHeader(headers)
451+
}
452+
table.SetBorder(false)
453+
table.SetColMinWidth(0, max)
454+
455+
for _, value := range history {
456+
component, entry, timestamp := GetComponentEntryTimestamp(value)
457+
prettyTimestamp, err := GetTimestampInFormat(timestamp, time.RFC822)
458+
if err != nil {
459+
prettyTimestamp = timestamp
460+
}
461+
configName := red(component) + "/" + blue(entry) + "@" + timestamp
462+
table.Append([]string{configName, prettyTimestamp})
463+
}
464+
table.Render()
465+
}
466+
467+
func GetComponentEntryTimestamp(key string)(component string, entry string, timestamp string) {
468+
key = strings.TrimPrefix(key, componentsPath)
469+
key = strings.TrimPrefix(key, "/'")
470+
key = strings.TrimSuffix(key, "/")
471+
elements := strings.Split(key, "/")
472+
component = elements[0]
473+
entry = elements[1]
474+
timestamp = elements[2]
475+
return
476+
}
477+
478+
func GetMaxLenOfKey(keys []string) (maxLen int){
479+
maxLen = 0
480+
for _, value := range keys {
481+
if len(value) - len(componentsPath) >= maxLen {
482+
maxLen = len(value) - len(componentsPath)
483+
}
484+
}
485+
}

0 commit comments

Comments
 (0)