Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Label Templates: rework collection of 'hostinfo' data and collected variables #843

Merged
merged 4 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 87 additions & 23 deletions cmd/register/showdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,86 +19,150 @@ package main
import (
"encoding/json"
"fmt"
"sort"

"github.com/rancher/elemental-operator/pkg/dmidecode"
"github.com/rancher/elemental-operator/pkg/hostinfo"
"github.com/rancher/elemental-operator/pkg/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"sigs.k8s.io/yaml"
)

const (
DUMPHW = "hardware"
DUMPSMBIOS = "smbios"
DUMPLEGACY = "legacy"
DUMPSMBIOS = "smbios"
DUMPHOSTINFO = "hostinfo"
FORMATLABELS = "labels"
FORMATJSON = "json"
FORMATJSONCOMPACT = "json-compact"
FORMATYAML = "yaml"
)

func newDumpDataCommand() *cobra.Command {
var raw bool
var format string

cmd := &cobra.Command{
Use: "dumpdata",
Aliases: []string{"dump"},
Short: "Show host data sent during the registration phase",
Long: "Prints to stdout the data sent by the registering client " +
"to the Elemental Operator.\nTakes the type of host data to dump " +
"as argument, be it '" + DUMPHW + "' or '" + DUMPSMBIOS + "'.",
"as argument, be it '" + DUMPHOSTINFO + "' (default), " + DUMPLEGACY +
"' or '" + DUMPSMBIOS + "'.",
Args: cobra.MatchAll(cobra.MaximumNArgs(1), cobra.OnlyValidArgs),
ValidArgs: []string{DUMPHW, DUMPSMBIOS},
ValidArgs: []string{DUMPHOSTINFO, DUMPLEGACY, DUMPSMBIOS},
RunE: func(_ *cobra.Command, args []string) error {
return dumpdata(args, raw)
return dumpdata(args, format, raw)
},
}

viper.AutomaticEnv()
cmd.Flags().BoolVarP(&raw, "raw", "r", false, "dump raw data before conversion to label templates' variables")
cmd.Flags().BoolVarP(&raw, "raw", "r", false, "dump all collected raw data before postprocessing to refine available label templates variables")
_ = viper.BindPFlag("raw", cmd.Flags().Lookup("raw"))

cmd.Flags().StringVarP(&format, "format", "f", FORMATLABELS, "ouput format ['"+FORMATLABELS+"', '"+FORMATYAML+"', '"+FORMATJSON+"', '"+FORMATJSONCOMPACT+"']")
_ = viper.BindPFlag("format", cmd.Flags().Lookup("format"))
return cmd
}

func dumpdata(args []string, raw bool) error {
dataType := "hardware"
func dumpdata(args []string, format string, raw bool) error {
dataType := "hostinfo"
if len(args) > 0 {
dataType = args[0]
}

var hostData interface{}
var mapData map[string]interface{}

switch dataType {
case DUMPHW:
hwData, err := hostinfo.Host()
case DUMPHOSTINFO:
hostData, err := hostinfo.Host()
if err != nil {
log.Fatalf("Cannot retrieve host data: %s", err)
}

if raw {
hostData = hwData
mapData = hostinfo.ExtractFullData(hostData)
} else {
dataMap, err := hostinfo.ExtractLabels(hwData)
if err != nil {
log.Fatalf("Cannot convert host data to labels: %s", err)
}
hostData = dataMap
mapData = hostinfo.ExtractLabels(hostData)
}
case DUMPLEGACY:
hwData, err := hostinfo.Host()
if err != nil {
log.Fatalf("Cannot retrieve host data: %s", err)
}

if raw {
mapData = hostinfo.ExtractFullData(hwData)
} else {
mapData = hostinfo.ExtractLabelsLegacy(hwData)
}
case DUMPSMBIOS:
smbiosData, err := dmidecode.Decode()
if err != nil {
log.Fatalf("Cannot retrieve SMBIOS data: %s", err)
}

hostData = smbiosData

mapData = smbiosData
default:
// Should never happen but manage it anyway
log.Fatalf("Unsupported data type: %s", dataType)
}

jsonData, err := json.MarshalIndent(hostData, "", " ")
var serializedData []byte
var err error

switch format {
case FORMATLABELS:
labels := map2Labels("", mapData)
keys := make([]string, 0, len(labels))
for k := range labels {
keys = append(keys, k)
}
sort.Strings(keys)

for _, k := range keys {
fmt.Printf("%-52s: %q\n", k, labels[k])
}
return nil
case FORMATJSON:
serializedData, err = json.MarshalIndent(mapData, "", " ")
case FORMATJSONCOMPACT:
serializedData, err = json.Marshal(mapData)
case FORMATYAML:
serializedData, err = yaml.Marshal(mapData)
default:
// Should never happen but manage it anyway
log.Fatalf("Unsupported output type: %s", format)
}

if err != nil {
log.Fatalf("Cannot convert host data to json: %s", err)
log.Fatalf("Cannot convert host data to %s: %s", format, err)
}
fmt.Printf("%s\n", string(jsonData))
fmt.Printf("%s\n", string(serializedData))

return nil
}

func map2Labels(rootKey string, data map[string]interface{}) map[string]string {
ret := map[string]string{}

for key, val := range data {
lbl := key
if len(rootKey) > 0 {
lbl = rootKey + "/" + lbl
}
if _, ok := val.(string); ok {
lbl = "${" + lbl + "}"
ret[lbl] = fmt.Sprintf("%s", val)
continue
}
if _, ok := val.(map[string]interface{}); !ok {
continue
}
for k, v := range map2Labels(lbl, val.(map[string]interface{})) {
ret[k] = v
}
}
return ret
}
Loading