Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve command printing #224

Merged
merged 10 commits into from
Sep 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,13 @@ builds:
- main: ./main.go
id: "meteor"
binary: meteor
flags:
- -a
flags: [-a]
ldflags:
- -X github.com/odpf/meteor/cmd.Version={{.Tag}}
- -X github.com/odpf/meteor/cmd.BuildCommit={{.FullCommit}}
- -X github.com/odpf/meteor/cmd.BuildDate={{.Date}}
goos:
- darwin
- linux
- windows
goarch:
- amd64
- 386
- arm
- arm64
goos: [darwin, linux, windows]
goarch: [amd64, 386, arm, arm64]
env:
- CGO_ENABLED=0

Expand Down Expand Up @@ -70,16 +62,19 @@ dockers:

brews:
- name: meteor
homepage: "https://github.com/odpf/meteor"
description: "Metadata collection tool."
tap:
owner: odpf
name: homebrew-taps
license: "Apache 2.0"
folder: Formula

dependencies:
- name: git
install: |-
bin.install "meteor"
commit_author:
name: Stewart Jingga
email: stewart_jingga@yahoo.com
name: Ravi Suhag
email: ravi.suhag@gmail.com

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Meteor is a plugin driven agent for collecting metadata. Meteor has plugins to source metadata from a variety of data stores, services and message queues. It also has sink plugins to send metadata to variety of third party APIs and catalog services.

<p align="center"><img src="./docs/assets/overview.svg" /></p>
<p align="center"><img src="./docs/assets/overview_4.svg" /></p>

## Key Features

