diff --git a/cmd/asciidoc.go b/cmd/asciidoc.go deleted file mode 100644 index 7d32f4e..0000000 --- a/cmd/asciidoc.go +++ /dev/null @@ -1,48 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var asciidocCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "asciidoc [PATH]", - Aliases: []string{"adoc"}, - Short: "Generate AsciiDoc of inputs and outputs", - Annotations: formatAnnotations("asciidoc"), - RunE: formatRunE, -} - -var asciidocTableCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "table [PATH]", - Aliases: []string{"tbl"}, - Short: "Generate AsciiDoc tables of inputs and outputs", - Annotations: formatAnnotations("asciidoc table"), - RunE: formatRunE, -} - -var asciidocDocumentCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "document [PATH]", - Aliases: []string{"doc"}, - Short: "Generate AsciiDoc document of inputs and outputs", - Annotations: formatAnnotations("asciidoc document"), - RunE: formatRunE, -} - -func init() { - asciidocCmd.PersistentFlags().BoolVar(new(bool), "no-required", false, "do not show \"Required\" column or section") - asciidocCmd.PersistentFlags().BoolVar(new(bool), "no-sensitive", false, "do not show \"Sensitive\" column or section") - asciidocCmd.PersistentFlags().MarkDeprecated("no-required", "use '--required=false' instead") //nolint:errcheck - asciidocCmd.PersistentFlags().MarkDeprecated("no-sensitive", "use '--sensitive=false' instead") //nolint:errcheck - - asciidocCmd.PersistentFlags().BoolVar(&settings.ShowRequired, "required", true, "show \"Required\" column or section") - asciidocCmd.PersistentFlags().BoolVar(&settings.ShowSensitivity, "sensitive", true, "show \"Sensitive\" column or section") - asciidocCmd.PersistentFlags().IntVar(&settings.IndentLevel, "indent", 2, "indention level of AsciiDoc sections [1, 2, 3, 4, 5]") - - asciidocCmd.AddCommand(asciidocTableCmd) - asciidocCmd.AddCommand(asciidocDocumentCmd) - - rootCmd.AddCommand(asciidocCmd) -} diff --git a/cmd/asciidoc/asciidoc.go b/cmd/asciidoc/asciidoc.go new file mode 100644 index 0000000..55a60bf --- /dev/null +++ b/cmd/asciidoc/asciidoc.go @@ -0,0 +1,39 @@ +package asciidoc + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/cmd/asciidoc/document" + "github.com/segmentio/terraform-docs/cmd/asciidoc/table" + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'asciidoc' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "asciidoc [PATH]", + Aliases: []string{"adoc"}, + Short: "Generate AsciiDoc of inputs and outputs", + Annotations: cli.Annotations("asciidoc"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + + // flags + cmd.PersistentFlags().BoolVar(&config.Settings.Required, "required", true, "show \"Required\" column or section") + cmd.PersistentFlags().BoolVar(&config.Settings.Sensitive, "sensitive", true, "show \"Sensitive\" column or section") + cmd.PersistentFlags().IntVar(&config.Settings.Indent, "indent", 2, "indention level of AsciiDoc sections [1, 2, 3, 4, 5]") + + // deprecation + cmd.PersistentFlags().BoolVar(new(bool), "no-required", false, "do not show \"Required\" column or section") + cmd.PersistentFlags().BoolVar(new(bool), "no-sensitive", false, "do not show \"Sensitive\" column or section") + cmd.PersistentFlags().MarkDeprecated("no-required", "use '--required=false' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-sensitive", "use '--sensitive=false' instead") //nolint:errcheck + + // subcommands + cmd.AddCommand(document.NewCommand(config)) + cmd.AddCommand(table.NewCommand(config)) + + return cmd +} diff --git a/cmd/asciidoc/document/document.go b/cmd/asciidoc/document/document.go new file mode 100644 index 0000000..e372ab3 --- /dev/null +++ b/cmd/asciidoc/document/document.go @@ -0,0 +1,21 @@ +package document + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'asciidoc document' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "document [PATH]", + Aliases: []string{"doc"}, + Short: "Generate AsciiDoc document of inputs and outputs", + Annotations: cli.Annotations("asciidoc document"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/asciidoc/table/table.go b/cmd/asciidoc/table/table.go new file mode 100644 index 0000000..71e2698 --- /dev/null +++ b/cmd/asciidoc/table/table.go @@ -0,0 +1,21 @@ +package table + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'asciidoc table' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "table [PATH]", + Aliases: []string{"tbl"}, + Short: "Generate AsciiDoc tables of inputs and outputs", + Annotations: cli.Annotations("asciidoc table"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/completion.go b/cmd/completion.go deleted file mode 100644 index 02ef981..0000000 --- a/cmd/completion.go +++ /dev/null @@ -1,40 +0,0 @@ -package cmd - -import ( - "os" - - "github.com/spf13/cobra" -) - -var completionCmd = &cobra.Command{ - Args: cobra.NoArgs, - Use: "completion SHELL", - Short: "Generate autocomplete for terraform-docs", - Long: "Generate autocomplete for terraform-docs", -} - -var bashCompletionCmd = &cobra.Command{ - Args: cobra.NoArgs, - Use: "bash", - Short: "Generate autocomplete for bash", - Long: "Generate autocomplete for bash", - Run: func(cmd *cobra.Command, args []string) { - _ = rootCmd.GenBashCompletion(os.Stdout) - }, -} -var zshCompletionCmd = &cobra.Command{ - Args: cobra.NoArgs, - Use: "zsh", - Short: "Generate autocomplete for zsh", - Long: "Generate autocomplete for zsh", - Run: func(cmd *cobra.Command, args []string) { - _ = rootCmd.GenZshCompletion(os.Stdout) - }, -} - -func init() { - completionCmd.AddCommand(bashCompletionCmd) - completionCmd.AddCommand(zshCompletionCmd) - - rootCmd.AddCommand(completionCmd) -} diff --git a/cmd/completion/bash/bash.go b/cmd/completion/bash/bash.go new file mode 100644 index 0000000..6afbaad --- /dev/null +++ b/cmd/completion/bash/bash.go @@ -0,0 +1,20 @@ +package bash + +import ( + "os" + + "github.com/spf13/cobra" +) + +// NewCommand returns a new cobra.Command for 'completion bash' command +func NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.NoArgs, + Use: "bash", + Short: "Generate shell completion for bash", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Parent().Parent().GenBashCompletion(os.Stdout) + }, + } + return cmd +} diff --git a/cmd/completion/completion.go b/cmd/completion/completion.go new file mode 100644 index 0000000..aad7744 --- /dev/null +++ b/cmd/completion/completion.go @@ -0,0 +1,40 @@ +package completion + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/cmd/completion/bash" + "github.com/segmentio/terraform-docs/cmd/completion/zsh" +) + +// NewCommand returns a new cobra.Command for 'completion' command +func NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.NoArgs, + Use: "completion SHELL", + Short: "Generate shell completion code for the specified shell (bash or zsh)", + Long: longDescription, + } + + // subcommands + cmd.AddCommand(bash.NewCommand()) + cmd.AddCommand(zsh.NewCommand()) + + return cmd +} + +const longDescription = `Outputs terraform-doc shell completion for the given shell (bash or zsh) +This depends on the bash-completion binary. Example installation instructions: +# for bash users + $ terraform-doc completion bash > ~/.terraform-doc-completion + $ source ~/.terraform-doc-completion + +# for zsh users + % terraform-doc completion zsh > /usr/local/share/zsh/site-functions/_terraform-doc + % autoload -U compinit && compinit +# or if zsh-completion is installed via homebrew + % terraform-doc completion zsh > "${fpath[1]}/_terraform-doc" + +Additionally, you may want to output the completion to a file and source in your .bashrc +Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2 +` diff --git a/cmd/completion/zsh/zsh.go b/cmd/completion/zsh/zsh.go new file mode 100644 index 0000000..7d9b3f1 --- /dev/null +++ b/cmd/completion/zsh/zsh.go @@ -0,0 +1,20 @@ +package zsh + +import ( + "os" + + "github.com/spf13/cobra" +) + +// NewCommand returns a new cobra.Command for 'completion zsh' command +func NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.NoArgs, + Use: "zsh", + Short: "Generate shel completion for zsh", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Parent().Parent().GenZshCompletion(os.Stdout) + }, + } + return cmd +} diff --git a/cmd/json.go b/cmd/json.go deleted file mode 100644 index 0af02f2..0000000 --- a/cmd/json.go +++ /dev/null @@ -1,22 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var jsonCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "json [PATH]", - Short: "Generate JSON of inputs and outputs", - Annotations: formatAnnotations("json"), - RunE: formatRunE, -} - -func init() { - jsonCmd.PersistentFlags().BoolVar(new(bool), "no-escape", false, "do not escape special characters") - jsonCmd.PersistentFlags().MarkDeprecated("no-escape", "use '--escape=false' instead") //nolint:errcheck - - jsonCmd.PersistentFlags().BoolVar(&settings.EscapeCharacters, "escape", true, "escape special characters") - - rootCmd.AddCommand(jsonCmd) -} diff --git a/cmd/json/json.go b/cmd/json/json.go new file mode 100644 index 0000000..72975a0 --- /dev/null +++ b/cmd/json/json.go @@ -0,0 +1,28 @@ +package json + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'json' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "json [PATH]", + Short: "Generate JSON of inputs and outputs", + Annotations: cli.Annotations("json"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + + // flags + cmd.PersistentFlags().BoolVar(&config.Settings.Escape, "escape", true, "escape special characters") + + // deprecation + cmd.PersistentFlags().BoolVar(new(bool), "no-escape", false, "do not escape special characters") + cmd.PersistentFlags().MarkDeprecated("no-escape", "use '--escape=false' instead") //nolint:errcheck + + return cmd +} diff --git a/cmd/markdown.go b/cmd/markdown.go deleted file mode 100644 index 7ab8230..0000000 --- a/cmd/markdown.go +++ /dev/null @@ -1,51 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var markdownCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "markdown [PATH]", - Aliases: []string{"md"}, - Short: "Generate Markdown of inputs and outputs", - Annotations: formatAnnotations("markdown"), - RunE: formatRunE, -} - -var markdownTableCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "table [PATH]", - Aliases: []string{"tbl"}, - Short: "Generate Markdown tables of inputs and outputs", - Annotations: formatAnnotations("markdown table"), - RunE: formatRunE, -} - -var markdownDocumentCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "document [PATH]", - Aliases: []string{"doc"}, - Short: "Generate Markdown document of inputs and outputs", - Annotations: formatAnnotations("markdown document"), - RunE: formatRunE, -} - -func init() { - markdownCmd.PersistentFlags().BoolVar(new(bool), "no-required", false, "do not show \"Required\" column or section") - markdownCmd.PersistentFlags().BoolVar(new(bool), "no-sensitive", false, "do not show \"Sensitive\" column or section") - markdownCmd.PersistentFlags().BoolVar(new(bool), "no-escape", false, "do not escape special characters") - markdownCmd.PersistentFlags().MarkDeprecated("no-required", "use '--required=false' instead") //nolint:errcheck - markdownCmd.PersistentFlags().MarkDeprecated("no-sensitive", "use '--sensitive=false' instead") //nolint:errcheck - markdownCmd.PersistentFlags().MarkDeprecated("no-escape", "use '--escape=false' instead") //nolint:errcheck - - markdownCmd.PersistentFlags().BoolVar(&settings.ShowRequired, "required", true, "show \"Required\" column or section") - markdownCmd.PersistentFlags().BoolVar(&settings.ShowSensitivity, "sensitive", true, "show \"Sensitive\" column or section") - markdownCmd.PersistentFlags().BoolVar(&settings.EscapeCharacters, "escape", true, "escape special characters") - markdownCmd.PersistentFlags().IntVar(&settings.IndentLevel, "indent", 2, "indention level of Markdown sections [1, 2, 3, 4, 5]") - - markdownCmd.AddCommand(markdownTableCmd) - markdownCmd.AddCommand(markdownDocumentCmd) - - rootCmd.AddCommand(markdownCmd) -} diff --git a/cmd/markdown/document/document.go b/cmd/markdown/document/document.go new file mode 100644 index 0000000..dbfc6eb --- /dev/null +++ b/cmd/markdown/document/document.go @@ -0,0 +1,21 @@ +package document + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'markdown document' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "document [PATH]", + Aliases: []string{"doc"}, + Short: "Generate Markdown document of inputs and outputs", + Annotations: cli.Annotations("markdown document"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/markdown/markdown.go b/cmd/markdown/markdown.go new file mode 100644 index 0000000..7d95d47 --- /dev/null +++ b/cmd/markdown/markdown.go @@ -0,0 +1,42 @@ +package markdown + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/cmd/markdown/document" + "github.com/segmentio/terraform-docs/cmd/markdown/table" + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'markdown' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "markdown [PATH]", + Aliases: []string{"md"}, + Short: "Generate Markdown of inputs and outputs", + Annotations: cli.Annotations("markdown"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + + // flags + cmd.PersistentFlags().BoolVar(&config.Settings.Required, "required", true, "show \"Required\" column or section") + cmd.PersistentFlags().BoolVar(&config.Settings.Sensitive, "sensitive", true, "show \"Sensitive\" column or section") + cmd.PersistentFlags().BoolVar(&config.Settings.Escape, "escape", true, "escape special characters") + cmd.PersistentFlags().IntVar(&config.Settings.Indent, "indent", 2, "indention level of Markdown sections [1, 2, 3, 4, 5]") + + // deprecation + cmd.PersistentFlags().BoolVar(new(bool), "no-required", false, "do not show \"Required\" column or section") + cmd.PersistentFlags().BoolVar(new(bool), "no-sensitive", false, "do not show \"Sensitive\" column or section") + cmd.PersistentFlags().BoolVar(new(bool), "no-escape", false, "do not escape special characters") + cmd.PersistentFlags().MarkDeprecated("no-required", "use '--required=false' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-sensitive", "use '--sensitive=false' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-escape", "use '--escape=false' instead") //nolint:errcheck + + // subcommands + cmd.AddCommand(document.NewCommand(config)) + cmd.AddCommand(table.NewCommand(config)) + + return cmd +} diff --git a/cmd/markdown/table/table.go b/cmd/markdown/table/table.go new file mode 100644 index 0000000..ce383a5 --- /dev/null +++ b/cmd/markdown/table/table.go @@ -0,0 +1,21 @@ +package table + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'markdown table' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "table [PATH]", + Aliases: []string{"tbl"}, + Short: "Generate Markdown tables of inputs and outputs", + Annotations: cli.Annotations("markdown table"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/pretty.go b/cmd/pretty.go deleted file mode 100644 index d7efd04..0000000 --- a/cmd/pretty.go +++ /dev/null @@ -1,22 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var prettyCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "pretty [PATH]", - Short: "Generate colorized pretty of inputs and outputs", - Annotations: formatAnnotations("pretty"), - RunE: formatRunE, -} - -func init() { - prettyCmd.PersistentFlags().BoolVar(new(bool), "no-color", false, "do not colorize printed result") - prettyCmd.PersistentFlags().MarkDeprecated("no-color", "use '--color=false' instead") //nolint:errcheck - - prettyCmd.PersistentFlags().BoolVar(&settings.ShowColor, "color", true, "colorize printed result") - - rootCmd.AddCommand(prettyCmd) -} diff --git a/cmd/pretty/pretty.go b/cmd/pretty/pretty.go new file mode 100644 index 0000000..748111b --- /dev/null +++ b/cmd/pretty/pretty.go @@ -0,0 +1,28 @@ +package pretty + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for pretty formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "pretty [PATH]", + Short: "Generate colorized pretty of inputs and outputs", + Annotations: cli.Annotations("pretty"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + + // flags + cmd.PersistentFlags().BoolVar(&config.Settings.Color, "color", true, "colorize printed result") + + // deprecation + cmd.PersistentFlags().BoolVar(new(bool), "no-color", false, "do not colorize printed result") + cmd.PersistentFlags().MarkDeprecated("no-color", "use '--color=false' instead") //nolint:errcheck + + return cmd +} diff --git a/cmd/root.go b/cmd/root.go index a14d77a..1289a3f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,180 +2,85 @@ package cmd import ( "fmt" - "strings" "github.com/spf13/cobra" - "github.com/segmentio/terraform-docs/internal/format" - "github.com/segmentio/terraform-docs/internal/module" - "github.com/segmentio/terraform-docs/internal/version" - "github.com/segmentio/terraform-docs/pkg/print" + "github.com/segmentio/terraform-docs/cmd/asciidoc" + "github.com/segmentio/terraform-docs/cmd/completion" + "github.com/segmentio/terraform-docs/cmd/json" + "github.com/segmentio/terraform-docs/cmd/markdown" + "github.com/segmentio/terraform-docs/cmd/pretty" + "github.com/segmentio/terraform-docs/cmd/tfvars" + "github.com/segmentio/terraform-docs/cmd/toml" + "github.com/segmentio/terraform-docs/cmd/version" + "github.com/segmentio/terraform-docs/cmd/xml" + "github.com/segmentio/terraform-docs/cmd/yaml" + "github.com/segmentio/terraform-docs/internal/cli" ) -var hides []string -var settings = print.NewSettings() -var options = module.NewOptions() - -var rootCmd = &cobra.Command{ - Args: cobra.NoArgs, - Use: "terraform-docs", - Short: "A utility to generate documentation from Terraform modules in various output formats", - Long: "A utility to generate documentation from Terraform modules in various output formats", - Version: version.Version(), - SilenceUsage: true, - SilenceErrors: true, - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - oppositeBool := func(name string) bool { - val, _ := cmd.Flags().GetBool(name) - return !val - } - - for _, h := range hides { - switch h { - case "header": - case "inputs": - case "outputs": - case "providers": - case "requirements": - default: - return fmt.Errorf("'%s' is not a valid section to hide, available options [header, inputs, outputs, providers, requirements]", h) - } - } - - if len(hides) > 0 && contains("header") { - settings.ShowHeader = false - } else { - settings.ShowHeader = oppositeBool("no-header") - } - options.ShowHeader = settings.ShowHeader - - if len(hides) > 0 && contains("inputs") { - settings.ShowInputs = false - } else { - settings.ShowInputs = oppositeBool("no-inputs") - } - if len(hides) > 0 && contains("outputs") { - settings.ShowOutputs = false - } else { - settings.ShowOutputs = oppositeBool("no-outputs") - } - if len(hides) > 0 && contains("providers") { - settings.ShowProviders = false - } else { - settings.ShowProviders = oppositeBool("no-providers") - } - if len(hides) > 0 && contains("requirements") { - settings.ShowRequirements = false - } else { - settings.ShowRequirements = oppositeBool("no-requirements") - } - - settings.OutputValues = options.OutputValues - - if !cmd.Flags().Changed("color") { - settings.ShowColor = oppositeBool("no-color") - } - if !cmd.Flags().Changed("sort") { - settings.SortByName = oppositeBool("no-sort") - } - if !cmd.Flags().Changed("required") { - settings.ShowRequired = oppositeBool("no-required") - } - if !cmd.Flags().Changed("escape") { - settings.EscapeCharacters = oppositeBool("no-escape") - } - if !cmd.Flags().Changed("sensitive") { - settings.ShowSensitivity = oppositeBool("no-sensitive") - } - - return nil - }, -} - -func init() { - rootCmd.PersistentFlags().StringSliceVar(&hides, "hide", []string{}, "hide section [header, inputs, outputs, providers, requirements]") - - rootCmd.PersistentFlags().BoolVar(new(bool), "no-header", false, "do not show module header") - rootCmd.PersistentFlags().BoolVar(new(bool), "no-inputs", false, "do not show inputs") - rootCmd.PersistentFlags().BoolVar(new(bool), "no-outputs", false, "do not show outputs") - rootCmd.PersistentFlags().BoolVar(new(bool), "no-providers", false, "do not show providers") - rootCmd.PersistentFlags().BoolVar(new(bool), "no-requirements", false, "do not show module requirements") - - rootCmd.PersistentFlags().BoolVar(new(bool), "no-sort", false, "do no sort items") - rootCmd.PersistentFlags().BoolVar(&settings.SortByName, "sort", true, "sort items") - rootCmd.PersistentFlags().BoolVar(&settings.SortByRequired, "sort-by-required", false, "sort items by name and print required ones first (default false)") - rootCmd.PersistentFlags().BoolVar(&settings.SortByType, "sort-by-type", false, "sort items by type of them (default false)") - - rootCmd.PersistentFlags().StringVar(&options.HeaderFromFile, "header-from", "main.tf", "relative path of a file to read header from") - - rootCmd.PersistentFlags().BoolVar(&options.OutputValues, "output-values", false, "inject output values into outputs (default false)") - rootCmd.PersistentFlags().StringVar(&options.OutputValuesPath, "output-values-from", "", "inject output values from file into outputs") - - rootCmd.PersistentFlags().MarkDeprecated("no-header", "use '--hide header' instead") //nolint:errcheck - rootCmd.PersistentFlags().MarkDeprecated("no-inputs", "use '--hide inputs' instead") //nolint:errcheck - rootCmd.PersistentFlags().MarkDeprecated("no-outputs", "use '--hide outputs' instead") //nolint:errcheck - rootCmd.PersistentFlags().MarkDeprecated("no-providers", "use '--hide providers' instead") //nolint:errcheck - rootCmd.PersistentFlags().MarkDeprecated("no-requirements", "use '--hide requirements' instead") //nolint:errcheck - rootCmd.PersistentFlags().MarkDeprecated("no-sort", "use '--sort=false' instead") //nolint:errcheck -} - // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() error { - if err := rootCmd.Execute(); err != nil { + if err := NewCommand().Execute(); err != nil { fmt.Printf("Error: %s\n", err.Error()) + return err } return nil } -// RootCmd represents the base command when called without any subcommands -func RootCmd() *cobra.Command { - return rootCmd -} +// NewCommand returns a new cobra.Command for 'root' command +func NewCommand() *cobra.Command { + config := cli.DefaultConfig() + cmd := &cobra.Command{ + Args: cobra.NoArgs, + Use: "terraform-docs", + Short: "A utility to generate documentation from Terraform modules in various output formats", + Long: "A utility to generate documentation from Terraform modules in various output formats", + Version: version.Full(), + SilenceUsage: true, + SilenceErrors: true, + } -func contains(section string) bool { - for _, h := range hides { - if h == section { - return true - } - } - return false -} + // flags + cmd.PersistentFlags().StringSliceVar(&config.Sections.Hide, "hide", []string{}, "hide section [header, inputs, outputs, providers, requirements]") -var formatRunE = func(cmd *cobra.Command, args []string) error { - name := strings.Replace(cmd.CommandPath(), "terraform-docs ", "", -1) - printer, err := format.Factory(name, settings) - if err != nil { - return err - } - _, err = options.With(&module.Options{ - Path: args[0], - SortBy: &module.SortBy{ - Name: settings.SortByName, - Required: settings.SortByRequired, - Type: settings.SortByType, - }, - }) - if err != nil { - return err - } - tfmodule, err := module.LoadWithOptions(options) - if err != nil { - return err - } - output, err := printer.Print(tfmodule, settings) - if err != nil { - return err - } - fmt.Println(output) - return nil -} + cmd.PersistentFlags().BoolVar(&config.Sort.Enabled, "sort", true, "sort items") + cmd.PersistentFlags().BoolVar(&config.Sort.By.Required, "sort-by-required", false, "sort items by name and print required ones first (default false)") + cmd.PersistentFlags().BoolVar(&config.Sort.By.Type, "sort-by-type", false, "sort items by type of them (default false)") -var formatAnnotations = func(cmd string) map[string]string { - annotations := make(map[string]string) - for _, s := range strings.Split(cmd, " ") { - annotations["command"] = s - } - annotations["kind"] = "formatter" - return annotations + cmd.PersistentFlags().StringVar(&config.HeaderFrom, "header-from", "main.tf", "relative path of a file to read header from") + + cmd.PersistentFlags().BoolVar(&config.OutputValues.Enabled, "output-values", false, "inject output values into outputs (default false)") + cmd.PersistentFlags().StringVar(&config.OutputValues.From, "output-values-from", "", "inject output values from file into outputs (default \"\")") + + // deprecation + cmd.PersistentFlags().BoolVar(new(bool), "no-header", false, "do not show module header") + cmd.PersistentFlags().BoolVar(new(bool), "no-inputs", false, "do not show inputs") + cmd.PersistentFlags().BoolVar(new(bool), "no-outputs", false, "do not show outputs") + cmd.PersistentFlags().BoolVar(new(bool), "no-providers", false, "do not show providers") + cmd.PersistentFlags().BoolVar(new(bool), "no-requirements", false, "do not show module requirements") + cmd.PersistentFlags().BoolVar(new(bool), "no-sort", false, "do no sort items") + + cmd.PersistentFlags().MarkDeprecated("no-header", "use '--hide header' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-inputs", "use '--hide inputs' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-outputs", "use '--hide outputs' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-providers", "use '--hide providers' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-requirements", "use '--hide requirements' instead") //nolint:errcheck + cmd.PersistentFlags().MarkDeprecated("no-sort", "use '--sort=false' instead") //nolint:errcheck + + // formatter subcommands + cmd.AddCommand(asciidoc.NewCommand(config)) + cmd.AddCommand(json.NewCommand(config)) + cmd.AddCommand(markdown.NewCommand(config)) + cmd.AddCommand(pretty.NewCommand(config)) + cmd.AddCommand(tfvars.NewCommand(config)) + cmd.AddCommand(toml.NewCommand(config)) + cmd.AddCommand(xml.NewCommand(config)) + cmd.AddCommand(yaml.NewCommand(config)) + + // other subcommands + cmd.AddCommand(completion.NewCommand()) + cmd.AddCommand(version.NewCommand()) + + return cmd } diff --git a/cmd/tfvars.go b/cmd/tfvars.go deleted file mode 100644 index c988e6b..0000000 --- a/cmd/tfvars.go +++ /dev/null @@ -1,35 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var tfvarsCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "tfvars [PATH]", - Short: "Generate terraform.tfvars of inputs", - Annotations: formatAnnotations("tfvars"), -} - -var tfvarsHCLCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "hcl [PATH]", - Short: "Generate HCL format of terraform.tfvars of inputs", - Annotations: formatAnnotations("tfvars hcl"), - RunE: formatRunE, -} - -var tfvarsJSONCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "json [PATH]", - Short: "Generate JSON format of terraform.tfvars of inputs", - Annotations: formatAnnotations("tfvars json"), - RunE: formatRunE, -} - -func init() { - tfvarsCmd.AddCommand(tfvarsHCLCmd) - tfvarsCmd.AddCommand(tfvarsJSONCmd) - - rootCmd.AddCommand(tfvarsCmd) -} diff --git a/cmd/tfvars/hcl/hcl.go b/cmd/tfvars/hcl/hcl.go new file mode 100644 index 0000000..f67c9bf --- /dev/null +++ b/cmd/tfvars/hcl/hcl.go @@ -0,0 +1,20 @@ +package hcl + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'tfvars hcl' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "hcl [PATH]", + Short: "Generate HCL format of terraform.tfvars of inputs", + Annotations: cli.Annotations("tfvars hcl"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/tfvars/json/json.go b/cmd/tfvars/json/json.go new file mode 100644 index 0000000..ce0caa4 --- /dev/null +++ b/cmd/tfvars/json/json.go @@ -0,0 +1,20 @@ +package json + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'tfvars json' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "json [PATH]", + Short: "Generate JSON format of terraform.tfvars of inputs", + Annotations: cli.Annotations("tfvars json"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/tfvars/tfvars.go b/cmd/tfvars/tfvars.go new file mode 100644 index 0000000..f878458 --- /dev/null +++ b/cmd/tfvars/tfvars.go @@ -0,0 +1,25 @@ +package tfvars + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/cmd/tfvars/hcl" + "github.com/segmentio/terraform-docs/cmd/tfvars/json" + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'tfvars' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "tfvars [PATH]", + Short: "Generate terraform.tfvars of inputs", + Annotations: cli.Annotations("tfvars"), + } + + // subcommands + cmd.AddCommand(hcl.NewCommand(config)) + cmd.AddCommand(json.NewCommand(config)) + + return cmd +} diff --git a/cmd/toml.go b/cmd/toml.go deleted file mode 100644 index ffda6c0..0000000 --- a/cmd/toml.go +++ /dev/null @@ -1,17 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var tomlCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "toml [PATH]", - Short: "Generate TOML of inputs and outputs", - Annotations: formatAnnotations("toml"), - RunE: formatRunE, -} - -func init() { - rootCmd.AddCommand(tomlCmd) -} diff --git a/cmd/toml/toml.go b/cmd/toml/toml.go new file mode 100644 index 0000000..bef6d73 --- /dev/null +++ b/cmd/toml/toml.go @@ -0,0 +1,20 @@ +package toml + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'toml' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "toml [PATH]", + Short: "Generate TOML of inputs and outputs", + Annotations: cli.Annotations("toml"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/version.go b/cmd/version.go deleted file mode 100644 index a2795cd..0000000 --- a/cmd/version.go +++ /dev/null @@ -1,22 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/segmentio/terraform-docs/internal/version" -) - -var versionCmd = &cobra.Command{ - Args: cobra.NoArgs, - Use: "version", - Short: "Print the version number of terraform-docs", - Run: func(cmd *cobra.Command, args []string) { - fmt.Print(fmt.Sprintf("terraform-docs version %s\n", version.Version())) - }, -} - -func init() { - rootCmd.AddCommand(versionCmd) -} diff --git a/cmd/version/version.go b/cmd/version/version.go new file mode 100644 index 0000000..806df79 --- /dev/null +++ b/cmd/version/version.go @@ -0,0 +1,27 @@ +package version + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/version" +) + +// NewCommand returns a new cobra.Command for 'version' command +func NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.NoArgs, + Use: "version", + Short: "Print the version number of terraform-docs", + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("terraform-docs version %s\n", Full()) + }, + } + return cmd +} + +// Full returns the full version of the binary +func Full() string { + return version.Full() +} diff --git a/cmd/xml.go b/cmd/xml.go deleted file mode 100644 index 38f4937..0000000 --- a/cmd/xml.go +++ /dev/null @@ -1,17 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var xmlCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "xml [PATH]", - Short: "Generate XML of inputs and outputs", - Annotations: formatAnnotations("xml"), - RunE: formatRunE, -} - -func init() { - rootCmd.AddCommand(xmlCmd) -} diff --git a/cmd/xml/xml.go b/cmd/xml/xml.go new file mode 100644 index 0000000..58a4db1 --- /dev/null +++ b/cmd/xml/xml.go @@ -0,0 +1,20 @@ +package xml + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'xml' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "xml [PATH]", + Short: "Generate XML of inputs and outputs", + Annotations: cli.Annotations("xml"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/cmd/yaml.go b/cmd/yaml.go deleted file mode 100644 index 1433132..0000000 --- a/cmd/yaml.go +++ /dev/null @@ -1,17 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var yamlCmd = &cobra.Command{ - Args: cobra.ExactArgs(1), - Use: "yaml [PATH]", - Short: "Generate YAML of inputs and outputs", - Annotations: formatAnnotations("yaml"), - RunE: formatRunE, -} - -func init() { - rootCmd.AddCommand(yamlCmd) -} diff --git a/cmd/yaml/yaml.go b/cmd/yaml/yaml.go new file mode 100644 index 0000000..5f80c27 --- /dev/null +++ b/cmd/yaml/yaml.go @@ -0,0 +1,20 @@ +package yaml + +import ( + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/cli" +) + +// NewCommand returns a new cobra.Command for 'yaml' formatter +func NewCommand(config *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Args: cobra.ExactArgs(1), + Use: "yaml [PATH]", + Short: "Generate YAML of inputs and outputs", + Annotations: cli.Annotations("yaml"), + PreRunE: cli.PreRunEFunc(config), + RunE: cli.RunEFunc(config), + } + return cmd +} diff --git a/docs/FORMATS_GUIDE.md b/docs/FORMATS_GUIDE.md index b13d2d5..2679f2d 100644 --- a/docs/FORMATS_GUIDE.md +++ b/docs/FORMATS_GUIDE.md @@ -13,7 +13,7 @@ A utility to generate documentation from Terraform modules in various output for -h, --help help for terraform-docs --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -36,4 +36,4 @@ A utility to generate documentation from Terraform modules in various output for * [terraform-docs xml](/docs/formats/xml.md) - Generate XML of inputs and outputs * [terraform-docs yaml](/docs/formats/yaml.md) - Generate YAML of inputs and outputs -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/asciidoc-document.md b/docs/formats/asciidoc-document.md index 8e4e1f8..30f8cbb 100644 --- a/docs/formats/asciidoc-document.md +++ b/docs/formats/asciidoc-document.md @@ -23,7 +23,7 @@ terraform-docs asciidoc document [PATH] [flags] --hide strings hide section [header, inputs, outputs, providers, requirements] --indent int indention level of AsciiDoc sections [1, 2, 3, 4, 5] (default 2) --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --required show "Required" column or section (default true) --sensitive show "Sensitive" column or section (default true) --sort sort items (default true) @@ -416,4 +416,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/asciidoc-table.md b/docs/formats/asciidoc-table.md index 1a5f661..2fba3cd 100644 --- a/docs/formats/asciidoc-table.md +++ b/docs/formats/asciidoc-table.md @@ -23,7 +23,7 @@ terraform-docs asciidoc table [PATH] [flags] --hide strings hide section [header, inputs, outputs, providers, requirements] --indent int indention level of AsciiDoc sections [1, 2, 3, 4, 5] (default 2) --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --required show "Required" column or section (default true) --sensitive show "Sensitive" column or section (default true) --sort sort items (default true) @@ -372,4 +372,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/asciidoc.md b/docs/formats/asciidoc.md index 6ba7f7b..88491de 100644 --- a/docs/formats/asciidoc.md +++ b/docs/formats/asciidoc.md @@ -25,7 +25,7 @@ terraform-docs asciidoc [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -36,4 +36,4 @@ terraform-docs asciidoc [PATH] [flags] * [terraform-docs asciidoc document](/docs/formats/asciidoc-document.md) - Generate AsciiDoc document of inputs and outputs * [terraform-docs asciidoc table](/docs/formats/asciidoc-table.md) - Generate AsciiDoc tables of inputs and outputs -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/json.md b/docs/formats/json.md index 01b44a7..b6da476 100644 --- a/docs/formats/json.md +++ b/docs/formats/json.md @@ -23,7 +23,7 @@ terraform-docs json [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -335,4 +335,4 @@ generates the following output: } -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/markdown-document.md b/docs/formats/markdown-document.md index e242087..e46b2be 100644 --- a/docs/formats/markdown-document.md +++ b/docs/formats/markdown-document.md @@ -24,7 +24,7 @@ terraform-docs markdown document [PATH] [flags] --hide strings hide section [header, inputs, outputs, providers, requirements] --indent int indention level of Markdown sections [1, 2, 3, 4, 5] (default 2) --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --required show "Required" column or section (default true) --sensitive show "Sensitive" column or section (default true) --sort sort items (default true) @@ -417,4 +417,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/markdown-table.md b/docs/formats/markdown-table.md index 6ec0d1b..1756e9d 100644 --- a/docs/formats/markdown-table.md +++ b/docs/formats/markdown-table.md @@ -24,7 +24,7 @@ terraform-docs markdown table [PATH] [flags] --hide strings hide section [header, inputs, outputs, providers, requirements] --indent int indention level of Markdown sections [1, 2, 3, 4, 5] (default 2) --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --required show "Required" column or section (default true) --sensitive show "Sensitive" column or section (default true) --sort sort items (default true) @@ -143,4 +143,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/markdown.md b/docs/formats/markdown.md index 2d5e909..545ba95 100644 --- a/docs/formats/markdown.md +++ b/docs/formats/markdown.md @@ -26,7 +26,7 @@ terraform-docs markdown [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -37,4 +37,4 @@ terraform-docs markdown [PATH] [flags] * [terraform-docs markdown document](/docs/formats/markdown-document.md) - Generate Markdown document of inputs and outputs * [terraform-docs markdown table](/docs/formats/markdown-table.md) - Generate Markdown tables of inputs and outputs -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/pretty.md b/docs/formats/pretty.md index 05477c3..53ec56e 100644 --- a/docs/formats/pretty.md +++ b/docs/formats/pretty.md @@ -23,7 +23,7 @@ terraform-docs pretty [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -239,4 +239,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/tfvars-hcl.md b/docs/formats/tfvars-hcl.md index ce54fa1..e5c254e 100644 --- a/docs/formats/tfvars-hcl.md +++ b/docs/formats/tfvars-hcl.md @@ -22,7 +22,7 @@ terraform-docs tfvars hcl [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -95,4 +95,4 @@ generates the following output: with-url = "" -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/tfvars-json.md b/docs/formats/tfvars-json.md index bf586c1..3ea12a4 100644 --- a/docs/formats/tfvars-json.md +++ b/docs/formats/tfvars-json.md @@ -22,7 +22,7 @@ terraform-docs tfvars json [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -97,4 +97,4 @@ generates the following output: } -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/tfvars.md b/docs/formats/tfvars.md index 8e0650c..19af717 100644 --- a/docs/formats/tfvars.md +++ b/docs/formats/tfvars.md @@ -18,7 +18,7 @@ Generate terraform.tfvars of inputs --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -29,4 +29,4 @@ Generate terraform.tfvars of inputs * [terraform-docs tfvars hcl](/docs/formats/tfvars-hcl.md) - Generate HCL format of terraform.tfvars of inputs * [terraform-docs tfvars json](/docs/formats/tfvars-json.md) - Generate JSON format of terraform.tfvars of inputs -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/toml.md b/docs/formats/toml.md index f549eec..b63e639 100644 --- a/docs/formats/toml.md +++ b/docs/formats/toml.md @@ -22,7 +22,7 @@ terraform-docs toml [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -312,4 +312,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/xml.md b/docs/formats/xml.md index 2f4e618..0a9fa50 100644 --- a/docs/formats/xml.md +++ b/docs/formats/xml.md @@ -22,7 +22,7 @@ terraform-docs xml [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -334,4 +334,4 @@ generates the following output: -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/docs/formats/yaml.md b/docs/formats/yaml.md index d59dd3f..5120443 100644 --- a/docs/formats/yaml.md +++ b/docs/formats/yaml.md @@ -22,7 +22,7 @@ terraform-docs yaml [PATH] [flags] --header-from string relative path of a file to read header from (default "main.tf") --hide strings hide section [header, inputs, outputs, providers, requirements] --output-values inject output values into outputs (default false) - --output-values-from string inject output values from file into outputs + --output-values-from string inject output values from file into outputs (default "") --sort sort items (default true) --sort-by-required sort items by name and print required ones first (default false) --sort-by-type sort items by type of them (default false) @@ -286,4 +286,4 @@ generates the following output: version: '>= 2.2.0' -###### Auto generated by spf13/cobra on 19-May-2020 +###### Auto generated by spf13/cobra on 20-May-2020 diff --git a/go.mod b/go.mod index a42af30..b1b964e 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 github.com/imdario/mergo v0.3.9 github.com/spf13/cobra v1.0.0 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.5.1 github.com/zclconf/go-cty v1.4.1 gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 diff --git a/go.sum b/go.sum index d98bfac..5a9232e 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -128,8 +130,6 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.4.0 h1:+q+tmgyUB94HIdH/uVTIi/+kt3pt4sHwEZAcTyLoGsQ= -github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ= github.com/zclconf/go-cty v1.4.1 h1:Xzr4m4utRDhHDifag1onwwUSq32HLoLBsp+w6tD0880= github.com/zclconf/go-cty v1.4.1/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= diff --git a/internal/cli/annotations.go b/internal/cli/annotations.go new file mode 100644 index 0000000..b0ad073 --- /dev/null +++ b/internal/cli/annotations.go @@ -0,0 +1,16 @@ +package cli + +import ( + "strings" +) + +// Annotations returns set of annotations for cobra.Commands, +// specifically the 'command' namd and command 'kind' +func Annotations(cmd string) map[string]string { + annotations := make(map[string]string) + for _, s := range strings.Split(cmd, " ") { + annotations["command"] = s + } + annotations["kind"] = "formatter" + return annotations +} diff --git a/internal/cli/config.go b/internal/cli/config.go new file mode 100644 index 0000000..3642fd8 --- /dev/null +++ b/internal/cli/config.go @@ -0,0 +1,235 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/spf13/pflag" + + "github.com/segmentio/terraform-docs/internal/module" + "github.com/segmentio/terraform-docs/pkg/print" +) + +type sections struct { + Hide []string + + header bool + inputs bool + outputs bool + providers bool + requirements bool +} + +func (s *sections) contains(section string) bool { + for _, item := range s.Hide { + if item == section { + return true + } + } + return false +} + +func (s *sections) validate(fs *pflag.FlagSet) error { + sections := []string{"header", "inputs", "outputs", "providers", "requirements"} + for _, h := range s.Hide { + switch h { + case sections[0], sections[1], sections[2], sections[3], sections[4]: + default: + return fmt.Errorf("'%s' is not a valid section", h) + } + } + for _, section := range sections { + if fs.Changed("no-"+section) && s.contains(section) { + return fmt.Errorf("'--no-%s' and '--hide %s' cannot be used together", section, section) + } + } + return nil +} + +type outputvalues struct { + Enabled bool + From string +} + +func (o *outputvalues) validate() error { + if o.Enabled && o.From == "" { + return fmt.Errorf("value of '--output-values-from' cannot be empty") + } + return nil +} + +type sortby struct { + Required bool + Type bool +} +type sort struct { + Enabled bool + By *sortby +} + +func (s *sort) validate(fs *pflag.FlagSet) error { + items := []string{"sort"} + for _, item := range items { + if fs.Changed("no-"+item) && fs.Changed(item) { + return fmt.Errorf("'--no-%s' and '--%s' cannot be used together", item, item) + } + } + if fs.Changed("sort-by-required") && fs.Changed("sort-by-type") { + return fmt.Errorf("'--sort-by-required' and '--sort-by-type' cannot be used together") + } + return nil +} + +type settings struct { + Color bool + Escape bool + Indent int + Required bool + Sensitive bool +} + +func (s *settings) validate(fs *pflag.FlagSet) error { + items := []string{"escape", "color", "required", "sensitive"} + for _, item := range items { + if fs.Changed("no-"+item) && fs.Changed(item) { + return fmt.Errorf("'--no-%s' and '--%s' cannot be used together", item, item) + } + } + return nil +} + +// Config represents all the available config options that can be accessed and passed through CLI +type Config struct { + Formatter string + HeaderFrom string + Sections *sections + OutputValues *outputvalues + Sort *sort + Settings *settings +} + +// DefaultConfig returns new instance of Config with default values set +func DefaultConfig() *Config { + return &Config{ + Formatter: "", + HeaderFrom: "main.tf", + Sections: §ions{ + Hide: []string{}, + + header: true, + inputs: true, + outputs: true, + providers: true, + requirements: true, + }, + OutputValues: &outputvalues{ + Enabled: false, + From: "", + }, + Sort: &sort{ + Enabled: true, + By: &sortby{ + Required: false, + Type: false, + }, + }, + Settings: &settings{ + Color: true, + Escape: true, + Indent: 2, + Required: false, + Sensitive: false, + }, + } +} + +// extract and build print.Settings and module.Options out of Config +func (c *Config) extract() (*print.Settings, *module.Options, error) { + settings := print.NewSettings() + options := module.NewOptions() + + // header-from + options.HeaderFromFile = c.HeaderFrom + + // sections + settings.ShowHeader = c.Sections.header + settings.ShowInputs = c.Sections.inputs + settings.ShowOutputs = c.Sections.outputs + settings.ShowProviders = c.Sections.providers + settings.ShowRequirements = c.Sections.requirements + options.ShowHeader = settings.ShowHeader + + // output values + settings.OutputValues = c.OutputValues.Enabled + options.OutputValues = c.OutputValues.Enabled + options.OutputValuesPath = c.OutputValues.From + + // sort + settings.SortByName = c.Sort.Enabled + settings.SortByRequired = c.Sort.Enabled && c.Sort.By.Required + settings.SortByType = c.Sort.Enabled && c.Sort.By.Type + options.SortBy.Name = settings.SortByName + options.SortBy.Required = settings.SortByRequired + options.SortBy.Type = settings.SortByType + + // settings + settings.EscapeCharacters = c.Settings.Escape + settings.IndentLevel = c.Settings.Indent + settings.ShowColor = c.Settings.Color + settings.ShowRequired = c.Settings.Required + settings.ShowSensitivity = c.Settings.Sensitive + + return settings, options, nil +} + +// normalize provided Config and check for any misuse or misconfiguration +func normalize(command string, fs *pflag.FlagSet, config *Config) error { + config.Formatter = strings.Replace(command, "terraform-docs ", "", -1) + + // header-from + if fs.Changed("header-from") && config.HeaderFrom == "" { + return fmt.Errorf("value of '--header-from' cannot be empty") + } + + // sections + if err := config.Sections.validate(fs); err != nil { + return err + } + config.Sections.header = !(config.Sections.contains("header") || fs.Changed("no-header")) + config.Sections.inputs = !(config.Sections.contains("inputs") || fs.Changed("no-inputs")) + config.Sections.outputs = !(config.Sections.contains("outputs") || fs.Changed("no-outputs")) + config.Sections.providers = !(config.Sections.contains("providers") || fs.Changed("no-providers")) + config.Sections.requirements = !(config.Sections.contains("requirements") || fs.Changed("no-requirements")) + + // output values + if err := config.OutputValues.validate(); err != nil { + return err + } + + // sort + if err := config.Sort.validate(fs); err != nil { + return err + } + if !fs.Changed("sort") { + config.Sort.Enabled = !fs.Changed("no-sort") + } + + // settings + if err := config.Settings.validate(fs); err != nil { + return err + } + if !fs.Changed("escape") { + config.Settings.Escape = !fs.Changed("no-escape") + } + if !fs.Changed("color") { + config.Settings.Color = !fs.Changed("no-color") + } + if !fs.Changed("required") { + config.Settings.Required = !fs.Changed("no-required") + } + if !fs.Changed("sensitive") { + config.Settings.Sensitive = !fs.Changed("no-sensitive") + } + + return nil +} diff --git a/internal/cli/run.go b/internal/cli/run.go new file mode 100644 index 0000000..8e47834 --- /dev/null +++ b/internal/cli/run.go @@ -0,0 +1,47 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/segmentio/terraform-docs/internal/format" + "github.com/segmentio/terraform-docs/internal/module" +) + +// PreRunEFunc returns actual 'cobra.Command#PreRunE' function +// for 'formatter' commands. This functions reads and normalizes +// flags and arguments passed through CLI execution. +func PreRunEFunc(config *Config) func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + return normalize(cmd.CommandPath(), cmd.Flags(), config) + } +} + +// RunEFunc returns actual 'cobra.Command#RunE' function for +// 'formatter' commands. This functions extract print.Settings +// and module.Options from generated and normalized Config and +// initializes required print.Format instance and executes it. +func RunEFunc(config *Config) func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + settings, options, err := config.extract() + if err != nil { + return err + } + printer, err := format.Factory(config.Formatter, settings) + if err != nil { + return err + } + options.Path = args[0] + tfmodule, err := module.LoadWithOptions(options) + if err != nil { + return err + } + output, err := printer.Print(tfmodule, settings) + if err != nil { + return err + } + fmt.Println(output) + return nil + } +} diff --git a/internal/format/factory.go b/internal/format/factory.go index 1734457..b464769 100644 --- a/internal/format/factory.go +++ b/internal/format/factory.go @@ -12,19 +12,19 @@ import ( // function. func Factory(name string, settings *print.Settings) (print.Format, error) { switch name { - case "asciidoc": + case "asciidoc", "adoc": return NewAsciidocTable(settings), nil - case "asciidoc document": + case "asciidoc document", "asciidoc doc", "adoc document", "adoc doc": return NewAsciidocDocument(settings), nil - case "asciidoc table": + case "asciidoc table", "asciidoc tbl", "adoc table", "adoc tbl": return NewAsciidocTable(settings), nil case "json": return NewJSON(settings), nil - case "markdown": + case "markdown", "md": return NewTable(settings), nil - case "markdown document": + case "markdown document", "markdown doc", "md document", "md doc": return NewDocument(settings), nil - case "markdown table": + case "markdown table", "markdown tbl", "md table", "md tbl": return NewTable(settings), nil case "pretty": return NewPretty(settings), nil diff --git a/internal/format/factory_test.go b/internal/format/factory_test.go index cefd7c9..7d266d9 100644 --- a/internal/format/factory_test.go +++ b/internal/format/factory_test.go @@ -22,18 +22,60 @@ func TestFormatFactory(t *testing.T) { expected: "*format.AsciidocTable", wantErr: false, }, + { + name: "format factory from name", + format: "adoc", + expected: "*format.AsciidocTable", + wantErr: false, + }, { name: "format factory from name", format: "asciidoc document", expected: "*format.AsciidocDocument", wantErr: false, }, + { + name: "format factory from name", + format: "asciidoc doc", + expected: "*format.AsciidocDocument", + wantErr: false, + }, + { + name: "format factory from name", + format: "adoc document", + expected: "*format.AsciidocDocument", + wantErr: false, + }, + { + name: "format factory from name", + format: "adoc doc", + expected: "*format.AsciidocDocument", + wantErr: false, + }, { name: "format factory from name", format: "asciidoc table", expected: "*format.AsciidocTable", wantErr: false, }, + { + name: "format factory from name", + format: "asciidoc tbl", + expected: "*format.AsciidocTable", + wantErr: false, + }, + { + name: "format factory from name", + format: "adoc table", + expected: "*format.AsciidocTable", + wantErr: false, + }, + { + name: "format factory from name", + format: "adoc tbl", + expected: "*format.AsciidocTable", + wantErr: false, + }, { name: "format factory from name", format: "json", @@ -46,18 +88,60 @@ func TestFormatFactory(t *testing.T) { expected: "*format.Table", wantErr: false, }, + { + name: "format factory from name", + format: "md", + expected: "*format.Table", + wantErr: false, + }, { name: "format factory from name", format: "markdown document", expected: "*format.Document", wantErr: false, }, + { + name: "format factory from name", + format: "markdown doc", + expected: "*format.Document", + wantErr: false, + }, + { + name: "format factory from name", + format: "md document", + expected: "*format.Document", + wantErr: false, + }, + { + name: "format factory from name", + format: "md doc", + expected: "*format.Document", + wantErr: false, + }, { name: "format factory from name", format: "markdown table", expected: "*format.Table", wantErr: false, }, + { + name: "format factory from name", + format: "markdown tbl", + expected: "*format.Table", + wantErr: false, + }, + { + name: "format factory from name", + format: "md table", + expected: "*format.Table", + wantErr: false, + }, + { + name: "format factory from name", + format: "md tbl", + expected: "*format.Table", + wantErr: false, + }, { name: "format factory from name", format: "pretty", diff --git a/internal/version/version.go b/internal/version/version.go index a43429f..99f4b74 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -30,8 +30,8 @@ func init() { } } -// Version return the full version of the binary including commit hash and build date -func Version() string { +// Full return the full version of the binary including commit hash and build date +func Full() string { if !strings.HasSuffix(version, commitHash) { version += " " + commitHash } diff --git a/pkg/print/settings.go b/pkg/print/settings.go index fea6660..78daed0 100644 --- a/pkg/print/settings.go +++ b/pkg/print/settings.go @@ -63,7 +63,7 @@ type Settings struct { SortByType bool } -//NewSettings returns new instance of Settings +// NewSettings returns new instance of Settings func NewSettings() *Settings { return &Settings{ EscapeCharacters: true, diff --git a/scripts/docs/generate.go b/scripts/docs/generate.go index 54c1705..784378b 100644 --- a/scripts/docs/generate.go +++ b/scripts/docs/generate.go @@ -26,7 +26,7 @@ var basedir = "/docs" var formatdir = "/formats" func main() { - err := generate(cmd.RootCmd(), "", "FORMATS_GUIDE") + err := generate(cmd.NewCommand(), "", "FORMATS_GUIDE") if err != nil { log.Fatal(err) }