From 3eb7bb5140fa5a4bdbea817b7a02cf8e6b2625af Mon Sep 17 00:00:00 2001 From: Andrii Abramov Date: Mon, 8 Nov 2021 00:22:57 +0200 Subject: [PATCH] add preconditions and emojis --- commands.go | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ goal.yaml | 36 ++++++--------- main.go | 93 ++++++-------------------------------- util.go | 17 +++++++ 4 files changed, 173 insertions(+), 101 deletions(-) create mode 100644 commands.go create mode 100644 util.go diff --git a/commands.go b/commands.go new file mode 100644 index 0000000..da86814 --- /dev/null +++ b/commands.go @@ -0,0 +1,128 @@ +package main + +import ( + "fmt" + "github.com/olekukonko/tablewriter" + "os" + osexec "os/exec" + "strings" +) + +type Assert struct { + Name string `yaml:"name"` + Ref string `yaml:"ref"` + Equals string `yaml:"equals"` +} + +func (a Assert) String() string { + return fmt.Sprintf("Assert{ref:'%s',equals:'%s'}", a.Ref, a.Equals) +} + +type YamlCommand struct { + Cmd string `yaml:"cmd"` + Args []string `yaml:"args"` + Assert *Assert `yaml:"assert"` + Desc string `yaml:"desc"` +} + +type Command struct { + Name string + Cmd string + Args []string + Assert *Assert + Desc string +} + +func (c Command) cli() string { + return fmt.Sprintf("%s %s", c.Cmd, strings.Join(c.Args, " ")) +} + +func (c Command) String() string { + return fmt.Sprintf("Command{name:'%s',cli:'%s',assert:'%s'}", c.Name, c.cli(), c.Assert) +} + +type Commands struct { + commands []Command +} + +func (c *Commands) get(name string) (*Command, bool) { + for _, command := range c.commands { + if command.Name == name { + return &command, true + } + } + return nil, false +} + +func (c *Commands) exec(name string) { + + command, exists := c.get(name) + if exists { + info("⚙️ Exec %s", command.Name) + if command.Assert != nil { + info("⌛ Check precondition: %s", command.Assert.Name) + ref, exists := c.get(command.Assert.Ref) + + if exists { + out := strings.TrimSpace(getOutput(ref)) + if out != command.Assert.Equals { + fatal( + "Precondition failed: %s\n\tOutput: \"%s\"\n\tExpected: \"%s\"\n\tCLI: %s", + ref.Name, + out, + command.Assert.Equals, + ref.cli(), + ) + } else { + info("✅ Precondition: " + command.Assert.Name) + } + } else { + fatal("Unknown assertion ref: %s", command.Assert.Ref) + } + } + + cmd := osexec.Command(command.Cmd, command.Args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err := cmd.Run() + + if err != nil { + info(fmt.Sprint(err)) + // TODO: code from child program + os.Exit(1) + } else { + os.Exit(0) + } + } else { + fatal("No such command in goal.yaml: %s", name) + } + +} + +func (c *Commands) render() { + info("Available commands:") + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Name", "CLI", "Description", "Assertions"}) + table.SetHeaderColor( + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.Bold}, + ) + table.SetColumnColor( + tablewriter.Colors{tablewriter.Bold, tablewriter.FgGreenColor}, + tablewriter.Colors{tablewriter.Normal}, + tablewriter.Colors{tablewriter.Normal}, + tablewriter.Colors{tablewriter.Normal}, + ) + for _, cmd := range c.commands { + assertion := "" + if cmd.Assert != nil { + assertion = cmd.Assert.Name + } + table.Append([]string{cmd.Name, cmd.cli(), cmd.Desc, assertion}) + //fmt.Printf("\t%s: '%s' #%s\n", cmd.Name, cmd.cli(), cmd.Desc) + } + table.Render() +} diff --git a/goal.yaml b/goal.yaml index 4a0df45..92e1d6c 100644 --- a/goal.yaml +++ b/goal.yaml @@ -1,26 +1,16 @@ -start: - cmd: echo - args: - - -n - - 123 - - 456 - desc: starts - -test: - cmd: echo +workspace: + desc: Current terraform workspace + cmd: terraform args: - - Testing! - desc: tests + - workspace + - show -pods: - cmd: kubectl - args: - - get - - pods - - -w - desc: kubectl get pods! [desc] - -wrong: - cmd: qqqwwweee +start: + cmd: terraform + desc: startscho + assert: + name: Check if on dev workspace + ref: workspace + equals: dev1 args: - desc: should fail + - Success diff --git a/main.go b/main.go index e471c02..cbc452b 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,8 @@ package main import ( + "bytes" "errors" - "fmt" - "github.com/olekukonko/tablewriter" "gopkg.in/yaml.v2" "io/ioutil" "os" @@ -11,53 +10,6 @@ import ( "strings" ) -type YamlCommand struct { - Cmd string `yaml:"cmd"` - Args []string `yaml:"args"` - Desc string `yaml:"desc"` -} - -type Command struct { - Name string - Cmd string - Args []string - Desc string -} - -func (c Command) cli() string { - return fmt.Sprintf("%s %s", c.Cmd, strings.Join(c.Args, " ")) -} - -type Commands struct { - commands []Command -} - -func (c *Commands) get(name string) (*Command, bool) { - for _, command := range c.commands { - if command.Name == name { - return &command, true - } - } - return nil, false -} - -func (c *Commands) render() { - fmt.Println("Available commands:") - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Name", "CLI", "Description"}) - table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold}, tablewriter.Colors{tablewriter.Bold}, tablewriter.Colors{tablewriter.Bold}) - table.SetColumnColor( - tablewriter.Colors{tablewriter.Bold, tablewriter.FgGreenColor}, - tablewriter.Colors{tablewriter.Normal}, - tablewriter.Colors{tablewriter.Normal}, - ) - for _, cmd := range c.commands { - table.Append([]string{cmd.Name, cmd.cli(), cmd.Desc}) - //fmt.Printf("\t%s: '%s' #%s\n", cmd.Name, cmd.cli(), cmd.Desc) - } - table.Render() -} - func parseCommands(bytes []byte) (*Commands, error) { rawCommands := map[string]YamlCommand{} err := yaml.Unmarshal(bytes, &rawCommands) @@ -73,10 +25,11 @@ func parseCommands(bytes []byte) (*Commands, error) { args = command.Args } res = append(res, Command{ - Name: name, - Cmd: command.Cmd, - Args: args, - Desc: command.Desc, + Name: name, + Cmd: command.Cmd, + Args: args, + Desc: command.Desc, + Assert: command.Assert, }) } return &Commands{commands: res}, nil @@ -87,12 +40,12 @@ func main() { defaultFilename := "goal.yaml" if _, err := os.Stat(defaultFilename); errors.Is(err, os.ErrNotExist) { - errorFatal("%s does not exist!", defaultFilename) + fatal("%s does not exist!", defaultFilename) } file, err := ioutil.ReadFile("goal.yaml") if err != nil { - errorFatal("Failed to commands from %s file.", defaultFilename) + fatal("Failed to commands from %s file.", defaultFilename) } commands, _ := parseCommands(file) @@ -101,34 +54,18 @@ func main() { } else { // TODO: support several commands name := strings.TrimSpace(os.Args[1]) - command, exists := commands.get(name) - if exists { - exec(command) - } else { - errorFatal("No such command in goal.yaml: %s", name) - } + commands.exec(name) } } -func errorFatal(message string, args ...string) { - msg := fmt.Sprintf(message, args) - _, _ = os.Stderr.WriteString(msg + "\n") - os.Exit(1) -} - -func exec(command *Command) { +func getOutput(command *Command) string { cmd := osexec.Command(command.Cmd, command.Args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + var output bytes.Buffer + cmd.Stdout = &output - err := cmd.Run() + // TODO: handle + _ = cmd.Run() - if err != nil { - fmt.Println(fmt.Sprint(err)) - // TODO: code from child program - os.Exit(1) - } else { - os.Exit(0) - } + return output.String() } diff --git a/util.go b/util.go new file mode 100644 index 0000000..b1b744a --- /dev/null +++ b/util.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + "os" +) + +func fatal(message string, args ...interface{}) { + msg := fmt.Sprintf(message, args...) + _, _ = os.Stderr.WriteString("❗ " + msg + "\n") + os.Exit(1) +} + +func info(message string, args ...interface{}) { + line := fmt.Sprintf(message, args...) + fmt.Printf(line + "\n") +}