cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
package views
|
|
|
|
|
|
|
|
import (
|
2021-02-10 23:31:43 +01:00
|
|
|
"github.com/hashicorp/terraform/command/arguments"
|
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
"github.com/hashicorp/terraform/command/format"
|
|
|
|
"github.com/hashicorp/terraform/internal/terminal"
|
|
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
|
|
"github.com/mitchellh/colorstring"
|
|
|
|
)
|
|
|
|
|
|
|
|
// View is the base layer for command views, encapsulating a set of I/O
|
|
|
|
// streams, a colorize implementation, and implementing a human friendly view
|
|
|
|
// for diagnostics.
|
|
|
|
type View struct {
|
|
|
|
streams *terminal.Streams
|
|
|
|
colorize *colorstring.Colorize
|
|
|
|
|
|
|
|
// NOTE: compactWarnings is currently always false. When implementing
|
|
|
|
// views for commands which support this flag, we will need to address this.
|
|
|
|
compactWarnings bool
|
|
|
|
|
|
|
|
// This unfortunate wart is required to enable rendering of diagnostics which
|
|
|
|
// have associated source code in the configuration. This function pointer
|
|
|
|
// will be dereferenced as late as possible when rendering diagnostics in
|
|
|
|
// order to access the config loader cache.
|
|
|
|
configSources func() map[string][]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize a View with the given streams, a disabled colorize object, and a
|
|
|
|
// no-op configSources callback.
|
|
|
|
func NewView(streams *terminal.Streams) *View {
|
|
|
|
return &View{
|
|
|
|
streams: streams,
|
|
|
|
colorize: &colorstring.Colorize{
|
|
|
|
Colors: colorstring.DefaultColors,
|
|
|
|
Disable: true,
|
|
|
|
Reset: true,
|
|
|
|
},
|
|
|
|
configSources: func() map[string][]byte { return nil },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-10 23:31:43 +01:00
|
|
|
// Configure applies the global view configuration flags.
|
|
|
|
func (v *View) Configure(view *arguments.View) {
|
|
|
|
v.colorize.Disable = view.NoColor
|
|
|
|
v.compactWarnings = view.CompactWarnings
|
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetConfigSources overrides the default no-op callback with a new function
|
|
|
|
// pointer, and should be called when the config loader is initialized.
|
|
|
|
func (v *View) SetConfigSources(cb func() map[string][]byte) {
|
|
|
|
v.configSources = cb
|
|
|
|
}
|
|
|
|
|
|
|
|
// Diagnostics renders a set of warnings and errors in human-readable form.
|
|
|
|
// Warnings are printed to stdout, and errors to stderr.
|
|
|
|
func (v *View) Diagnostics(diags tfdiags.Diagnostics) {
|
|
|
|
diags.Sort()
|
|
|
|
|
|
|
|
if len(diags) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
diags = diags.ConsolidateWarnings(1)
|
|
|
|
|
|
|
|
// Since warning messages are generally competing
|
|
|
|
if v.compactWarnings {
|
|
|
|
// If the user selected compact warnings and all of the diagnostics are
|
|
|
|
// warnings then we'll use a more compact representation of the warnings
|
|
|
|
// that only includes their summaries.
|
|
|
|
// We show full warnings if there are also errors, because a warning
|
|
|
|
// can sometimes serve as good context for a subsequent error.
|
|
|
|
useCompact := true
|
|
|
|
for _, diag := range diags {
|
|
|
|
if diag.Severity() != tfdiags.Warning {
|
|
|
|
useCompact = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if useCompact {
|
|
|
|
msg := format.DiagnosticWarningsCompact(diags, v.colorize)
|
|
|
|
msg = "\n" + msg + "\nTo see the full warning notes, run Terraform without -compact-warnings.\n"
|
2021-02-12 21:37:02 +01:00
|
|
|
v.streams.Print(msg)
|
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, diag := range diags {
|
|
|
|
var msg string
|
|
|
|
if v.colorize.Disable {
|
|
|
|
msg = format.DiagnosticPlain(diag, v.configSources(), v.streams.Stderr.Columns())
|
|
|
|
} else {
|
|
|
|
msg = format.Diagnostic(diag, v.configSources(), v.colorize, v.streams.Stderr.Columns())
|
|
|
|
}
|
|
|
|
|
|
|
|
if diag.Severity() == tfdiags.Error {
|
2021-02-12 21:37:02 +01:00
|
|
|
v.streams.Eprint(msg)
|
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
} else {
|
2021-02-12 21:37:02 +01:00
|
|
|
v.streams.Print(msg)
|
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// HelpPrompt is intended to be called from commands which fail to parse all
|
|
|
|
// of their CLI arguments successfully. It refers users to the full help output
|
|
|
|
// rather than rendering it directly, which can be overwhelming and confusing.
|
|
|
|
func (v *View) HelpPrompt(command string) {
|
2021-02-12 21:37:02 +01:00
|
|
|
v.streams.Eprintf(helpPrompt, command)
|
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const helpPrompt = `
|
|
|
|
For more help on using this command, run:
|
|
|
|
terraform %s -help
|
|
|
|
`
|