Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial stab at JSON plan output #3170

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions command/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type PlanCommand struct {
}

func (c *PlanCommand) Run(args []string) int {
var destroy, refresh, detailed bool
var destroy, refresh, detailed, outJson bool
var outPath string
var moduleDepth int

Expand All @@ -27,6 +27,7 @@ func (c *PlanCommand) Run(args []string) int {
cmdFlags.BoolVar(&refresh, "refresh", true, "refresh")
c.addModuleDepthFlag(cmdFlags, &moduleDepth)
cmdFlags.StringVar(&outPath, "out", "", "path")
cmdFlags.BoolVar(&outJson, "out-json", false, "out-json")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path")
cmdFlags.BoolVar(&detailed, "detailed-exitcode", false, "detailed-exitcode")
Expand Down Expand Up @@ -111,7 +112,11 @@ func (c *PlanCommand) Run(args []string) int {
f, err := os.Create(outPath)
if err == nil {
defer f.Close()
err = terraform.WritePlan(plan, f)
if outJson {
err = terraform.WriteJsonPlan(plan, f)
} else {
err = terraform.WritePlan(plan, f)
}
}
if err != nil {
c.Ui.Error(fmt.Sprintf("Error writing plan file: %s", err))
Expand Down
28 changes: 15 additions & 13 deletions terraform/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,11 @@ func (d *Diff) init() {
// ModuleDiff tracks the differences between resources to apply within
// a single module.
type ModuleDiff struct {
Path []string
Resources map[string]*InstanceDiff
Destroy bool // Set only by the destroy plan
Path []string `json:"path"`
Resources map[string]*InstanceDiff `json:"resources"`

// Set only by the destroy plan
Destroy bool `json:"destroy"`
}

func (d *ModuleDiff) init() {
Expand Down Expand Up @@ -270,20 +272,20 @@ func (d *ModuleDiff) String() string {

// InstanceDiff is the diff of a resource from some state to another.
type InstanceDiff struct {
Attributes map[string]*ResourceAttrDiff
Destroy bool
DestroyTainted bool
Attributes map[string]*ResourceAttrDiff `json:"attributes"`
Destroy bool `json:"destroy"`
DestroyTainted bool `json:"tainted"`
}

// ResourceAttrDiff is the diff of a single attribute of a resource.
type ResourceAttrDiff struct {
Old string // Old Value
New string // New Value
NewComputed bool // True if new value is computed (unknown currently)
NewRemoved bool // True if this attribute is being removed
NewExtra interface{} // Extra information for the provider
RequiresNew bool // True if change requires new resource
Type DiffAttrType
Old string `json:"old"` // Old Value
New string `json:"new"` // New Value
NewComputed bool `json:"new_computed"` // True if new value is computed (unknown currently)
NewRemoved bool `json:"new_removed"` // True if this attribute is being removed
NewExtra interface{} `json:"new_extra"` // Extra information for the provider
RequiresNew bool `json:"requires_new"` // True if change requires new resource
Type DiffAttrType `json:"-"`
}

func (d *ResourceAttrDiff) GoString() string {
Expand Down
18 changes: 18 additions & 0 deletions terraform/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package terraform
import (
"bytes"
"encoding/gob"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -115,6 +116,23 @@ func ReadPlan(src io.Reader) (*Plan, error) {
return result, nil
}

// WriteJsonPlan writes a plan somewhere in a JSON format.
func WriteJsonPlan(d *Plan, dst io.Writer) error {

// Encode the data in a human-friendly way
data, err := json.MarshalIndent(d.Diff.Modules, "", " ")
if err != nil {
return err
}

// We append a newline to the data because MarshalIndent doesn't
data = append(data, '\n')

_, err = dst.Write(data)

return err
}

// WritePlan writes a plan somewhere in a binary format.
func WritePlan(d *Plan, dst io.Writer) error {
// Write the magic bytes so we can determine the file format later
Expand Down