Expand Down
4 changes: 1 addition & 3 deletions cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ func GenRecipeCmd() *cobra.Command {

The recipe will be printed on standard output.
Specify recipe name with the first argument without extension.
Use commma to separate multiple sinks and processors.
`),
Use commma to separate multiple sinks and processors.`),
Example: heredoc.Doc(`
# generate a recipe with a bigquery extractor and a console sink
$ meteor gen recipe sample -e bigquery -s console
Expand All @@ -61,7 +60,6 @@ func GenRecipeCmd() *cobra.Command {
sinkList := strings.Split(sinks, ",")
procList := strings.Split(processors, ",")

// TODO: validate extractor and sink names
return generator.Recipe(args[0], extractor, sinkList, procList)
},
}
Expand Down
5 changes: 3 additions & 2 deletions cmd/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ func InfoSinkCmd() *cobra.Command {
Long: heredoc.Doc(`
Display sink information.

The list of supported sinks is available via the 'meteor list sinks' command.
`),
The list of supported sinks is available via the 'meteor list sinks' command.`),
Example: heredoc.Doc(`
$ meteor info sink console
$ meteor info sink columbus
`),
Args: cobra.ExactArgs(1),
Annotations: map[string]string{
Expand Down Expand Up @@ -68,6 +68,7 @@ func InfoExtCmd() *cobra.Command {
`),
Example: heredoc.Doc(`
$ meteor info extractor postgres
$ meteor info extractor bigquery
`),
Args: cobra.ExactArgs(1),
Annotations: map[string]string{
Expand Down
31 changes: 20 additions & 11 deletions cmd/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package cmd

import (
"fmt"
"os"

"github.com/MakeNowJust/heredoc"
"github.com/odpf/meteor/agent"
"github.com/odpf/meteor/metrics"
"github.com/odpf/meteor/recipe"
"github.com/odpf/meteor/registry"
"github.com/odpf/salt/log"
"github.com/odpf/salt/printer"
"github.com/odpf/salt/term"

"github.com/spf13/cobra"
Expand All @@ -25,8 +27,7 @@ func LintCmd(lg log.Logger, mt *metrics.StatsdMonitor) *cobra.Command {
Check for issues specified recipes.

Linters are run on the recipe files in the specified path.
If no path is specified, the current directory is used.
`),
If no path is specified, the current directory is used.`),
Example: heredoc.Doc(`
$ meteor lint recipe.yml

Expand All @@ -50,32 +51,40 @@ func LintCmd(lg log.Logger, mt *metrics.StatsdMonitor) *cobra.Command {
}

if len(recipes) == 0 {
fmt.Println(cs.Yellowf("no recipe found in [%s]", args[0]))
fmt.Println(cs.Yellowf("No recipe found in [%s]", args[0]))
fmt.Println(cs.Blue("\nUse 'meteor gen recipe' to generate a new recipe."))
return nil
}

report := []string{""}
report := [][]string{}
var success = 0
var failures = 0

// Run linters and generate report
for _, recipe := range recipes {
errs := runner.Validate(recipe)
var row = []string{}
if len(errs) > 0 {
for _, err := range errs {
lg.Error(err.Error())
}
report = append(report, fmt.Sprint(cs.FailureIcon(), cs.Redf(" %d errors found is recipe %s", len(errs), recipe.Name)))
row = []string{fmt.Sprintf("%s %s", cs.FailureIcon(), recipe.Name), cs.Greyf("(%d errors, 0 warnings)", len(errs))}
failures++
continue
} else {
row = []string{fmt.Sprintf("%s %s", cs.SuccessIcon(), recipe.Name), cs.Greyf("(%d errors, 0 warnings)", len(errs))}
success++
}
report = append(report, fmt.Sprint(cs.SuccessIcon(), cs.Greenf(" 0 error found in recipe %s", recipe.Name)))
success++
report = append(report, row)
}

for _, line := range report {
fmt.Println(line)
// Print the report
if failures > 0 {
fmt.Println("\nSome checks were not successful")
} else {
fmt.Println("\nAll checks were successful")
}
fmt.Printf("Total: %d, Success: %d, Failures: %d\n", len(recipes), success, failures)
fmt.Printf("%d failing, %d successful, and %d total\n\n", failures, success, len(recipes))
printer.Table(os.Stdout, report)
return nil
},
}
Expand Down
43 changes: 36 additions & 7 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package cmd
import (
"fmt"
"os"
"strings"

"github.com/MakeNowJust/heredoc"
"github.com/odpf/meteor/registry"
"github.com/odpf/salt/log"
"github.com/odpf/salt/printer"
"github.com/odpf/salt/term"

"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -51,9 +53,19 @@ func ListExtCmd() *cobra.Command {
"group:core": "true",
},
Run: func(cmd *cobra.Command, args []string) {
cs := term.NewColorScheme()

extractors := registry.Extractors.List()
fmt.Printf(" \nShowing %d of %d extractors\n \n", len(extractors), len(extractors))
printer.Table(os.Stdout, extractors)

report := [][]string{}
index := 1

for n, i := range extractors {
report = append(report, []string{cs.Greenf("#%02d", index), n, i.Description, cs.Greyf(" (%s)", strings.Join(i.Tags, ", "))})
index++
}
printer.Table(os.Stdout, report)
},
}
return cmd
Expand All @@ -70,8 +82,7 @@ func ListSinksCmd() *cobra.Command {

This command lists all available sinks.
Sinks are used to send data to a target.
For example, you can use a sink to send metadata to standard output.
`),
For example, you can use a sink to send metadata to standard output.`),
Example: heredoc.Doc(`
$ meteor list sinks

Expand All @@ -82,9 +93,18 @@ func ListSinksCmd() *cobra.Command {
"group:core": "true",
},
Run: func(cmd *cobra.Command, args []string) {
cs := term.NewColorScheme()

sinks := registry.Sinks.List()
fmt.Printf(" \nShowing %d of %d sinks\n \n", len(sinks), len(sinks))
printer.Table(os.Stdout, sinks)

report := [][]string{}
index := 1
for n, i := range sinks {
report = append(report, []string{cs.Greenf("#%02d", index), n, i.Description, cs.Greyf(" (%s)", strings.Join(i.Tags, ", "))})
index++
}
printer.Table(os.Stdout, report)
},
}
return cmd
Expand All @@ -101,8 +121,7 @@ func ListProccCmd() *cobra.Command {

This command lists all available processors.
Processors are used to transform data before it is sent to a sink.
For example, you can use a processor to enrich custom attributes.
`),
For example, you can use a processor to enrich custom attributes.`),
Example: heredoc.Doc(`
$ meteor list processors

