diff --git a/cmd/collect.go b/cmd/collect.go index e43e083..472b32d 100644 --- a/cmd/collect.go +++ b/cmd/collect.go @@ -161,8 +161,8 @@ func init() { checkBindFlagError(viper.BindPFlag("collect.output", CollectCmd.Flags().Lookup("output"))) checkBindFlagError(viper.BindPFlag("collect.force-update", CollectCmd.Flags().Lookup("force-update"))) checkBindFlagError(viper.BindPFlag("collect.cacert", CollectCmd.Flags().Lookup("cacert"))) - checkBindFlagError(viper.BindPFlags(CollectCmd.Flags())) checkBindFlagError(viper.BindPFlag("collect.use-hive", CollectCmd.Flags().Lookup("use-hive"))) + checkBindFlagError(viper.BindPFlags(CollectCmd.Flags())) rootCmd.AddCommand(CollectCmd) } diff --git a/cmd/root.go b/cmd/root.go index d073c18..11d30ee 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -26,6 +26,11 @@ import ( "github.com/spf13/viper" ) +const ( + FORMAT_JSON = "json" + FORMAT_YAML = "yaml" +) + var ( currentUser *user.User accessToken string diff --git a/cmd/send.go b/cmd/send.go index e7897be..d9a6ca0 100644 --- a/cmd/send.go +++ b/cmd/send.go @@ -3,18 +3,21 @@ package cmd import ( "crypto/x509" "encoding/json" + "fmt" "net/http" "os" - "strings" urlx "github.com/OpenCHAMI/magellan/internal/url" "github.com/OpenCHAMI/magellan/pkg/auth" "github.com/OpenCHAMI/magellan/pkg/client" "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "gopkg.in/yaml.v3" ) -var sendData []string +var ( + sendDataArgs []string +) var sendCmd = &cobra.Command{ Use: "send [host]", @@ -28,9 +31,37 @@ var sendCmd = &cobra.Command{ // concatenate all of the data from `-d` flag to send var ( smdClient = &client.SmdClient{Client: &http.Client{}} - inputData = []byte(strings.Join(sendData, "\n")) + inputData []byte ) + // load data either from file or directly from args + for _, dataArg := range sendDataArgs { + // determine if we're reading from file + if len(dataArg) > 0 { + // load from file + if dataArg[0] == '@' { + var ( + path string = dataArg[1:] + contents []byte + err error + ) + contents, err = os.ReadFile(path) + if err != nil { + log.Error().Err(err).Str("path", path).Msg("failed to read file") + continue + } + inputData = append(inputData, []byte(contents)...) + fmt.Println("file:\n", string(contents)) + } else { + // read data directly + inputData = append(inputData, []byte(dataArg)...) + fmt.Println("data:\n", string(dataArg)) + } + } else { + continue + } + } + // try to load access token either from env var, file, or config if var not set if accessToken == "" { var err error @@ -57,23 +88,30 @@ var sendCmd = &cobra.Command{ headers.Authorization(accessToken) headers.ContentType("application/json") - // unmarshal into map - data := map[string]any{} - err := json.Unmarshal(inputData, &data) - if err != nil { - log.Error().Err(err).Msg("failed to unmarshal data to make request") + // unmarshal into map with specified format + var ( + data = map[string]any{} + err error + ) + switch format { + case "json": + // NOTE: no need to convert if data is already in JSON + case "yaml": + inputData, err = yamlToJson(inputData) + if err != nil { + log.Error().Err(err) + } } for _, host := range args { host, err := urlx.Sanitize(host) if err != nil { - log.Error().Err(err).Msg("failed to sanitize host") + log.Warn().Err(err).Str("host", host).Msg("could not sanitize host") } smdClient.URI = host err = smdClient.Add(inputData, headers) if err != nil { - // try updating instead if forceUpdate { smdClient.Xname = data["ID"].(string) @@ -90,9 +128,31 @@ var sendCmd = &cobra.Command{ } func init() { - sendCmd.Flags().StringSliceVarP(&sendData, "data", "d", []string{}, "Set the data to send to specified host.") + sendCmd.Flags().StringSliceVarP(&sendDataArgs, "data", "d", []string{}, "Set the data in to send to specified host.") + sendCmd.Flags().StringVarP(&format, "format", "F", "json", "Set the data input format. (json|yaml)") sendCmd.Flags().BoolVarP(&forceUpdate, "force-update", "f", false, "Set flag to force update data sent to SMD.") sendCmd.Flags().StringVar(&cacertPath, "cacert", "", "Set the path to CA cert file. (defaults to system CAs when blank)") rootCmd.AddCommand(sendCmd) } + +func yamlToJson(input []byte) ([]byte, error) { + var ( + data map[string]any + output []byte + err error + ) + + // unmarshal YAML contents into map + err = yaml.Unmarshal(input, &data) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal YAML input data") + } + + // marshal map into JSON + output, err = json.Marshal(data) + if err != nil { + return nil, fmt.Errorf("failed to marshal input data to JSON: %v", err) + } + return output, nil +}