diff --git a/cmd/crawl.go b/cmd/crawl.go index 4707999..cd573ed 100644 --- a/cmd/crawl.go +++ b/cmd/crawl.go @@ -3,23 +3,47 @@ package cmd import ( "encoding/json" "fmt" + "log" + "net/url" + "strings" "github.com/OpenCHAMI/magellan/pkg/crawler" "github.com/spf13/cobra" ) var crawlCmd = &cobra.Command{ - Use: "crawl", + Use: "crawl [uri]", + Long: "Crawl a single BMC for inventory information\n" + + "\n" + + "Example:\n" + + " magellan crawl https://bmc.example.com", Short: "Crawl a single BMC for inventory information", + Args: func(cmd *cobra.Command, args []string) error { + // Validate that the only argument is a valid URI + if err := cobra.ExactArgs(1)(cmd, args); err != nil { + return err + } + parsedURI, err := url.ParseRequestURI(args[0]) + if err != nil { + return fmt.Errorf("invalid URI specified: %s", args[0]) + } + // Remove any trailing slashes + parsedURI.Path = strings.TrimSuffix(parsedURI.Path, "/") + // Collapse any doubled slashes + parsedURI.Path = strings.ReplaceAll(parsedURI.Path, "//", "/") + // Update the URI in the args slice + args[0] = parsedURI.String() + return nil + }, Run: func(cmd *cobra.Command, args []string) { systems, err := crawler.CrawlBMC(crawler.CrawlerConfig{ - URI: cmd.Flag("uri").Value.String(), + URI: args[0], Username: cmd.Flag("username").Value.String(), Password: cmd.Flag("password").Value.String(), Insecure: cmd.Flag("insecure").Value.String() == "true", }) if err != nil { - panic(err) + log.Fatalf("Error crawling BMC: %v", err) } // Marshal the inventory details to JSON jsonData, err := json.MarshalIndent(systems, "", " ") @@ -34,8 +58,7 @@ var crawlCmd = &cobra.Command{ } func init() { - crawlCmd.Flags().StringP("uri", "u", "", "URI of the BMC") - crawlCmd.Flags().StringP("username", "n", "", "Username for the BMC") + crawlCmd.Flags().StringP("username", "u", "", "Username for the BMC") crawlCmd.Flags().StringP("password", "p", "", "Password for the BMC") crawlCmd.Flags().BoolP("insecure", "i", false, "Ignore SSL errors") diff --git a/pkg/crawler/main.go b/pkg/crawler/main.go index d2d5b64..00ee07f 100644 --- a/pkg/crawler/main.go +++ b/pkg/crawler/main.go @@ -2,6 +2,7 @@ package crawler import ( "fmt" + "strings" "github.com/rs/zerolog/log" "github.com/stmcginnis/gofish" @@ -56,6 +57,12 @@ func CrawlBMC(config CrawlerConfig) ([]InventoryDetail, error) { BasicAuth: true, }) if err != nil { + if strings.HasPrefix(err.Error(), "404:") { + err = fmt.Errorf("no ServiceRoot found. This is probably not a BMC: %s", config.URI) + } + if strings.HasPrefix(err.Error(), "401:") { + err = fmt.Errorf("authentication failed. Check your username and password: %s", config.URI) + } event := log.Error() event.Err(err) event.Msg("failed to connect to BMC") @@ -65,6 +72,7 @@ func CrawlBMC(config CrawlerConfig) ([]InventoryDetail, error) { // Obtain the ServiceRoot rf_service := client.GetService() + log.Info().Msgf("found ServiceRoot %s. Redfish Version %s", rf_service.ID, rf_service.RedfishVersion) var rf_systems []*redfish.ComputerSystem