Moved some code to utils.go
This commit is contained in:
parent
f1c4fd960d
commit
bf20c815ce
331
cmd/list.go
331
cmd/list.go
@ -4,7 +4,6 @@ import (
|
||||
"os"
|
||||
"fmt"
|
||||
"log"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
@ -13,312 +12,9 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
|
||||
// Recurse into structure, returning reflect.Value of wanted field.
|
||||
// Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
func getStructFieldValue(parentStruct interface{}, fieldName string) (*reflect.Value, string, error) {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
/* if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
*/
|
||||
if false {
|
||||
for i := 0 ; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if f.Kind() == reflect.String {
|
||||
fmt.Printf("%v=%v\n", v.Type().Field(i).Name, f.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(fieldName, ".") {
|
||||
fs := strings.Split(fieldName, ".")
|
||||
//f := v.FieldByName(fs[0])
|
||||
f := v.Elem().FieldByName(fs[0])
|
||||
if f.Kind() == reflect.Struct {
|
||||
return getStructFieldValue(f.Interface(), strings.Join(fs[1:], "."))
|
||||
} else {
|
||||
log.Fatalln(fmt.Sprintf("%s is not a struct: %s\n", fs[0], f.Kind().String()))
|
||||
}
|
||||
} else {
|
||||
f := v.FieldByName(fieldName)
|
||||
if f.IsValid() {
|
||||
return &f, fieldName, nil
|
||||
} else {
|
||||
return &v, fieldName, errors.New(fmt.Sprintf("Field not found: %s", fieldName))
|
||||
}
|
||||
}
|
||||
|
||||
return &v, fieldName, nil
|
||||
}
|
||||
|
||||
|
||||
// TODO : Replace by getStructFieldValue
|
||||
// Recurse into structure, returning reflect.Value of wanted field.
|
||||
// Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
func getStructField(parentStruct interface{}, fieldName string) (reflect.Value, string) {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if false {
|
||||
for i := 0 ; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if f.Kind() == reflect.String {
|
||||
fmt.Printf("%v=%v\n", v.Type().Field(i).Name, f.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(fieldName, ".") {
|
||||
fs := strings.Split(fieldName, ".")
|
||||
f := v.FieldByName(fs[0])
|
||||
if f.Kind() == reflect.Struct {
|
||||
return getStructField(f.Interface(), strings.Join(fs[1:], "."))
|
||||
} else {
|
||||
log.Fatalln(fmt.Sprintf("%s is not a struct: %s\n", fs[0], f.Kind().String()))
|
||||
}
|
||||
}
|
||||
|
||||
return v, fieldName
|
||||
}
|
||||
|
||||
|
||||
/* Pretty display of jails field
|
||||
Fields to show are given in a string array parameter
|
||||
Ex. : displayJails(["Name", "JID", "RootPath"])
|
||||
*/
|
||||
func displayStructFields(jails []Jail, valsToDisplay []string) {
|
||||
/* A line is defined by :
|
||||
Nr of fields
|
||||
For each field :
|
||||
Its name
|
||||
Its max length
|
||||
Its value
|
||||
*/
|
||||
type Field struct {
|
||||
Name string
|
||||
MaxLen int
|
||||
Value string
|
||||
}
|
||||
|
||||
type Line []Field
|
||||
|
||||
type Output []Line
|
||||
var out Output
|
||||
|
||||
//fmt.Printf("%d fields in a %d items structure\n", len(valsToDisplay), len(jails))
|
||||
|
||||
// Browse structure to get max length and values
|
||||
for _, j := range jails {
|
||||
// Have to use a pointer, else reflect.Value.Elem() will panic : https://pkg.go.dev/reflect#Value.Elem
|
||||
tj := &j
|
||||
|
||||
line := make([]Field, len(valsToDisplay))
|
||||
for i, f := range valsToDisplay {
|
||||
a, f := getStructField(tj, f)
|
||||
|
||||
field := Field {
|
||||
Name: f,
|
||||
}
|
||||
if a.FieldByName(f).IsValid() {
|
||||
// For now this just contains this item length, will adjust later
|
||||
// We need to divide length by number of items in string fields (because we can have more than 1 ip4_addr)
|
||||
if reflect.TypeOf(a.FieldByName(f).Interface()).Kind() == reflect.String {
|
||||
itnr := len(strings.Split(string(a.FieldByName(f).Interface().(string)), ","))
|
||||
field.MaxLen = len(fmt.Sprintf("%v", a.FieldByName(f).Interface())) / itnr
|
||||
} else {
|
||||
field.MaxLen = len(fmt.Sprintf("%v", a.FieldByName(f).Interface()))
|
||||
}
|
||||
field.Value = fmt.Sprintf("%v", a.FieldByName(f).Interface())
|
||||
} else {
|
||||
fmt.Printf("Invalid field name: %s\n", f)
|
||||
}
|
||||
line[i] = field
|
||||
|
||||
}
|
||||
out = append(out, line)
|
||||
}
|
||||
|
||||
if len(out) == 0 {
|
||||
fmt.Printf("Nothing to see here!\n")
|
||||
return
|
||||
}
|
||||
|
||||
// Get real maximum length
|
||||
maxlen := make([]int, len(valsToDisplay))
|
||||
for i := 0; i< len(valsToDisplay); i++ {
|
||||
maxlen[i] = len(valsToDisplay[i])
|
||||
}
|
||||
for _, l := range out {
|
||||
for i, f := range l {
|
||||
if f.MaxLen > maxlen[i] {
|
||||
maxlen[i] = f.MaxLen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Align maxlen to the real maximum length
|
||||
for io, l := range out {
|
||||
for ii, _ := range l {
|
||||
// We need to access slice by index if we want to modify content
|
||||
out[io][ii].MaxLen = maxlen[ii]
|
||||
}
|
||||
}
|
||||
|
||||
totalLen := 0
|
||||
// For each field, add separator and 2 blank spaces
|
||||
for _, f := range out[0] {
|
||||
totalLen += f.MaxLen + 3
|
||||
}
|
||||
// Then add starting delimiter
|
||||
totalLen += 1
|
||||
|
||||
Debug := false
|
||||
if Debug == true {
|
||||
for _, f := range out[0] {
|
||||
fmt.Printf("%s max length : %d\n", f.Name, f.MaxLen)
|
||||
}
|
||||
}
|
||||
|
||||
// Lets draw things on the screen!
|
||||
// First, headers: 1st separator line
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("=") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
|
||||
// Column names
|
||||
for i, f := range out[0] {
|
||||
if i == 0 {
|
||||
fmt.Printf("|")
|
||||
}
|
||||
/* Use vlsToDisplay to get real name (with "Config.")
|
||||
fmt.Printf(" %s", f.Name)
|
||||
for i := len(f.Name)+1 ; i < f.MaxLen+1 ; i++ { */
|
||||
fmt.Printf(" %s", valsToDisplay[i])
|
||||
for i := len(valsToDisplay[i])+1 ; i < f.MaxLen+1 ; i++ {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf(" |")
|
||||
}
|
||||
// Finally separator line
|
||||
fmt.Printf("\n")
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("=") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
// Then display data
|
||||
// Loop through lines
|
||||
for _, l := range out {
|
||||
|
||||
// Loop through fields
|
||||
// In case we need to add a line for a 2nd IP, or whatever object
|
||||
var supplines = make(map[string]string)
|
||||
for i, f := range l {
|
||||
if i == 0 {
|
||||
fmt.Printf("|")
|
||||
}
|
||||
// Special cases of value displaying
|
||||
if f.Name == "JID" && f.Value == "0" {
|
||||
fmt.Printf(" ")
|
||||
} else if f.Name == "Ip4_addr" {
|
||||
ia := strings.Split(f.Value, ",")
|
||||
// If we have more than 1 value we need to finish this line, and store value for writing at the end of line loop
|
||||
for i, inter := range ia {
|
||||
if i > 0 {
|
||||
supplines[f.Name] = inter
|
||||
} else {
|
||||
fmt.Printf(" %s", inter)
|
||||
}
|
||||
}
|
||||
//fmt.Printf(" %s", strings.Split(strings.Split(f.Value, "|")[1], "/")[0])
|
||||
} else {
|
||||
fmt.Printf(" %s", f.Value)
|
||||
}
|
||||
// Complete with spaces to the max length
|
||||
for i := len(f.Value)+1 ; i < f.MaxLen+1 ; i++ {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf(" |")
|
||||
}
|
||||
// Draw supplementary lines
|
||||
if len(supplines) > 0 {
|
||||
for i, f := range l {
|
||||
if i == 0 {
|
||||
fmt.Printf("\n|")
|
||||
}
|
||||
// Overwrite value in this scope
|
||||
v, exists := supplines[f.Name]
|
||||
if exists {
|
||||
fmt.Printf(" %s", v)
|
||||
} else {
|
||||
// 1st option : Do not redisplay precedent line values
|
||||
fmt.Printf(" ")
|
||||
// 2nd option : Redisplay precedenet line values
|
||||
//fmt.Printf(" %s", f.Value)
|
||||
}
|
||||
// Complete with spaces to the max length
|
||||
for i := len(v)+1 ; i < f.MaxLen+1 ; i++ {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf(" |")
|
||||
}
|
||||
}
|
||||
// Draw line separator between jails
|
||||
if !gNoLineSep {
|
||||
fmt.Printf("\n")
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("-") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
if gNoLineSep {
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("-") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
/*
|
||||
* Display struct attributes name for a given struct.
|
||||
* Recurse into struct attributes of type struct
|
||||
* Used to show user jail properties
|
||||
*/
|
||||
func getStructFieldNames(parentStruct interface{}, result []string, prefix string) []string {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
for i := 0 ; i < v.NumField() ; i++ {
|
||||
if v.Type().Field(i).Type.Kind() == reflect.Struct {
|
||||
result = getStructFieldNames(v.Field(i).Interface(), result, v.Type().Field(i).Name)
|
||||
} else {
|
||||
if len(prefix) > 0 {
|
||||
result = append(result, fmt.Sprintf("%s.%s", prefix, v.Type().Field(i).Name))
|
||||
} else {
|
||||
result = append(result, v.Type().Field(i).Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* List all properties a jail have, with their internal name
|
||||
*******************************************************************************/
|
||||
func ListJailsProps(args []string) {
|
||||
var conf Jail
|
||||
var jailconf JailConfig
|
||||
@ -333,7 +29,10 @@ func ListJailsProps(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Get Jails from datastores. Store config and running metadata into gJails global var */
|
||||
/********************************************************************************
|
||||
* Get Jails from datastores. Store config and running metadata
|
||||
* into gJails global var
|
||||
*******************************************************************************/
|
||||
func ListJails(args []string, display bool) {
|
||||
fields := strings.Split(gDisplayColumns, ",")
|
||||
|
||||
@ -344,9 +43,9 @@ func ListJails(args []string, display bool) {
|
||||
// This is the structure we will filter, then display
|
||||
var jails []Jail
|
||||
|
||||
/************************************************************************************
|
||||
/***************************************************************
|
||||
/ Filter jails with "filter" options
|
||||
/***********************************************************************************/
|
||||
/**************************************************************/
|
||||
if len(gFilterJails) > 0 && gFilterJails != "none" {
|
||||
flts := make(map[string]string)
|
||||
for _, flt := range strings.Split(gFilterJails, ",") {
|
||||
@ -378,9 +77,9 @@ func ListJails(args []string, display bool) {
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
/***************************************************************
|
||||
/ Filter jails by names given on command line
|
||||
/***********************************************************************************/
|
||||
/**************************************************************/
|
||||
if len(args) > 0 {
|
||||
var js []Jail
|
||||
for _, a := range args {
|
||||
@ -394,10 +93,10 @@ func ListJails(args []string, display bool) {
|
||||
jails = js
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
/***************************************************************
|
||||
/ Sort jails
|
||||
/ We support 3 sort criteria max
|
||||
/***********************************************************************************/
|
||||
/**************************************************************/
|
||||
if len(gSortFields) > 0 && gSortFields != "none" {
|
||||
js := initSortStruct()
|
||||
|
||||
@ -435,9 +134,9 @@ func ListJails(args []string, display bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
/***************************************************************
|
||||
/ Finally, display jails
|
||||
/***********************************************************************************/
|
||||
/**************************************************************/
|
||||
if display {
|
||||
displayStructFields(jails, fields)
|
||||
}
|
||||
|
326
cmd/utils.go
326
cmd/utils.go
@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"bufio"
|
||||
"errors"
|
||||
@ -104,9 +105,9 @@ func getFstab(path string) ([]Mount, error) {
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Get a specific jail source reference, to update properties after a range loop
|
||||
*****************************************************************************/
|
||||
/********************************************************************************
|
||||
* Get a specific jail source reference, to update properties after a range loop
|
||||
*******************************************************************************/
|
||||
func getJailFromArray(internalName string, jarray []Jail) (*Jail, error) {
|
||||
for _, j := range jarray {
|
||||
if internalName == j.InternalName {
|
||||
@ -116,11 +117,10 @@ func getJailFromArray(internalName string, jarray []Jail) (*Jail, error) {
|
||||
return &Jail{}, errors.New("Jail not found")
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
// Recurse into structure, returning reflect.Kind of named field.
|
||||
// Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
/********************************************************************************
|
||||
* Recurse into structure, returning reflect.Kind of named field.
|
||||
* Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
*******************************************************************************/
|
||||
func getStructFieldKind(parentStruct interface{}, fieldName string) (reflect.Kind, string, error) {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
@ -158,6 +158,316 @@ func getStructFieldKind(parentStruct interface{}, fieldName string) (reflect.Kin
|
||||
return reflect.Kind(0), fieldName, errors.New(fmt.Sprintf("Field not found: %s", fieldName))
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Display struct attributes name for a given struct.
|
||||
* Recurse into struct attributes of type struct
|
||||
* Used to show user jail properties
|
||||
*******************************************************************************/
|
||||
func getStructFieldNames(parentStruct interface{}, result []string, prefix string) []string {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
for i := 0 ; i < v.NumField() ; i++ {
|
||||
if v.Type().Field(i).Type.Kind() == reflect.Struct {
|
||||
result = getStructFieldNames(v.Field(i).Interface(), result, v.Type().Field(i).Name)
|
||||
} else {
|
||||
if len(prefix) > 0 {
|
||||
result = append(result, fmt.Sprintf("%s.%s", prefix, v.Type().Field(i).Name))
|
||||
} else {
|
||||
result = append(result, v.Type().Field(i).Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Recurse into structure, returning reflect.Value of wanted field.
|
||||
* Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
*******************************************************************************/
|
||||
func getStructFieldValue(parentStruct interface{}, fieldName string) (*reflect.Value, string, error) {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
/* if v.Kind() == reflect.Ptr {
|
||||
* v = v.Elem()
|
||||
}
|
||||
*/
|
||||
if false {
|
||||
for i := 0 ; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if f.Kind() == reflect.String {
|
||||
fmt.Printf("%v=%v\n", v.Type().Field(i).Name, f.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(fieldName, ".") {
|
||||
fs := strings.Split(fieldName, ".")
|
||||
//f := v.FieldByName(fs[0])
|
||||
f := v.Elem().FieldByName(fs[0])
|
||||
if f.Kind() == reflect.Struct {
|
||||
return getStructFieldValue(f.Interface(), strings.Join(fs[1:], "."))
|
||||
} else {
|
||||
log.Fatalln(fmt.Sprintf("%s is not a struct: %s\n", fs[0], f.Kind().String()))
|
||||
}
|
||||
} else {
|
||||
f := v.FieldByName(fieldName)
|
||||
if f.IsValid() {
|
||||
return &f, fieldName, nil
|
||||
} else {
|
||||
return &v, fieldName, errors.New(fmt.Sprintf("Field not found: %s", fieldName))
|
||||
}
|
||||
}
|
||||
|
||||
return &v, fieldName, nil
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
* TODO : Replace by getStructFieldValue
|
||||
* Recurse into structure, returning reflect.Value of wanted field.
|
||||
* Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
*******************************************************************************/
|
||||
func getStructField(parentStruct interface{}, fieldName string) (reflect.Value, string) {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if false {
|
||||
for i := 0 ; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if f.Kind() == reflect.String {
|
||||
fmt.Printf("%v=%v\n", v.Type().Field(i).Name, f.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(fieldName, ".") {
|
||||
fs := strings.Split(fieldName, ".")
|
||||
f := v.FieldByName(fs[0])
|
||||
if f.Kind() == reflect.Struct {
|
||||
return getStructField(f.Interface(), strings.Join(fs[1:], "."))
|
||||
} else {
|
||||
log.Fatalln(fmt.Sprintf("%s is not a struct: %s\n", fs[0], f.Kind().String()))
|
||||
}
|
||||
}
|
||||
|
||||
return v, fieldName
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
* Pretty display of jails field
|
||||
* Fields to show are given in a string array parameter
|
||||
* Ex. : displayJails(["Name", "JID", "RootPath"])
|
||||
*******************************************************************************/
|
||||
func displayStructFields(jails []Jail, valsToDisplay []string) {
|
||||
/* A line is defined by :
|
||||
* Nr of fields
|
||||
* For each field :
|
||||
* Its name
|
||||
* Its max length
|
||||
* Its value
|
||||
*/
|
||||
type Field struct {
|
||||
Name string
|
||||
MaxLen int
|
||||
Value string
|
||||
}
|
||||
|
||||
type Line []Field
|
||||
|
||||
type Output []Line
|
||||
var out Output
|
||||
|
||||
//fmt.Printf("%d fields in a %d items structure\n", len(valsToDisplay), len(jails))
|
||||
|
||||
// Browse structure to get max length and values
|
||||
for _, j := range jails {
|
||||
// Have to use a pointer, else reflect.Value.Elem() will panic : https://pkg.go.dev/reflect#Value.Elem
|
||||
tj := &j
|
||||
|
||||
line := make([]Field, len(valsToDisplay))
|
||||
for i, f := range valsToDisplay {
|
||||
a, f := getStructField(tj, f)
|
||||
|
||||
field := Field {
|
||||
Name: f,
|
||||
}
|
||||
if a.FieldByName(f).IsValid() {
|
||||
// For now this just contains this item length, will adjust later
|
||||
// We need to divide length by number of items in string fields (because we can have more than 1 ip4_addr)
|
||||
if reflect.TypeOf(a.FieldByName(f).Interface()).Kind() == reflect.String {
|
||||
itnr := len(strings.Split(string(a.FieldByName(f).Interface().(string)), ","))
|
||||
field.MaxLen = len(fmt.Sprintf("%v", a.FieldByName(f).Interface())) / itnr
|
||||
} else {
|
||||
field.MaxLen = len(fmt.Sprintf("%v", a.FieldByName(f).Interface()))
|
||||
}
|
||||
field.Value = fmt.Sprintf("%v", a.FieldByName(f).Interface())
|
||||
} else {
|
||||
fmt.Printf("Invalid field name: %s\n", f)
|
||||
}
|
||||
line[i] = field
|
||||
|
||||
}
|
||||
out = append(out, line)
|
||||
}
|
||||
|
||||
if len(out) == 0 {
|
||||
fmt.Printf("Nothing to see here!\n")
|
||||
return
|
||||
}
|
||||
|
||||
// Get real maximum length
|
||||
maxlen := make([]int, len(valsToDisplay))
|
||||
for i := 0; i< len(valsToDisplay); i++ {
|
||||
maxlen[i] = len(valsToDisplay[i])
|
||||
}
|
||||
for _, l := range out {
|
||||
for i, f := range l {
|
||||
if f.MaxLen > maxlen[i] {
|
||||
maxlen[i] = f.MaxLen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Align maxlen to the real maximum length
|
||||
for io, l := range out {
|
||||
for ii, _ := range l {
|
||||
// We need to access slice by index if we want to modify content
|
||||
out[io][ii].MaxLen = maxlen[ii]
|
||||
}
|
||||
}
|
||||
|
||||
totalLen := 0
|
||||
// For each field, add separator and 2 blank spaces
|
||||
for _, f := range out[0] {
|
||||
totalLen += f.MaxLen + 3
|
||||
}
|
||||
// Then add starting delimiter
|
||||
totalLen += 1
|
||||
|
||||
Debug := false
|
||||
if Debug == true {
|
||||
for _, f := range out[0] {
|
||||
fmt.Printf("%s max length : %d\n", f.Name, f.MaxLen)
|
||||
}
|
||||
}
|
||||
|
||||
// Lets draw things on the screen!
|
||||
// First, headers: 1st separator line
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("=") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
|
||||
// Column names
|
||||
for i, f := range out[0] {
|
||||
if i == 0 {
|
||||
fmt.Printf("|")
|
||||
}
|
||||
/* Use vlsToDisplay to get real name (with "Config.")
|
||||
* fmt.Printf(" %s", f.Name)
|
||||
* for i := len(f.Name)+1 ; i < f.MaxLen+1 ; i++ { */
|
||||
fmt.Printf(" %s", valsToDisplay[i])
|
||||
for i := len(valsToDisplay[i])+1 ; i < f.MaxLen+1 ; i++ {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf(" |")
|
||||
}
|
||||
// Finally separator line
|
||||
fmt.Printf("\n")
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("=") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
// Then display data
|
||||
// Loop through lines
|
||||
for _, l := range out {
|
||||
|
||||
// Loop through fields
|
||||
// In case we need to add a line for a 2nd IP, or whatever object
|
||||
var supplines = make(map[string]string)
|
||||
for i, f := range l {
|
||||
if i == 0 {
|
||||
fmt.Printf("|")
|
||||
}
|
||||
// Special cases of value displaying
|
||||
if f.Name == "JID" && f.Value == "0" {
|
||||
fmt.Printf(" ")
|
||||
} else if f.Name == "Ip4_addr" {
|
||||
ia := strings.Split(f.Value, ",")
|
||||
// If we have more than 1 value we need to finish this line, and store value for writing at the end of line loop
|
||||
for i, inter := range ia {
|
||||
if i > 0 {
|
||||
supplines[f.Name] = inter
|
||||
} else {
|
||||
fmt.Printf(" %s", inter)
|
||||
}
|
||||
}
|
||||
//fmt.Printf(" %s", strings.Split(strings.Split(f.Value, "|")[1], "/")[0])
|
||||
} else {
|
||||
fmt.Printf(" %s", f.Value)
|
||||
}
|
||||
// Complete with spaces to the max length
|
||||
for i := len(f.Value)+1 ; i < f.MaxLen+1 ; i++ {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf(" |")
|
||||
}
|
||||
// Draw supplementary lines
|
||||
if len(supplines) > 0 {
|
||||
for i, f := range l {
|
||||
if i == 0 {
|
||||
fmt.Printf("\n|")
|
||||
}
|
||||
// Overwrite value in this scope
|
||||
v, exists := supplines[f.Name]
|
||||
if exists {
|
||||
fmt.Printf(" %s", v)
|
||||
} else {
|
||||
// 1st option : Do not redisplay precedent line values
|
||||
fmt.Printf(" ")
|
||||
// 2nd option : Redisplay precedenet line values
|
||||
//fmt.Printf(" %s", f.Value)
|
||||
}
|
||||
// Complete with spaces to the max length
|
||||
for i := len(v)+1 ; i < f.MaxLen+1 ; i++ {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf(" |")
|
||||
}
|
||||
}
|
||||
// Draw line separator between jails
|
||||
if !gNoLineSep {
|
||||
fmt.Printf("\n")
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("-") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
if gNoLineSep {
|
||||
for i, f := range out[0] {
|
||||
if i == 0 { fmt.Printf("+") }
|
||||
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("-") }
|
||||
fmt.Printf("+")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user