cli: Add global view arguments parser
Rather than modifying and relying on the existing Meta.process argument extractor, we can more clearly handle global CLI flags using a separate parser step. This allows us to explicitly configure the view in the command.
This commit is contained in:
parent
c5a6aa31d3
commit
57879bfb71
|
@ -0,0 +1,43 @@
|
|||
package arguments
|
||||
|
||||
// View represents the global command-line arguments which configure the view.
|
||||
type View struct {
|
||||
// NoColor is used to disable the use of terminal color codes in all
|
||||
// output.
|
||||
NoColor bool
|
||||
|
||||
// CompactWarnings is used to coalesce duplicate warnings, to reduce the
|
||||
// level of noise when multiple instances of the same warning are raised
|
||||
// for a configuration.
|
||||
CompactWarnings bool
|
||||
}
|
||||
|
||||
// ParseView processes CLI arguments, returning a View value and a
|
||||
// possibly-modified slice of arguments. If any of the supported flags are
|
||||
// found, they will be removed from the slice.
|
||||
func ParseView(args []string) (*View, []string) {
|
||||
common := &View{}
|
||||
|
||||
// Keep track of the length of the returned slice. When we find an
|
||||
// argument we support, i will not be incremented.
|
||||
i := 0
|
||||
for _, v := range args {
|
||||
switch v {
|
||||
case "-no-color":
|
||||
common.NoColor = true
|
||||
case "-compact-warnings":
|
||||
common.CompactWarnings = true
|
||||
default:
|
||||
// Unsupported argument: move left to the current position, and
|
||||
// increment the index.
|
||||
args[i] = v
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce the slice to the number of unsupported arguments. Any remaining
|
||||
// to the right of i have already been moved left.
|
||||
args = args[:i]
|
||||
|
||||
return common, args
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package arguments
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestParseView(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
args []string
|
||||
want *View
|
||||
wantArgs []string
|
||||
}{
|
||||
"nil": {
|
||||
nil,
|
||||
&View{NoColor: false, CompactWarnings: false},
|
||||
nil,
|
||||
},
|
||||
"empty": {
|
||||
[]string{},
|
||||
&View{NoColor: false, CompactWarnings: false},
|
||||
[]string{},
|
||||
},
|
||||
"none matching": {
|
||||
[]string{"-foo", "bar", "-baz"},
|
||||
&View{NoColor: false, CompactWarnings: false},
|
||||
[]string{"-foo", "bar", "-baz"},
|
||||
},
|
||||
"no-color": {
|
||||
[]string{"-foo", "-no-color", "-baz"},
|
||||
&View{NoColor: true, CompactWarnings: false},
|
||||
[]string{"-foo", "-baz"},
|
||||
},
|
||||
"compact-warnings": {
|
||||
[]string{"-foo", "-compact-warnings", "-baz"},
|
||||
&View{NoColor: false, CompactWarnings: true},
|
||||
[]string{"-foo", "-baz"},
|
||||
},
|
||||
"both": {
|
||||
[]string{"-foo", "-no-color", "-compact-warnings", "-baz"},
|
||||
&View{NoColor: true, CompactWarnings: true},
|
||||
[]string{"-foo", "-baz"},
|
||||
},
|
||||
"both, resulting in empty args": {
|
||||
[]string{"-no-color", "-compact-warnings"},
|
||||
&View{NoColor: true, CompactWarnings: true},
|
||||
[]string{},
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got, gotArgs := ParseView(tc.args)
|
||||
if *got != *tc.want {
|
||||
t.Errorf("unexpected result\n got: %#v\nwant: %#v", got, tc.want)
|
||||
}
|
||||
if !cmp.Equal(gotArgs, tc.wantArgs) {
|
||||
t.Errorf("unexpected args\n got: %#v\nwant: %#v", gotArgs, tc.wantArgs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -621,10 +621,6 @@ func (m *Meta) process(args []string) []string {
|
|||
},
|
||||
}
|
||||
|
||||
if m.View != nil {
|
||||
m.View.EnableColor(m.Color)
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ type OutputCommand struct {
|
|||
}
|
||||
|
||||
func (c *OutputCommand) Run(rawArgs []string) int {
|
||||
rawArgs = c.Meta.process(rawArgs)
|
||||
// Parse and apply global view arguments
|
||||
common, rawArgs := arguments.ParseView(rawArgs)
|
||||
c.View.Configure(common)
|
||||
|
||||
// Parse and validate flags
|
||||
args, diags := arguments.ParseOutput(rawArgs)
|
||||
|
|
|
@ -149,6 +149,7 @@ func TestOutput_emptyOutputs(t *testing.T) {
|
|||
}
|
||||
|
||||
args := []string{
|
||||
"-no-color",
|
||||
"-state", statePath,
|
||||
}
|
||||
code := c.Run(args)
|
||||
|
|
|
@ -3,6 +3,7 @@ package views
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/command/arguments"
|
||||
"github.com/hashicorp/terraform/command/format"
|
||||
"github.com/hashicorp/terraform/internal/terminal"
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
|
@ -41,11 +42,10 @@ func NewView(streams *terminal.Streams) *View {
|
|||
}
|
||||
}
|
||||
|
||||
// EnableColor controls the colorize implementation used by this view (and any
|
||||
// other views which depend on it). This is called by the code which processes
|
||||
// the global -no-color CLI flag, which happens after the view is initialized.
|
||||
func (v *View) EnableColor(color bool) {
|
||||
v.colorize.Disable = !color
|
||||
// Configure applies the global view configuration flags.
|
||||
func (v *View) Configure(view *arguments.View) {
|
||||
v.colorize.Disable = view.NoColor
|
||||
v.compactWarnings = view.CompactWarnings
|
||||
}
|
||||
|
||||
// SetConfigSources overrides the default no-op callback with a new function
|
||||
|
|
Loading…
Reference in New Issue