Expand All @@ -113,9 +132,19 @@ func ListProccCmd() *cobra.Command {
"group:core": "true",
},
Run: func(cmd *cobra.Command, args []string) {
cs := term.NewColorScheme()

processors := registry.Processors.List()
fmt.Printf(" \nShowing %d of %d processors\n \n", len(processors), len(processors))
printer.Table(os.Stdout, processors)

report := [][]string{}
index := 1

for n, i := range processors {
report = append(report, []string{cs.Greenf("#%02d", index), n, i.Description, cs.Greyf(" (%s)", strings.Join(i.Tags, ", "))})
index++
}
printer.Table(os.Stdout, report)
},
}
return cmd
Expand Down
9 changes: 6 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@ func New(lg log.Logger, mt *metrics.StatsdMonitor) *cobra.Command {
Meteor is a plugin driven agent for collecting metadata.
Meteor has plugins to source metadata from a variety of data stores,
services and message queues. It also has sink plugins to send metadata
to variety of third party APIs and catalog services.
`),
to variety of third party APIs and catalog services.`),
SilenceErrors: true,
SilenceUsage: false,
Example: heredoc.Doc(`
$ meteor list extractors
$ meteor run recipe.yaml
$ meteor gen recipe --extractor=date
$ meteor gen recipe --extractor=date --sink console
`),
Annotations: map[string]string{
"group:core": "true",
"help:learn": heredoc.Doc(`
Use 'meteor <command> <subcommand> --help' for more information about a command.
Read the manual at https://odpf.gitbook.io/meteor/
`),
"help:feedback": heredoc.Doc(`
Open an issue here https://github.com/odpf/meteor/issues
`),
Expand Down
37 changes: 18 additions & 19 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ func RunCmd(lg log.Logger, mt *metrics.StatsdMonitor) *cobra.Command {
A recipe is a set of instructions and configurations defined by user,
and in Meteor they are used to define how metadata will be collected.

If a recipe file is provided, recipe will be
executed as a single recipe.
If a recipe directory is provided, recipes will
be executed as a group of recipes.
`),
If a recipe file is provided, recipe will be executed as a single recipe.
If a recipe directory is provided, recipes will be executed as a group of recipes.`),
Example: heredoc.Doc(`
$ meteor run recipe.yml

Expand All @@ -56,36 +53,38 @@ func RunCmd(lg log.Logger, mt *metrics.StatsdMonitor) *cobra.Command {
}

if len(recipes) == 0 {
fmt.Println(cs.WarningIcon(), cs.Yellowf(" no recipe found in [%s]", args[0]))
fmt.Println(cs.WarningIcon(), cs.Yellowf("No recipe found in [%s]", args[0]))
return nil
}

report := [][]string{}
var success = 0
var failures = 0
tabular_report := [][]string{}
tabular_report = append(tabular_report, []string{"Recipe", "Source", "Status", "Duration(ms)"})

// Run recipes and collect results
runs := runner.RunMultiple(recipes)
for _, run := range runs {
lg.Debug("recipe details", "recipe", run.Recipe)
report_row := []string{run.Recipe.Name, run.Recipe.Source.Type}

row := []string{}
if run.Error != nil {
lg.Error(run.Error.Error(), "recipe")
failures++
report_row = append(report_row, cs.FailureIcon()+cs.Redf("failure"))
row = append(row, fmt.Sprintf("%s %s", cs.FailureIcon(), run.Recipe.Name), cs.Grey(run.Recipe.Source.Type), cs.Greyf("%v ms", strconv.Itoa(run.DurationInMs)))
} else {
success++
report_row = append(report_row, cs.SuccessIcon()+cs.Greenf("successful"))
row = append(row, fmt.Sprintf("%s %s", cs.SuccessIcon(), run.Recipe.Name), cs.Grey(run.Recipe.Source.Type), cs.Greyf("%v ms", strconv.Itoa(run.DurationInMs)))
}

report_row = append(report_row, strconv.Itoa(run.DurationInMs))
tabular_report = append(tabular_report, report_row)
report = append(report, row)
}

fmt.Print("\n\n")
printer.Table(os.Stdout, tabular_report)
fmt.Printf("Total: %d, Success: %d, Failures: %d\n", len(recipes), success, failures)

// Print the report
if failures > 0 {
fmt.Println("\nSome recipes were not successful")
} else {
fmt.Println("\nAll recipes ran successful")
}
fmt.Printf("%d failing, %d successful, and %d total\n\n", failures, success, len(recipes))
printer.Table(os.Stdout, report)
return nil
},
}
Expand Down
Binary file added docs/assets/.DS_Store
Binary file not shown.
Loading