This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new d0ca0fcb add generator for create-plugin (#2352)
d0ca0fcb is described below
commit d0ca0fcb6ee467e008526cf47ffd6a17b9cfd748
Author: likyh <[email protected]>
AuthorDate: Mon Jun 27 11:11:44 2022 +0800
add generator for create-plugin (#2352)
* add generator for create-plugin
* add document
* append
* delete gif in repo
* fix lint
Co-authored-by: linyh <[email protected]>
Co-authored-by: Klesh Wong <[email protected]>
---
generator/README.md | 27 +++++
generator/cmd/create_collector.go | 128 +++++++++++++++++++
generator/cmd/create_extractor.go | 126 +++++++++++++++++++
generator/cmd/create_plugin.go | 135 +++++++++++++++++++++
.../task_data.go-template => cmd/generator_doc.go} | 25 ++--
generator/cmd/root.go | 77 ++++++++++++
generator/docs/generator.md | 21 ++++
generator/docs/generator_completion.md | 32 +++++
generator/docs/generator_completion_bash.md | 51 ++++++++
generator/docs/generator_completion_fish.md | 42 +++++++
generator/docs/generator_completion_powershell.md | 39 ++++++
generator/docs/generator_completion_zsh.md | 53 ++++++++
generator/docs/generator_create-collector.md | 31 +++++
generator/docs/generator_create-extractor.md | 31 +++++
generator/docs/generator_create-plugin.md | 31 +++++
generator/docs/generator_generator-doc.md | 26 ++++
.../plugin/tasks/task_data.go-template => main.go} | 23 ++--
generator/template/plugin/plugin_main.go-template | 10 +-
...ate => plugin_main_with_api_client.go-template} | 14 +--
.../template/plugin/tasks/api_client.go-template | 10 +-
.../template/plugin/tasks/extractor.go-template | 1 -
.../template/plugin/tasks/task_data.go-template | 6 -
...plate => task_data_with_api_client.go-template} | 3 +-
generator/util/template.go | 102 ++++++++++++++++
go.mod | 7 +-
go.sum | 12 ++
26 files changed, 1002 insertions(+), 61 deletions(-)
diff --git a/generator/README.md b/generator/README.md
new file mode 100644
index 00000000..b129f940
--- /dev/null
+++ b/generator/README.md
@@ -0,0 +1,27 @@
+# Apache DevLake Cli Tool -- Code Generator
+
+## How to use?
+
+Just run by `go run`:
+```bash
+go run generator/main.go [command]
+```
+
+Help also integrate in it:
+```bash
+go run generator/main.go help
+```
+
+Usage Gif:
+
+
+## Plugin Related
+
+* [create-collector](./docs/generator_create-collector.md) - Create a new
collector
+* [create-extractor](./docs/generator_create-extractor.md) - Create a new
extractor
+* [create-plugin](./docs/generator_create-plugin.md) - Create a new plugin
+
+## Others
+
+* [completion](./docs/generator_completion.md) - Generate the autocompletion
script for the specified shell
+* [global options](./docs/generator.md)
diff --git a/generator/cmd/create_collector.go
b/generator/cmd/create_collector.go
new file mode 100644
index 00000000..79744028
--- /dev/null
+++ b/generator/cmd/create_collector.go
@@ -0,0 +1,128 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+ "errors"
+ "fmt"
+ "github.com/apache/incubator-devlake/generator/util"
+ "github.com/manifoldco/promptui"
+ "github.com/spf13/cobra"
+ "github.com/stoewer/go-strcase"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+func init() {
+ rootCmd.AddCommand(createCollectorCmd)
+}
+
+func collectorNameNotExistValidateHoc(pluginName string) func(input string)
error {
+ collectorNameValidate := func(input string) error {
+ if input == `` {
+ return errors.New("please input which data would you
will collect (snake_format)")
+ }
+ snakeNameReg := regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`)
+ if !snakeNameReg.MatchString(input) {
+ return errors.New("collector name invalid (start with
a-z and consist with a-z0-9_)")
+ }
+ _, err := os.Stat(filepath.Join(`plugins`, pluginName, `tasks`,
input+`_collector.go`))
+ if os.IsNotExist(err) {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ return errors.New("collector exists")
+ }
+ return collectorNameValidate
+}
+
+func collectorNameExistValidateHoc(pluginName string) func(input string) error
{
+ collectorNameValidate := func(input string) error {
+ if input == `` {
+ return errors.New("please input which data would you
will collect (snake_format)")
+ }
+ _, err := os.Stat(filepath.Join(`plugins`, pluginName, `tasks`,
input+`_collector.go`))
+ return err
+ }
+ return collectorNameValidate
+}
+
+var createCollectorCmd = &cobra.Command{
+ Use: "create-collector [plugin_name] [collector_name]",
+ Short: "Create a new collector",
+ Long: `Create a new collector
+Type in what the name of collector is, then generator will create a new
collector in plugins/$plugin_name/tasks/$collector_name for you`,
+ Run: func(cmd *cobra.Command, args []string) {
+ var pluginName string
+ var collectorName string
+ var err error
+
+ // try to get plugin name and collector name
+ if len(args) > 0 {
+ pluginName = args[0]
+ }
+ prompt := promptui.Prompt{
+ Label: "plugin_name",
+ Validate: pluginNameExistValidate,
+ Default: pluginName,
+ }
+ pluginName, err = prompt.Run()
+ cobra.CheckErr(err)
+ pluginName = strings.ToLower(pluginName)
+
+ if len(args) > 1 {
+ collectorName = args[1]
+ }
+ prompt = promptui.Prompt{
+ Label: "collector_data_name",
+ Validate: collectorNameNotExistValidateHoc(pluginName),
+ Default: collectorName,
+ }
+ collectorName, err = prompt.Run()
+ cobra.CheckErr(err)
+ collectorName = strings.ToLower(collectorName)
+
+ // read template
+ templates := map[string]string{
+ collectorName + `_collector.go`:
util.ReadTemplate("generator/template/plugin/tasks/api_collector.go-template"),
+ }
+
+ // create vars
+ values := map[string]string{}
+ util.GenerateAllFormatVar(values, `plugin_name`, pluginName)
+ util.GenerateAllFormatVar(values, `collector_data_name`,
collectorName)
+ collectorDataNameUpperCamel :=
strcase.UpperCamelCase(collectorName)
+ values = util.DetectExistVars(templates, values)
+ println(`vars in template:`, fmt.Sprint(values))
+
+ // write template
+ util.ReplaceVarInTemplates(templates, values)
+ util.WriteTemplates(filepath.Join(`plugins`, pluginName,
`tasks`), templates)
+ if modifyExistCode {
+ util.ReplaceVarInFile(
+ filepath.Join(`plugins`, pluginName,
`plugin_main.go`),
+ regexp.MustCompile(`(return
+\[]core\.SubTaskMeta ?\{ ?\n?)((\s*[\w.]+,\n)*)(\s*})`),
+ fmt.Sprintf("$1$2\t\ttasks.Collect%sMeta,\n$4",
collectorDataNameUpperCamel),
+ )
+ }
+ },
+}
diff --git a/generator/cmd/create_extractor.go
b/generator/cmd/create_extractor.go
new file mode 100644
index 00000000..b63ac6a6
--- /dev/null
+++ b/generator/cmd/create_extractor.go
@@ -0,0 +1,126 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+ "errors"
+ "fmt"
+ "github.com/apache/incubator-devlake/generator/util"
+ "github.com/manifoldco/promptui"
+ "github.com/spf13/cobra"
+ "github.com/stoewer/go-strcase"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+func init() {
+ rootCmd.AddCommand(createExtractorCmd)
+}
+
+func extractorNameNotExistValidateHoc(pluginName string) func(input string)
error {
+ extractorNameValidate := func(input string) error {
+ if input == `` {
+ return errors.New("please input which data would you
will extract (snake_format)")
+ }
+ snakeNameReg := regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`)
+ if !snakeNameReg.MatchString(input) {
+ return errors.New("extractor name invalid (start with
a-z and consist with a-z0-9_)")
+ }
+ _, err := os.Stat(filepath.Join(`plugins`, pluginName, `tasks`,
input+`_extractor.go`))
+ if os.IsNotExist(err) {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ return errors.New("extractor exists")
+ }
+ return extractorNameValidate
+}
+
+var createExtractorCmd = &cobra.Command{
+ Use: "create-extractor [plugin_name] [extractor_name]",
+ Short: "Create a new extractor",
+ Long: `Create a new extractor
+Type in what the name of extractor is, then generator will create a new
extractor in plugins/$plugin_name/tasks/$extractor_name for you`,
+ Run: func(cmd *cobra.Command, args []string) {
+ var pluginName string
+ var extractorName string
+ var err error
+
+ // try to get plugin name and extractor name
+ if len(args) > 0 {
+ pluginName = args[0]
+ }
+ prompt := promptui.Prompt{
+ Label: "plugin_name",
+ Validate: pluginNameExistValidate,
+ Default: pluginName,
+ }
+ pluginName, err = prompt.Run()
+ cobra.CheckErr(err)
+ pluginName = strings.ToLower(pluginName)
+
+ prompt = promptui.Prompt{
+ Label: "collector_name",
+ Validate: collectorNameExistValidateHoc(pluginName),
+ }
+ collectorName, err := prompt.Run()
+ cobra.CheckErr(err)
+ collectorName = strings.ToLower(collectorName)
+
+ if len(args) > 1 {
+ extractorName = args[1]
+ }
+ prompt = promptui.Prompt{
+ Label: "extractor_name",
+ Validate: extractorNameNotExistValidateHoc(pluginName),
+ Default: extractorName,
+ }
+ extractorName, err = prompt.Run()
+ cobra.CheckErr(err)
+ extractorName = strings.ToLower(extractorName)
+
+ // read template
+ templates := map[string]string{
+ extractorName + `_extractor.go`:
util.ReadTemplate("generator/template/plugin/tasks/extractor.go-template"),
+ }
+
+ // create vars
+ values := map[string]string{}
+ util.GenerateAllFormatVar(values, `plugin_name`, pluginName)
+ util.GenerateAllFormatVar(values, `collector_data_name`,
collectorName)
+ util.GenerateAllFormatVar(values, `extractor_data_name`,
extractorName)
+ extractorDataNameUpperCamel :=
strcase.UpperCamelCase(extractorName)
+ values = util.DetectExistVars(templates, values)
+ println(`vars in template:`, fmt.Sprint(values))
+
+ // write template
+ util.ReplaceVarInTemplates(templates, values)
+ util.WriteTemplates(filepath.Join(`plugins`, pluginName,
`tasks`), templates)
+ if modifyExistCode {
+ util.ReplaceVarInFile(
+ filepath.Join(`plugins`, pluginName,
`plugin_main.go`),
+ regexp.MustCompile(`(return
+\[]core\.SubTaskMeta ?\{ ?\n?)((\s*[\w.]+,\n)*)(\s*})`),
+ fmt.Sprintf("$1$2\t\ttasks.Extract%sMeta,\n$4",
extractorDataNameUpperCamel),
+ )
+ }
+ },
+}
diff --git a/generator/cmd/create_plugin.go b/generator/cmd/create_plugin.go
new file mode 100644
index 00000000..026cea13
--- /dev/null
+++ b/generator/cmd/create_plugin.go
@@ -0,0 +1,135 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+ "errors"
+ "fmt"
+ "github.com/apache/incubator-devlake/generator/util"
+ "github.com/manifoldco/promptui"
+ "github.com/spf13/cobra"
+ "os"
+ "regexp"
+ "strings"
+)
+
+func init() {
+ rootCmd.AddCommand(createPluginCmd)
+}
+
+func pluginNameNotExistValidate(input string) error {
+ if input == `` {
+ return errors.New("plugin name requite")
+ }
+ snakeNameReg := regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`)
+ if !snakeNameReg.MatchString(input) {
+ return errors.New("plugin name invalid (start with a-z and
consist with a-z0-9_)")
+ }
+ _, err := os.Stat(`plugins/` + input)
+ if os.IsNotExist(err) {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ return errors.New("plugin exists")
+}
+
+func pluginNameExistValidate(input string) error {
+ if input == `` {
+ return errors.New("plugin name requite")
+ }
+ _, err := os.Stat(`plugins/` + input)
+ return err
+}
+
+var createPluginCmd = &cobra.Command{
+ Use: "create-plugin [plugin_name]",
+ Short: "Create a new plugin",
+ Long: `Create a new plugin
+Type in what the name of plugin is, then generator will create a new plugin in
plugins/$plugin_name for you`,
+ Run: func(cmd *cobra.Command, args []string) {
+ var pluginName string
+
+ // try to get plugin name
+ if len(args) > 0 {
+ pluginName = args[0]
+ }
+ err := pluginNameNotExistValidate(pluginName)
+ if err != nil {
+ prompt := promptui.Prompt{
+ Label: "plugin_name",
+ Validate: pluginNameNotExistValidate,
+ Default: pluginName,
+ }
+ pluginName, err = prompt.Run()
+ cobra.CheckErr(err)
+ pluginName = strings.ToLower(pluginName)
+ }
+
+ prompt := promptui.Select{
+ Label: "with_api_client (is this plugin will request
HTTP APIs?)",
+ Items: []string{"Yes", "No"},
+ }
+ _, withApiClient, err := prompt.Run()
+ cobra.CheckErr(err)
+
+ values := map[string]string{}
+ templates := map[string]string{}
+ if withApiClient == `Yes` {
+ prompt := promptui.Prompt{
+ Label: "Endpoint (which host to request)",
+ Default: `https://open.example.cn/api/v1`,
+ Validate: func(input string) error {
+ if input == `` {
+ return errors.New("endpoint
requite")
+ }
+ if !strings.HasPrefix(input, `http`) {
+ return errors.New("endpoint
should start with http")
+ }
+ return nil
+ },
+ }
+ endpoint, err := prompt.Run()
+ cobra.CheckErr(err)
+
+ // read template
+ templates = map[string]string{
+ `plugin_main.go`:
util.ReadTemplate("generator/template/plugin/plugin_main_with_api_client.go-template"),
+ `tasks/api_client.go`:
util.ReadTemplate("generator/template/plugin/tasks/api_client.go-template"),
+ `tasks/task_data.go`:
util.ReadTemplate("generator/template/plugin/tasks/task_data_with_api_client.go-template"),
+ }
+ util.GenerateAllFormatVar(values, `plugin_name`,
pluginName)
+ values[`Endpoint`] = endpoint
+ } else if withApiClient == `No` {
+ // read template
+ templates = map[string]string{
+ `plugin_main.go`:
util.ReadTemplate("generator/template/plugin/plugin_main.go-template"),
+ `tasks/task_data.go`:
util.ReadTemplate("generator/template/plugin/tasks/task_data.go-template"),
+ }
+ util.GenerateAllFormatVar(values, `plugin_name`,
pluginName)
+ }
+
+ values = util.DetectExistVars(templates, values)
+ println(`vars in template:`, fmt.Sprint(values))
+
+ // write template
+ util.ReplaceVarInTemplates(templates, values)
+ util.WriteTemplates(`plugins/`+pluginName, templates)
+ },
+}
diff --git a/generator/template/plugin/tasks/task_data.go-template
b/generator/cmd/generator_doc.go
similarity index 59%
copy from generator/template/plugin/tasks/task_data.go-template
copy to generator/cmd/generator_doc.go
index 8a58ae4c..6a4cded6 100644
--- a/generator/template/plugin/tasks/task_data.go-template
+++ b/generator/cmd/generator_doc.go
@@ -15,24 +15,21 @@ See the License for the specific language governing
permissions and
limitations under the License.
*/
-package tasks
+package cmd
import (
- "github.com/apache/incubator-devlake/plugins/helper"
+ "github.com/spf13/cobra"
+ "github.com/spf13/cobra/doc"
)
-type {{ .PluginName }}ApiParams struct {
+func init() {
+ rootCmd.AddCommand(GeneratorDocCmd)
}
-type {{ .PluginName }}Options struct {
- // TODO add some custom options here if necessary
- // options means some custom params required by plugin running.
- // Such As How many rows do your want
- // You can use it in sub tasks and you need pass it in main.go and
pipelines.
- Tasks []string `json:"tasks,omitempty"`
-}
-
-type {{ .PluginName }}TaskData struct {
- Options *{{ .PluginName }}Options
- // ApiClient *helper.ApiAsyncClient
+var GeneratorDocCmd = &cobra.Command{
+ Use: "generator-doc",
+ Short: "generate document for generator",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return doc.GenMarkdownTree(rootCmd, "generator/docs")
+ },
}
diff --git a/generator/cmd/root.go b/generator/cmd/root.go
new file mode 100644
index 00000000..4a1316c5
--- /dev/null
+++ b/generator/cmd/root.go
@@ -0,0 +1,77 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+ "errors"
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
+)
+
+var (
+ // Used for flags.
+ cfgFile string
+ modifyExistCode bool
+
+ rootCmd = &cobra.Command{
+ Use: `generator [command]`,
+ Short: "Apache DevLake Cli Tool -- Code Generator",
+ }
+)
+
+// Execute executes the root command.
+func Execute() error {
+ return rootCmd.Execute()
+}
+
+func init() {
+ cobra.OnInitialize(initConfig)
+
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config
file (default is PROJECT/.env)")
+ rootCmd.PersistentFlags().BoolVar(&modifyExistCode, "modifyExistCode",
true, "allow generator modify exist code")
+}
+
+func initConfig() {
+ if cfgFile != "" {
+ // Use config file from the flag.
+ viper.SetConfigFile(cfgFile)
+ } else {
+ viper.AddConfigPath("..")
+ viper.AddConfigPath(".")
+ viper.SetConfigType("env")
+ viper.SetConfigName(".env")
+ }
+
+ viper.AutomaticEnv()
+
+ err := viper.ReadInConfig()
+
+ notFound := &viper.ConfigFileNotFoundError{}
+ switch {
+ case err != nil && !errors.As(err, notFound):
+ cobra.CheckErr(err)
+ case err != nil && errors.As(err, notFound):
+ // The config file is optional, we shouldn't exit when the
config is not found
+ break
+ default:
+ fmt.Fprintln(os.Stderr, "Using config file:",
viper.ConfigFileUsed())
+ }
+}
diff --git a/generator/docs/generator.md b/generator/docs/generator.md
new file mode 100644
index 00000000..003fd86f
--- /dev/null
+++ b/generator/docs/generator.md
@@ -0,0 +1,21 @@
+## generator
+
+Apache DevLake Cli Tool -- Code Generator
+
+### Options
+
+```
+ --config string config file (default is PROJECT/.env)
+ -h, --help help for generator
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator completion](generator_completion.md) - Generate the
autocompletion script for the specified shell
+* [generator create-collector](generator_create-collector.md) - Create a new
collector
+* [generator create-extractor](generator_create-extractor.md) - Create a new
extractor
+* [generator create-plugin](generator_create-plugin.md) - Create a new
plugin
+* [generator generator-doc](generator_generator-doc.md) - generate
document for generator
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_completion.md
b/generator/docs/generator_completion.md
new file mode 100644
index 00000000..c0f14d04
--- /dev/null
+++ b/generator/docs/generator_completion.md
@@ -0,0 +1,32 @@
+## generator completion
+
+Generate the autocompletion script for the specified shell
+
+### Synopsis
+
+Generate the autocompletion script for generator for the specified shell.
+See each sub-command's help for details on how to use the generated script.
+
+
+### Options
+
+```
+ -h, --help help for completion
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator](generator.md) - Apache DevLake Cli Tool -- Code Generator
+* [generator completion bash](generator_completion_bash.md) - Generate the
autocompletion script for bash
+* [generator completion fish](generator_completion_fish.md) - Generate the
autocompletion script for fish
+* [generator completion powershell](generator_completion_powershell.md)
- Generate the autocompletion script for powershell
+* [generator completion zsh](generator_completion_zsh.md) - Generate the
autocompletion script for zsh
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_completion_bash.md
b/generator/docs/generator_completion_bash.md
new file mode 100644
index 00000000..99f70263
--- /dev/null
+++ b/generator/docs/generator_completion_bash.md
@@ -0,0 +1,51 @@
+## generator completion bash
+
+Generate the autocompletion script for bash
+
+### Synopsis
+
+Generate the autocompletion script for the bash shell.
+
+This script depends on the 'bash-completion' package.
+If it is not installed already, you can install it via your OS's package
manager.
+
+To load completions in your current shell session:
+
+ source <(generator completion bash)
+
+To load completions for every new session, execute once:
+
+#### Linux:
+
+ generator completion bash > /etc/bash_completion.d/generator
+
+#### macOS:
+
+ generator completion bash > $(brew
--prefix)/etc/bash_completion.d/generator
+
+You will need to start a new shell for this setup to take effect.
+
+
+```
+generator completion bash
+```
+
+### Options
+
+```
+ -h, --help help for bash
+ --no-descriptions disable completion descriptions
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator completion](generator_completion.md) - Generate the
autocompletion script for the specified shell
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_completion_fish.md
b/generator/docs/generator_completion_fish.md
new file mode 100644
index 00000000..d55e5b16
--- /dev/null
+++ b/generator/docs/generator_completion_fish.md
@@ -0,0 +1,42 @@
+## generator completion fish
+
+Generate the autocompletion script for fish
+
+### Synopsis
+
+Generate the autocompletion script for the fish shell.
+
+To load completions in your current shell session:
+
+ generator completion fish | source
+
+To load completions for every new session, execute once:
+
+ generator completion fish > ~/.config/fish/completions/generator.fish
+
+You will need to start a new shell for this setup to take effect.
+
+
+```
+generator completion fish [flags]
+```
+
+### Options
+
+```
+ -h, --help help for fish
+ --no-descriptions disable completion descriptions
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator completion](generator_completion.md) - Generate the
autocompletion script for the specified shell
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_completion_powershell.md
b/generator/docs/generator_completion_powershell.md
new file mode 100644
index 00000000..b3106331
--- /dev/null
+++ b/generator/docs/generator_completion_powershell.md
@@ -0,0 +1,39 @@
+## generator completion powershell
+
+Generate the autocompletion script for powershell
+
+### Synopsis
+
+Generate the autocompletion script for powershell.
+
+To load completions in your current shell session:
+
+ generator completion powershell | Out-String | Invoke-Expression
+
+To load completions for every new session, add the output of the above command
+to your powershell profile.
+
+
+```
+generator completion powershell [flags]
+```
+
+### Options
+
+```
+ -h, --help help for powershell
+ --no-descriptions disable completion descriptions
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator completion](generator_completion.md) - Generate the
autocompletion script for the specified shell
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_completion_zsh.md
b/generator/docs/generator_completion_zsh.md
new file mode 100644
index 00000000..82dbe67d
--- /dev/null
+++ b/generator/docs/generator_completion_zsh.md
@@ -0,0 +1,53 @@
+## generator completion zsh
+
+Generate the autocompletion script for zsh
+
+### Synopsis
+
+Generate the autocompletion script for the zsh shell.
+
+If shell completion is not already enabled in your environment you will need
+to enable it. You can execute the following once:
+
+ echo "autoload -U compinit; compinit" >> ~/.zshrc
+
+To load completions in your current shell session:
+
+ source <(generator completion zsh); compdef _generator generator
+
+To load completions for every new session, execute once:
+
+#### Linux:
+
+ generator completion zsh > "${fpath[1]}/_generator"
+
+#### macOS:
+
+ generator completion zsh > $(brew
--prefix)/share/zsh/site-functions/_generator
+
+You will need to start a new shell for this setup to take effect.
+
+
+```
+generator completion zsh [flags]
+```
+
+### Options
+
+```
+ -h, --help help for zsh
+ --no-descriptions disable completion descriptions
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator completion](generator_completion.md) - Generate the
autocompletion script for the specified shell
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_create-collector.md
b/generator/docs/generator_create-collector.md
new file mode 100644
index 00000000..6e90cf55
--- /dev/null
+++ b/generator/docs/generator_create-collector.md
@@ -0,0 +1,31 @@
+## generator create-collector
+
+Create a new collector
+
+### Synopsis
+
+Create a new collector
+Type in what the name of collector is, then generator will create a new
collector in plugins/$plugin_name/tasks/$collector_name for you
+
+```
+generator create-collector [plugin_name] [collector_name] [flags]
+```
+
+### Options
+
+```
+ -h, --help help for create-collector
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator](generator.md) - Apache DevLake Cli Tool -- Code Generator
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_create-extractor.md
b/generator/docs/generator_create-extractor.md
new file mode 100644
index 00000000..fe8a906b
--- /dev/null
+++ b/generator/docs/generator_create-extractor.md
@@ -0,0 +1,31 @@
+## generator create-extractor
+
+Create a new extractor
+
+### Synopsis
+
+Create a new extractor
+Type in what the name of extractor is, then generator will create a new
extractor in plugins/$plugin_name/tasks/$extractor_name for you
+
+```
+generator create-extractor [plugin_name] [extractor_name] [flags]
+```
+
+### Options
+
+```
+ -h, --help help for create-extractor
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator](generator.md) - Apache DevLake Cli Tool -- Code Generator
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_create-plugin.md
b/generator/docs/generator_create-plugin.md
new file mode 100644
index 00000000..8a83b062
--- /dev/null
+++ b/generator/docs/generator_create-plugin.md
@@ -0,0 +1,31 @@
+## generator create-plugin
+
+Create a new plugin
+
+### Synopsis
+
+Create a new plugin
+Type in what the name of plugin is, then generator will create a new plugin in
plugins/$plugin_name for you
+
+```
+generator create-plugin [plugin_name] [flags]
+```
+
+### Options
+
+```
+ -h, --help help for create-plugin
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator](generator.md) - Apache DevLake Cli Tool -- Code Generator
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/docs/generator_generator-doc.md
b/generator/docs/generator_generator-doc.md
new file mode 100644
index 00000000..02689b43
--- /dev/null
+++ b/generator/docs/generator_generator-doc.md
@@ -0,0 +1,26 @@
+## generator generator-doc
+
+generate document for generator
+
+```
+generator generator-doc [flags]
+```
+
+### Options
+
+```
+ -h, --help help for generator-doc
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is PROJECT/.env)
+ --modifyExistCode allow generator modify exist code (default true)
+```
+
+### SEE ALSO
+
+* [generator](generator.md) - Apache DevLake Cli Tool -- Code Generator
+
+###### Auto generated by spf13/cobra on 24-Jun-2022
diff --git a/generator/template/plugin/tasks/task_data.go-template
b/generator/main.go
similarity index 58%
copy from generator/template/plugin/tasks/task_data.go-template
copy to generator/main.go
index 8a58ae4c..0515a4be 100644
--- a/generator/template/plugin/tasks/task_data.go-template
+++ b/generator/main.go
@@ -15,24 +15,15 @@ See the License for the specific language governing
permissions and
limitations under the License.
*/
-package tasks
+package main
import (
- "github.com/apache/incubator-devlake/plugins/helper"
+ "github.com/apache/incubator-devlake/generator/cmd"
+ "os"
)
-type {{ .PluginName }}ApiParams struct {
-}
-
-type {{ .PluginName }}Options struct {
- // TODO add some custom options here if necessary
- // options means some custom params required by plugin running.
- // Such As How many rows do your want
- // You can use it in sub tasks and you need pass it in main.go and
pipelines.
- Tasks []string `json:"tasks,omitempty"`
-}
-
-type {{ .PluginName }}TaskData struct {
- Options *{{ .PluginName }}Options
- // ApiClient *helper.ApiAsyncClient
+func main() {
+ if err := cmd.Execute(); err != nil {
+ os.Exit(1)
+ }
}
diff --git a/generator/template/plugin/plugin_main.go-template
b/generator/template/plugin/plugin_main.go-template
index f6ab681a..a2ec81db 100644
--- a/generator/template/plugin/plugin_main.go-template
+++ b/generator/template/plugin/plugin_main.go-template
@@ -51,8 +51,8 @@ func (plugin {{ .PluginName }}) Init(config *viper.Viper,
logger core.Logger, db
}
func (plugin {{ .PluginName }}) SubTaskMetas() []core.SubTaskMeta {
+ // TODO add your sub task here
return []core.SubTaskMeta{
- // TODO add your sub task here
}
}
@@ -63,16 +63,8 @@ func (plugin {{ .PluginName }}) PrepareTaskData(taskCtx
core.TaskContext, option
return nil, err
}
- // apiClient, err := tasks.New{{ .PluginName }}ApiClient(taskCtx)
- // if err != nil {
- // return nil, err
- // }
-
return &tasks.{{ .PluginName }}TaskData{
Options: &op,
- // TODO you can init and stash some handler to deal data at all
subtasks, Such as apiClient as below.
- // NOTES: In task_data.go/TaskData should declare `ApiClient`
- // ApiClient: apiClient,
}, nil
}
diff --git a/generator/template/plugin/plugin_main.go-template
b/generator/template/plugin/plugin_main_with_api_client.go-template
similarity index 89%
copy from generator/template/plugin/plugin_main.go-template
copy to generator/template/plugin/plugin_main_with_api_client.go-template
index f6ab681a..1ab8333d 100644
--- a/generator/template/plugin/plugin_main.go-template
+++ b/generator/template/plugin/plugin_main_with_api_client.go-template
@@ -51,8 +51,8 @@ func (plugin {{ .PluginName }}) Init(config *viper.Viper,
logger core.Logger, db
}
func (plugin {{ .PluginName }}) SubTaskMetas() []core.SubTaskMeta {
+ // TODO add your sub task here
return []core.SubTaskMeta{
- // TODO add your sub task here
}
}
@@ -63,16 +63,14 @@ func (plugin {{ .PluginName }}) PrepareTaskData(taskCtx
core.TaskContext, option
return nil, err
}
- // apiClient, err := tasks.New{{ .PluginName }}ApiClient(taskCtx)
- // if err != nil {
- // return nil, err
- // }
+ apiClient, err := tasks.New{{ .PluginName }}ApiClient(taskCtx)
+ if err != nil {
+ return nil, err
+ }
return &tasks.{{ .PluginName }}TaskData{
Options: &op,
- // TODO you can init and stash some handler to deal data at all
subtasks, Such as apiClient as below.
- // NOTES: In task_data.go/TaskData should declare `ApiClient`
- // ApiClient: apiClient,
+ ApiClient: apiClient,
}, nil
}
diff --git a/generator/template/plugin/tasks/api_client.go-template
b/generator/template/plugin/tasks/api_client.go-template
index b4387c14..a79e1312 100644
--- a/generator/template/plugin/tasks/api_client.go-template
+++ b/generator/template/plugin/tasks/api_client.go-template
@@ -26,7 +26,7 @@ import (
)
// TODO add what host would want to requist
-const ENDPOINT = "https://open.example.cn/api/v1"
+const ENDPOINT = "{{ .Endpoint }}"
func New{{ .PluginName }}ApiClient(taskCtx core.TaskContext)
(*helper.ApiAsyncClient, error) {
// load and process configuration
@@ -46,9 +46,11 @@ func New{{ .PluginName }}ApiClient(taskCtx core.TaskContext)
(*helper.ApiAsyncCl
return nil, err
}
// set token
- apiClient.SetHeaders(map[string]string{
- "Authorization": fmt.Sprintf("Bearer %v", token),
- })
+ if token != "" {
+ apiClient.SetHeaders(map[string]string{
+ "Authorization": fmt.Sprintf("Bearer %v", token),
+ })
+ }
// TODO add some check after request if necessary
// apiClient.SetAfterFunction(func(res *http.Response) error {
diff --git a/generator/template/plugin/tasks/extractor.go-template
b/generator/template/plugin/tasks/extractor.go-template
index eceb661c..7a41a59d 100644
--- a/generator/template/plugin/tasks/extractor.go-template
+++ b/generator/template/plugin/tasks/extractor.go-template
@@ -18,7 +18,6 @@ limitations under the License.
package tasks
import (
- "encoding/json"
"github.com/apache/incubator-devlake/plugins/core"
"github.com/apache/incubator-devlake/plugins/helper"
)
diff --git a/generator/template/plugin/tasks/task_data.go-template
b/generator/template/plugin/tasks/task_data.go-template
index 8a58ae4c..50fdbd05 100644
--- a/generator/template/plugin/tasks/task_data.go-template
+++ b/generator/template/plugin/tasks/task_data.go-template
@@ -17,10 +17,6 @@ limitations under the License.
package tasks
-import (
- "github.com/apache/incubator-devlake/plugins/helper"
-)
-
type {{ .PluginName }}ApiParams struct {
}
@@ -29,10 +25,8 @@ type {{ .PluginName }}Options struct {
// options means some custom params required by plugin running.
// Such As How many rows do your want
// You can use it in sub tasks and you need pass it in main.go and
pipelines.
- Tasks []string `json:"tasks,omitempty"`
}
type {{ .PluginName }}TaskData struct {
Options *{{ .PluginName }}Options
- // ApiClient *helper.ApiAsyncClient
}
diff --git a/generator/template/plugin/tasks/task_data.go-template
b/generator/template/plugin/tasks/task_data_with_api_client.go-template
similarity index 94%
copy from generator/template/plugin/tasks/task_data.go-template
copy to generator/template/plugin/tasks/task_data_with_api_client.go-template
index 8a58ae4c..5dec7665 100644
--- a/generator/template/plugin/tasks/task_data.go-template
+++ b/generator/template/plugin/tasks/task_data_with_api_client.go-template
@@ -29,10 +29,9 @@ type {{ .PluginName }}Options struct {
// options means some custom params required by plugin running.
// Such As How many rows do your want
// You can use it in sub tasks and you need pass it in main.go and
pipelines.
- Tasks []string `json:"tasks,omitempty"`
}
type {{ .PluginName }}TaskData struct {
Options *{{ .PluginName }}Options
- // ApiClient *helper.ApiAsyncClient
+ ApiClient *helper.ApiAsyncClient
}
diff --git a/generator/util/template.go b/generator/util/template.go
new file mode 100644
index 00000000..7d4c83bf
--- /dev/null
+++ b/generator/util/template.go
@@ -0,0 +1,102 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+ "fmt"
+ "github.com/spf13/cobra"
+ "github.com/stoewer/go-strcase"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+// GenerateAllFormatVar fill all format var into values
+func GenerateAllFormatVar(values map[string]string, baseVarName, baseValue
string) {
+ values[strcase.LowerCamelCase(baseVarName)] =
strcase.LowerCamelCase(baseValue)
+ values[strcase.UpperCamelCase(baseVarName)] =
strcase.UpperCamelCase(baseValue)
+ values[strcase.SnakeCase(baseVarName)] = strcase.SnakeCase(baseValue)
+ values[strcase.UpperSnakeCase(baseVarName)] =
strcase.UpperSnakeCase(baseValue)
+ values[strcase.KebabCase(baseVarName)] = strcase.KebabCase(baseValue)
+ values[strcase.UpperKebabCase(baseVarName)] =
strcase.UpperKebabCase(baseValue)
+}
+
+// ReadTemplate read a file to string
+func ReadTemplate(templateFile string) string {
+ f, err := ioutil.ReadFile(templateFile)
+ cobra.CheckErr(err)
+ return string(f)
+}
+
+// WriteTemplates write some strings to files
+func WriteTemplates(path string, templates map[string]string) {
+ err := os.MkdirAll(path, 0777)
+ cobra.CheckErr(err)
+ for name, template := range templates {
+ err := os.MkdirAll(filepath.Dir(filepath.Join(path, name)),
0777)
+ cobra.CheckErr(err)
+ err = ioutil.WriteFile(filepath.Join(path, name),
[]byte(template), 0777)
+ cobra.CheckErr(err)
+ println(filepath.Join(path, name), ` generated`)
+ }
+}
+
+// ReplaceVarInFile replacte var into file without reading
+func ReplaceVarInFile(filename string, reg *regexp.Regexp, new string) {
+ f, err := ioutil.ReadFile(filename)
+ cobra.CheckErr(err)
+ f = reg.ReplaceAll(f, []byte(new))
+
+ err = ioutil.WriteFile(filename, f, 0777)
+ cobra.CheckErr(err)
+ println(filename, ` updated`)
+}
+
+// DetectExistVars filter the used vars in templates
+func DetectExistVars(templates map[string]string, values map[string]string)
(newValues map[string]string) {
+ newValues = map[string]string{}
+ for varName, value := range values {
+ for _, template := range templates {
+ if strings.Contains(template, varName) {
+ newValues[varName] = value
+ break
+ }
+ }
+ }
+ return newValues
+}
+
+// ReplaceVarInTemplates replace var with templates into templates
+func ReplaceVarInTemplates(templates map[string]string, valueMap
map[string]string) {
+ for i, template := range templates {
+ templates[i] = ReplaceVars(template, valueMap)
+ }
+}
+
+func ReplaceVars(s string, valueMap map[string]string) string {
+ for varName, value := range valueMap {
+ s = ReplaceVar(s, varName, value)
+ }
+ return s
+}
+
+func ReplaceVar(s, varName, value string) string {
+ return strings.ReplaceAll(s, fmt.Sprintf(`{{ .%s }}`, varName), value)
+}
diff --git a/go.mod b/go.mod
index 00d0b4ce..38ce2129 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,7 @@ require (
github.com/robfig/cron/v3 v3.0.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/afero v1.6.0
- github.com/spf13/cobra v1.2.1
+ github.com/spf13/cobra v1.5.0
github.com/spf13/viper v1.8.1
github.com/stretchr/testify v1.7.0
github.com/swaggo/gin-swagger v1.4.3
@@ -37,6 +37,8 @@ require (
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 //
indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
+ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e //
indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denisenkom/go-mssqldb v0.10.0 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
@@ -79,6 +81,7 @@ require (
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 //
indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
+ github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mattn/go-sqlite3 v1.14.6 // indirect
@@ -92,10 +95,12 @@ require (
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/robfig/cron v1.2.0 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.6-0.20200504143853-81378bbcd8a1 // indirect
+ github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/stretchr/objx v0.3.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/ugorji/go/codec v1.2.6 // indirect
diff --git a/go.sum b/go.sum
index b9e4de6d..217f9ee8 100644
--- a/go.sum
+++ b/go.sum
@@ -71,6 +71,7 @@ github.com/bketelsen/crypt v0.0.4/go.mod
h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqO
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod
h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod
h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod
h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod
h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod
h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -89,6 +90,8 @@ github.com/coreos/go-systemd
v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7
github.com/coreos/go-systemd/v22 v22.3.2/go.mod
h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod
h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod
h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.2
h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod
h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod
h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -408,6 +411,8 @@ github.com/mailru/easyjson
v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod
h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6
h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod
h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/manifoldco/promptui v0.9.0
h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
+github.com/manifoldco/promptui v0.9.0/go.mod
h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
github.com/matryer/is v1.2.0/go.mod
h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattn/go-colorable v0.0.9/go.mod
h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -493,6 +498,8 @@ github.com/rs/xid v1.2.1/go.mod
h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod
h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod
h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0
h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod
h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/satori/go.uuid v1.2.0/go.mod
h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod
h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
@@ -520,6 +527,8 @@ github.com/spf13/cast v1.4.1
h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cast v1.4.1/go.mod
h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
github.com/spf13/cobra v1.2.1/go.mod
h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
+github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
+github.com/spf13/cobra v1.5.0/go.mod
h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/jwalterweatherman v1.1.0
h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod
h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5/go.mod
h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -527,6 +536,8 @@ github.com/spf13/pflag v1.0.6-0.20200504143853-81378bbcd8a1
h1:zrNp7OPtn2fjeNHI9
github.com/spf13/pflag v1.0.6-0.20200504143853-81378bbcd8a1/go.mod
h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
github.com/spf13/viper v1.8.1/go.mod
h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
+github.com/stoewer/go-strcase v1.2.0
h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
+github.com/stoewer/go-strcase v1.2.0/go.mod
h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod
h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
@@ -724,6 +735,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod
h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=