@@ -5,38 +5,26 @@ package views
55
66import (
77 "bytes"
8- "errors "
8+ "encoding/json "
99 "fmt"
1010 "strings"
1111
1212 "github.com/hashicorp/terraform/internal/command/arguments"
13+ viewsjson "github.com/hashicorp/terraform/internal/command/views/json"
1314 "github.com/hashicorp/terraform/internal/tfdiags"
1415)
1516
16- // The Workspace view is used for workspace subcommands.
17- type Workspace interface {
18- Diagnostics (diags tfdiags.Diagnostics )
19- Output (message string )
20-
21- // These methods are present in the interface to allow
22- // backwards compatibility while human-readable output is
23- // fulfilled using the cli.Ui interface.
24- Error (message string )
25- Warn (message string )
26- }
27-
17+ // The WorkspaceList view is used for the `workspace list` subcommand.
2818type WorkspaceList interface {
29- Workspace
30-
31- List (selected string , list []string )
19+ List (selected string , list []string , diags tfdiags.Diagnostics )
3220}
3321
3422// NewWorkspace returns the Workspace implementation for the given ViewType.
3523func NewWorkspaceList (vt arguments.ViewType , view * View ) WorkspaceList {
3624 switch vt {
3725 case arguments .ViewJSON :
3826 return & WorkspaceJSON {
39- view : NewJSONView ( view ) ,
27+ view : view ,
4028 }
4129 case arguments .ViewHuman :
4230 // TODO: Allow use of WorkspaceHuman here when we remove use of cli.Ui from workspace commands.
@@ -49,75 +37,62 @@ func NewWorkspaceList(vt arguments.ViewType, view *View) WorkspaceList {
4937// The WorkspaceJSON implementation renders machine-readable logs, suitable for
5038// integrating with other software.
5139type WorkspaceJSON struct {
52- view * JSONView
40+ view * View
5341}
5442
55- var _ Workspace = (* WorkspaceJSON )(nil )
43+ var _ WorkspaceList = (* WorkspaceJSON )(nil )
5644
5745// Diagnostics renders a list of diagnostics, including the option for compact warnings.
5846func (v * WorkspaceJSON ) Diagnostics (diags tfdiags.Diagnostics ) {
5947 v .view .Diagnostics (diags )
6048}
6149
62- // Output is used to render text in the terminal via stdout.
63- func (v * WorkspaceJSON ) Output (msg string ) {
64- v .view .Log (msg )
50+ type WorkspaceListOutput struct {
51+ Workspaces []WorkspaceOutput `json:"workspaces"`
52+ Diagnostics []* viewsjson.Diagnostic `json:"diagnostics"`
53+ }
54+
55+ type WorkspaceOutput struct {
56+ Name string `json:"name"`
57+ IsCurrent bool `json:"is_current"`
6558}
6659
6760// List is used to log the list of present workspaces and indicate which is currently selected
68- func (v * WorkspaceJSON ) List (current string , list []string ) {
69- var msg bytes. Buffer
70- for _ , s := range list {
71- if s == current {
72- msg . WriteString ( "* " )
73- } else {
74- msg . WriteString ( " " )
61+ func (v * WorkspaceJSON ) List (current string , list []string , diags tfdiags. Diagnostics ) {
62+ output := WorkspaceListOutput {}
63+
64+ for _ , item := range list {
65+ workspace := WorkspaceOutput {
66+ Name : item ,
67+ IsCurrent : item == current ,
7568 }
76- msg . WriteString ( s + " \n " )
69+ output . Workspaces = append ( output . Workspaces , workspace )
7770 }
7871
79- v . view . log . Info (
80- msg . String (),
81- "current" , current ,
82- "workspaces" , list )
83- }
72+ if output . Workspaces == nil {
73+ // Make sure this always appears as an array in our output, since
74+ // this is easier to consume for dynamically-typed languages.
75+ output . Workspaces = [] WorkspaceOutput {}
76+ }
8477
85- // Error
86- //
87- // This method is a temporary measure while the workspace subcommands contain both
88- // use of cli.Ui for human output and view.View for machine-readable output.
89- // In future calling code should use Diagnostics directly.
90- //
91- // If a message is being logged as an error we can create a native error (which can be made from a string),
92- // use existing logic in (tfdiags.Diagnostics) Append to create an error diagnostic from a native error,
93- // and then log that single error diagnostic.
94- func (v * WorkspaceJSON ) Error (msg string ) {
95- var diags tfdiags.Diagnostics
96- err := errors .New (msg )
97- diags = diags .Append (err )
98-
99- v .Diagnostics (diags )
100- }
78+ configSources := v .view .configSources ()
79+ for _ , diag := range diags {
80+ output .Diagnostics = append (output .Diagnostics , viewsjson .NewDiagnostic (diag , configSources ))
81+ }
10182
102- // Warn
103- //
104- // This method is a temporary measure while the workspace subcommands contain both
105- // use of cli.Ui for human output and view.View for machine-readable output.
106- // In future calling code should use Diagnostics directly.
107- //
108- // This method takes inspiration from how native errors are converted into error diagnostics;
109- // the Details value is left empty and the provided string is used only in the Summary.
110- // See : https://github.com/hashicorp/terraform/blob/v1.14.4/internal/tfdiags/error.go
111- func (v * WorkspaceJSON ) Warn (msg string ) {
112- var diags tfdiags.Diagnostics
113- warn := tfdiags .Sourceless (
114- tfdiags .Warning ,
115- msg ,
116- "" ,
117- )
118- diags = diags .Append (warn )
119-
120- v .Diagnostics (diags )
83+ if output .Diagnostics == nil {
84+ // Make sure this always appears as an array in our output, since
85+ // this is easier to consume for dynamically-typed languages.
86+ output .Diagnostics = []* viewsjson.Diagnostic {}
87+ }
88+
89+ jsonOutput , err := json .MarshalIndent (output , "" , " " )
90+ if err != nil {
91+ // Should never happen because we fully-control the input here
92+ panic (err )
93+ }
94+
95+ v .view .streams .Println (string (jsonOutput ))
12196}
12297
12398// The WorkspaceHuman implementation renders human-readable text logs, suitable for
@@ -126,32 +101,27 @@ type WorkspaceHuman struct {
126101 view * View
127102}
128103
129- var _ Workspace = (* WorkspaceHuman )(nil )
104+ var _ WorkspaceList = (* WorkspaceHuman )(nil )
130105
131- // Diagnostics renders a list of diagnostics, including the option for compact warnings.
132- func ( v * WorkspaceHuman ) Diagnostics ( diags tfdiags. Diagnostics ) {
106+ func ( v * WorkspaceHuman ) List ( selected string , list [] string , diags tfdiags. Diagnostics ) {
107+ // Print diags above output
133108 v .view .Diagnostics (diags )
134- }
135109
136- // Output is used to render text in the terminal, such as data returned from a command.
137- func (v * WorkspaceHuman ) Output (msg string ) {
138- v .view .streams .Println (v .prepareMessage (msg ))
139- }
140-
141- // Error is implemented to fulfil the Workspace interface
142- // Once we can make breaking changes that interface shouldn't have an
143- // Error method, so this method should be deleted in future.
144- func (v * WorkspaceHuman ) Error (msg string ) {
145- panic ("(WorkspaceHuman).Error should not be used" )
146- }
147-
148- // Warn is implemented to fulfil the Workspace interface
149- // Onc we can make breaking changes that interface shouldn't have an
150- // Warn method, so this method should be deleted in future.
151- func (v * WorkspaceHuman ) Warn (msg string ) {
152- panic ("(WorkspaceHuman).Warn should not be used" )
110+ // Print list
111+ if len (list ) > 0 {
112+ var out bytes.Buffer
113+ for _ , s := range list {
114+ if s == selected {
115+ out .WriteString ("* " )
116+ } else {
117+ out .WriteString (" " )
118+ }
119+ out .WriteString (s + "\n " )
120+ }
121+ v .output (out .String ())
122+ }
153123}
154124
155- func (v * WorkspaceHuman ) prepareMessage (msg string ) string {
125+ func (v * WorkspaceHuman ) output (msg string ) string {
156126 return v .view .colorize .Color (strings .TrimSpace (msg ))
157127}
0 commit comments