Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var AttributesCmd = &cobra.Command{ Use: "attributes " + strings.Join(validArgs, "|"), Args: validateAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), ValidArgs: validArgs, Short: "List Hermes attributes", PreRunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.Flags()); err != nil { return err } return verifyGlobalFlags(nil) }, RunE: func(cmd *cobra.Command, args []string) error { client, err := NewHermesV1Client(cmd.Context()) if err != nil { return fmt.Errorf("failed to create Hermes client: %w", err) } format := viper.GetString("format") projectID := viper.GetString("project-id") if viper.GetBool("all-projects") { projectID = "*" } listOpts := attributes.ListOpts{ Limit: viper.GetInt("limit"), MaxDepth: viper.GetInt("max-depth"), ProjectID: projectID, } var allAttributes []string for _, name := range args { err = attributes.List(client, name, listOpts).EachPage(cmd.Context(), func(ctx context.Context, page pagination.Page) (bool, error) { attrs, err := attributes.ExtractAttributes(page) if err != nil { return false, fmt.Errorf("failed to extract attributes: %w", err) } allAttributes = append(allAttributes, attrs...) return true, nil }) if err != nil { if gophercloud.ResponseCodeIs(err, http.StatusInternalServerError) { return fmt.Errorf(`failed to list attributes: %w: please try to decrease the amount of the attributes in output, e.g. set "--limit 100"`, err) } return fmt.Errorf("failed to list attributes: %w", err) } } switch format { case "json": jsonAttrs, err := json.MarshalIndent(allAttributes, "", " ") if err != nil { return err } fmt.Printf("%s\n", jsonAttrs) case "yaml": yamlAttrs, err := yaml.Marshal(allAttributes) if err != nil { return err } fmt.Printf("%s", yamlAttrs) case "csv", "value", "table": fmt.Printf("%s\n", strings.Join(allAttributes, "\n")) default: return fmt.Errorf("unsupported format: %s", format) } return nil }, }
AttributesCmd represents the list command
var ExportCmd = &cobra.Command{ Use: "export", Args: cobra.ExactArgs(0), Short: "Export Hermes events to Swift", Long: `Export Hermes events to Swift storage container. Exports can be saved in different formats (json, csv, yaml) for further processing or archival.`, PreRunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.Flags()); err != nil { return fmt.Errorf("failed to bind flags: %w", err) } if viper.GetString("container") == "" { return errors.New("container name is required") } _, err := parseExportFormat(viper.GetString("format")) if err != nil { return err } return verifyGlobalFlags(defaultListKeyOrder) }, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() if viper.GetInt("limit") > maxOffset { fmt.Fprintf(os.Stderr, "Warning: Exporting more than %d events may take a long time.\n\n", maxOffset) } client, err := NewHermesV1Client(ctx) if err != nil { return fmt.Errorf("failed to create Hermes client: %w", err) } fmt.Fprintf(os.Stderr, "Fetching events...\n") var allEvents []events.Event var bar *pb.ProgressBar logg.Debug("fetching events matching specified criteria") listOpts := buildListOpts() if err = getEvents(ctx, client, &allEvents, listOpts, viper.GetInt("limit"), true, &bar); err != nil { if bar != nil { bar.Finish() } return fmt.Errorf("failed to list events: %w", err) } if bar != nil { bar.Finish() } if len(allEvents) == 0 { return errors.New("no events found matching the specified criteria") } fmt.Fprintf(os.Stderr, "\nFound %d events to export\n", len(allEvents)) fmt.Fprintf(os.Stderr, "Converting to %s format...\n", viper.GetString("format")) var buf bytes.Buffer if err = convertToRequestedFormat(&buf, allEvents, viper.GetString("format")); err != nil { return fmt.Errorf("failed to convert events: %w", err) } dataSize := float64(buf.Len()) / 1024 / 1024 fmt.Fprintf(os.Stderr, "Uploading %.1fMB to Swift...\n", dataSize) uploadBar := pb.Full.Start64(int64(buf.Len())) uploadBar.Set(pb.Bytes, true) uploadBar.Set(pb.Terminal, true) uploadBar.SetWidth(0) defer uploadBar.Finish() progressReader := &progressReader{ Reader: &buf, Bar: uploadBar, } container, err := InitializeSwiftContainer( ctx, client.ProviderClient, viper.GetString("container"), ) if err != nil { return fmt.Errorf("failed to initialize Swift container: %w", err) } // Use hyphenated timestamp format for safe and sortable filenames const timeFormat = "2006-01-02-150405" filename := viper.GetString("filename") if filename == "" { filename = "hermes-export-" + time.Now().Format(timeFormat) } format, err := parseExportFormat(viper.GetString("format")) if err != nil { return fmt.Errorf("invalid format: %w", err) } exportFile := ExportFile{ Format: format, FileName: filename, SegmentSize: uint64(viper.GetInt("segment-size")) * 1024 * 1024, Contents: progressReader, } if err := exportFile.UploadTo(ctx, container); err != nil { return fmt.Errorf("failed to upload to Swift: %w", err) } fmt.Fprintf(os.Stderr, "\nSuccessfully exported %d events\n", len(allEvents)) return nil }, }
ExportCmd represents the export command
var ListCmd = &cobra.Command{ Use: "list", Args: cobra.ExactArgs(0), Short: "List Hermes events", PreRunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.Flags()); err != nil { return err } teq := viper.GetString("time") tgt := viper.GetString("time-start") tlt := viper.GetString("time-end") if teq != "" && !(tgt == "" && tlt == "") { return errors.New("cannot combine time flag with time-start or time-end flags") } return verifyGlobalFlags(defaultListKeyOrder) }, RunE: func(cmd *cobra.Command, args []string) error { userLimit := viper.GetInt("limit") keyOrder := viper.GetStringSlice("column") if len(keyOrder) == 0 { keyOrder = defaultListKeyOrder } format := viper.GetString("format") projectID := viper.GetString("project-id") if viper.GetBool("all-projects") { projectID = "*" } listOpts := events.ListOpts{ Limit: maxOffset, TargetType: viper.GetString("target-type"), TargetID: viper.GetString("target-id"), InitiatorID: viper.GetString("initiator-id"), InitiatorName: viper.GetString("initiator-name"), Action: viper.GetString("action"), Outcome: viper.GetString("outcome"), RequestPath: viper.GetString("request-path"), ObserverType: viper.GetString("source"), Search: viper.GetString("search"), ProjectID: projectID, Sort: strings.Join(viper.GetStringSlice("sort"), ","), } if userLimit > 0 && userLimit <= maxOffset { listOpts.Limit = userLimit } if t := viper.GetString("time"); t != "" { rt, err := parseTime(t) if err != nil { return fmt.Errorf("failed to parse time: %w", err) } listOpts.Time = []events.DateQuery{ { Date: rt, }, } } if t := viper.GetString("time-start"); t != "" { rt, err := parseTime(t) if err != nil { return fmt.Errorf("failed to parse time-start: %w", err) } listOpts.Time = append(listOpts.Time, events.DateQuery{ Date: rt, Filter: events.DateFilterGTE, }) } if t := viper.GetString("time-end"); t != "" { rt, err := parseTime(t) if err != nil { return fmt.Errorf("failed to parse time-end: %w", err) } listOpts.Time = append(listOpts.Time, events.DateQuery{ Date: rt, Filter: events.DateFilterLTE, }) } client, err := NewHermesV1Client(cmd.Context()) if err != nil { return fmt.Errorf("failed to create Hermes client: %w", err) } var allEvents []events.Event var bar *pb.ProgressBar if err = getEvents(cmd.Context(), client, &allEvents, listOpts, userLimit, viper.GetBool("over-10k-fix"), &bar); err != nil { if bar != nil { bar.Finish() } return fmt.Errorf("failed to list the events: %w", err) } if bar != nil { bar.Finish() } if format == "table" { var buf bytes.Buffer table := tablewriter.NewWriter(&buf) table.SetColWidth(20) table.SetAlignment(3) table.SetHeader(keyOrder) for _, v := range allEvents { kv := eventToKV(v) tableRow := []string{} for _, k := range keyOrder { v := kv[k] tableRow = append(tableRow, v) } table.Append(tableRow) } table.Render() fmt.Print(buf.String()) } else { return printEvent(allEvents, format, keyOrder) } return nil }, }
ListCmd represents the list command
var RootCmd = &cobra.Command{ Use: "hermescli", Short: "Hermes CLI tool", SilenceUsage: true, }
RootCmd represents the base command when called without any subcommands
var ShowCmd = &cobra.Command{ Use: "show <event-id> [<event-id>...]", Args: cobra.MinimumNArgs(1), Short: "Show Hermes event", PreRunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.Flags()); err != nil { return err } return verifyGlobalFlags(defaultShowKeyOrder) }, RunE: func(cmd *cobra.Command, args []string) error { client, err := NewHermesV1Client(cmd.Context()) if err != nil { return fmt.Errorf("failed to create Hermes client: %w", err) } keyOrder := viper.GetStringSlice("column") if len(keyOrder) == 0 { keyOrder = defaultShowKeyOrder } format := viper.GetString("format") // initialize the progress bar, when multiple events are requested var bar *pb.ProgressBar if len(args) > 1 { bar = pb.New(len(args)) bar.SetWriter(os.Stderr) bar.Start() } projectID := viper.GetString("project-id") if viper.GetBool("all-projects") { projectID = "*" } getOpts := events.GetOpts{ ProjectID: projectID, } var allEvents []events.Event for i, id := range args { if bar != nil { bar.SetCurrent(int64(i + 1)) } event, err := events.Get(cmd.Context(), client, id, getOpts).Extract() if err != nil { log.Printf("[WARNING] Failed to get %s event: %s", id, err) continue } allEvents = append(allEvents, *event) } if bar != nil { bar.Finish() } if format == "table" { for _, event := range allEvents { kv := eventToKV(event) // create table var buf bytes.Buffer table := tablewriter.NewWriter(&buf) table.SetColWidth(20) table.SetAlignment(3) table.SetHeader([]string{"Key", "Value"}) for _, k := range keyOrder { if v, ok := kv[k]; ok { table.Append([]string{k, v}) } } table.Render() fmt.Print(buf.String()) } } else { return printEvent(allEvents, format, keyOrder) } return nil }, }
ShowCmd represents the show command
var Version = "dev"
Functions ¶
func Execute ¶
func Execute()
Execute adds all child commands to the root command sets flags appropriately. This is called by main.main(). It only needs to happen once to the rootCmd.
func InitializeSwiftContainer ¶ added in v0.5.8
func InitializeSwiftContainer(ctx context.Context, provider *gophercloud.ProviderClient, containerName string) (*schwift.Container, error)
InitializeSwiftContainer creates and initializes a Swift container
func NewHermesV1Client ¶
NewHermesV1Client returns a *ServiceClient for making calls to the OpenStack Lyra v1 API. An error will be returned if authentication or client creation was not possible.
Types ¶
type ExportFile ¶ added in v0.5.8
type ExportFile struct {
Format ExportFormat
FileName string
SegmentSize uint64
Contents io.Reader
}
ExportFile represents a file to be exported to Swift storage
type ExportFormat ¶ added in v0.5.8
type ExportFormat string
const ( ExportFormatJSON ExportFormat = "json" ExportFormatYAML ExportFormat = "yaml" ExportFormatCSV ExportFormat = "csv" )