// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package command import ( "encoding/json" "fmt" "os" "strings" flaghelper "github.com/hashicorp/nomad/helper/flags" "github.com/hashicorp/nomad/helper/raftutil" "github.com/hashicorp/nomad/nomad" "github.com/posener/complete" ) type OperatorSnapshotStateCommand struct { Meta } func (c *OperatorSnapshotStateCommand) Help() string { helpText := ` Usage: nomad operator snapshot state [options] Displays a JSON representation of state in the snapshot. To inspect the file "backup.snap": $ nomad operator snapshot state backup.snap Snapshot State Options: -filter Specifies an expression used to filter query results. ` return strings.TrimSpace(helpText) } func (c *OperatorSnapshotStateCommand) AutocompleteFlags() complete.Flags { return complete.Flags{} } func (c *OperatorSnapshotStateCommand) AutocompleteArgs() complete.Predictor { return complete.PredictFiles("*.snap") } func (c *OperatorSnapshotStateCommand) Synopsis() string { return "Displays information about a Nomad snapshot file" } func (c *OperatorSnapshotStateCommand) Name() string { return "operator snapshot state" } func (c *OperatorSnapshotStateCommand) Run(args []string) int { var filterExpr flaghelper.StringFlag flags := c.Meta.FlagSet(c.Name(), FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } flags.Var(&filterExpr, "filter", "") if err := flags.Parse(args); err != nil { c.Ui.Error(fmt.Sprintf("Failed to parse args: %v", err)) return 1 } filter, err := nomad.NewFSMFilter(filterExpr.String()) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid filter expression %q: %s", filterExpr, err)) return 1 } // Check that we either got no filename or exactly one. if len(flags.Args()) != 1 { c.Ui.Error("This command takes one argument: ") c.Ui.Error(commandErrorText(c)) return 1 } path := flags.Args()[0] f, err := os.Open(path) if err != nil { c.Ui.Error(fmt.Sprintf("Error opening snapshot file: %s", err)) return 1 } defer f.Close() state, meta, err := raftutil.RestoreFromArchive(f, filter) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to read archive file: %s", err)) return 1 } sm := raftutil.StateAsMap(state) sm["SnapshotMeta"] = []interface{}{meta} enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") if err := enc.Encode(sm); err != nil { c.Ui.Error(fmt.Sprintf("Failed to encode output: %v", err)) return 1 } return 0 }