Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content

Commit ace06f9

Browse files
authored
Merge pull request hashicorp#10149 from hashicorp/jbardin/debug-cmd
Add debug command with json2dot
2 parents b1f974b + b8adf10 commit ace06f9

5 files changed

Lines changed: 173 additions & 0 deletions

File tree

command/debug_command.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package command
2+
3+
import (
4+
"strings"
5+
6+
"github.com/mitchellh/cli"
7+
)
8+
9+
// DebugCommand is a Command implementation that just shows help for
10+
// the subcommands nested below it.
11+
type DebugCommand struct {
12+
Meta
13+
}
14+
15+
func (c *DebugCommand) Run(args []string) int {
16+
return cli.RunResultHelp
17+
}
18+
19+
func (c *DebugCommand) Help() string {
20+
helpText := `
21+
Usage: terraform debug <subcommand> [options] [args]
22+
23+
This command has subcommands for debug output management
24+
`
25+
return strings.TrimSpace(helpText)
26+
}
27+
28+
func (c *DebugCommand) Synopsis() string {
29+
return "Debug output management (experimental)"
30+
}

command/debug_json2dot.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package command
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
8+
"github.com/hashicorp/terraform/dag"
9+
"github.com/mitchellh/cli"
10+
)
11+
12+
// DebugJSON2DotCommand is a Command implementation that translates a json
13+
// graph debug log to Dot format.
14+
type DebugJSON2DotCommand struct {
15+
Meta
16+
}
17+
18+
func (c *DebugJSON2DotCommand) Run(args []string) int {
19+
args = c.Meta.process(args, true)
20+
cmdFlags := c.Meta.flagSet("debug json2dot")
21+
22+
if err := cmdFlags.Parse(args); err != nil {
23+
return cli.RunResultHelp
24+
}
25+
26+
fileName := cmdFlags.Arg(0)
27+
if fileName == "" {
28+
return cli.RunResultHelp
29+
}
30+
31+
f, err := os.Open(fileName)
32+
if err != nil {
33+
c.Ui.Error(fmt.Sprintf(errInvalidLog, err))
34+
return cli.RunResultHelp
35+
}
36+
37+
dot, err := dag.JSON2Dot(f)
38+
if err != nil {
39+
c.Ui.Error(fmt.Sprintf(errInvalidLog, err))
40+
return cli.RunResultHelp
41+
}
42+
43+
c.Ui.Output(string(dot))
44+
return 0
45+
}
46+
47+
func (c *DebugJSON2DotCommand) Help() string {
48+
helpText := `
49+
Usage: terraform debug json2dot input.json
50+
51+
Translate a graph debug file to dot format.
52+
53+
This command takes a single json graph log file and converts it to a single
54+
dot graph written to stdout.
55+
`
56+
return strings.TrimSpace(helpText)
57+
}
58+
59+
func (c *DebugJSON2DotCommand) Synopsis() string {
60+
return "Convert json graph log to dot"
61+
}
62+
63+
const errInvalidLog = `Error parsing log file: %[1]s`

command/debug_json2dot_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package command
2+
3+
import (
4+
"io/ioutil"
5+
"os"
6+
"strings"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform/dag"
10+
"github.com/mitchellh/cli"
11+
)
12+
13+
func TestDebugJSON2Dot(t *testing.T) {
14+
// create the graph JSON output
15+
logFile, err := ioutil.TempFile("", "tf")
16+
if err != nil {
17+
t.Fatal(err)
18+
}
19+
defer os.Remove(logFile.Name())
20+
21+
var g dag.Graph
22+
g.SetDebugWriter(logFile)
23+
24+
g.Add(1)
25+
g.Add(2)
26+
g.Add(3)
27+
g.Connect(dag.BasicEdge(1, 2))
28+
g.Connect(dag.BasicEdge(2, 3))
29+
30+
ui := new(cli.MockUi)
31+
c := &DebugJSON2DotCommand{
32+
Meta: Meta{
33+
ContextOpts: testCtxConfig(testProvider()),
34+
Ui: ui,
35+
},
36+
}
37+
38+
args := []string{
39+
logFile.Name(),
40+
}
41+
if code := c.Run(args); code != 0 {
42+
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
43+
}
44+
45+
output := ui.OutputWriter.String()
46+
if !strings.HasPrefix(output, "digraph {") {
47+
t.Fatalf("doesn't look like digraph: %s", output)
48+
}
49+
50+
if !strings.Contains(output, `subgraph "root" {`) {
51+
t.Fatalf("doesn't contains root subgraph: %s", output)
52+
}
53+
}

commands.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func init() {
3737

3838
PlumbingCommands = map[string]struct{}{
3939
"state": struct{}{}, // includes all subcommands
40+
"debug": struct{}{}, // includes all subcommands
4041
}
4142

4243
Commands = map[string]cli.CommandFactory{
@@ -166,6 +167,18 @@ func init() {
166167
// Plumbing
167168
//-----------------------------------------------------------
168169

170+
"debug": func() (cli.Command, error) {
171+
return &command.DebugCommand{
172+
Meta: meta,
173+
}, nil
174+
},
175+
176+
"debug json2dot": func() (cli.Command, error) {
177+
return &command.DebugJSON2DotCommand{
178+
Meta: meta,
179+
}, nil
180+
},
181+
169182
"state": func() (cli.Command, error) {
170183
return &command.StateCommand{
171184
Meta: meta,

dag/marshal.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,17 @@ func newEdgeInfo(infoType string, e Edge, info string) *marshalEdgeInfo {
454454
Info: info,
455455
}
456456
}
457+
458+
// JSON2Dot reads a Graph debug log from and io.Reader, and converts the final
459+
// graph dot format.
460+
//
461+
// TODO: Allow returning the output at a certain point during decode.
462+
// Encode extra information from the json log into the Dot.
463+
func JSON2Dot(r io.Reader) ([]byte, error) {
464+
g, err := decodeGraph(r)
465+
if err != nil {
466+
return nil, err
467+
}
468+
469+
return g.Dot(nil), nil
470+
}

0 commit comments

Comments
 (0)