command/show: improvements to show -json output (#20110)

* terraform_version is now included in state
* provisioner "name" is now provisioner "type"
This commit is contained in:
Kristin Laemmert 2019-01-24 15:28:53 -08:00 committed by GitHub
parent a30bd5cdd4
commit 514ac6b890
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 27 deletions

View File

@ -83,7 +83,7 @@ type configOutput struct {
}
type provisioner struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Expressions map[string]interface{} `json:"expressions,omitempty"`
}
@ -242,7 +242,7 @@ func marshalResources(resources map[string]*configs.Resource, schemas *terraform
for _, p := range v.Managed.Provisioners {
schema := schemas.ProvisionerConfig(p.Type)
prov := provisioner{
Name: p.Type,
Type: p.Type,
Expressions: marshalExpressions(p.Config, schema),
}
provisioners = append(provisioners, prov)

View File

@ -13,6 +13,7 @@ import (
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/states/statefile"
"github.com/hashicorp/terraform/terraform"
ctyjson "github.com/zclconf/go-cty/cty/json"
@ -76,7 +77,7 @@ type output struct {
func Marshal(
config *configs.Config,
p *plans.Plan,
s *states.State,
sf *statefile.File,
schemas *terraform.Schemas,
) ([]byte, error) {
@ -101,7 +102,7 @@ func Marshal(
}
// output.PriorState
output.PriorState, err = jsonstate.Marshal(s, schemas)
output.PriorState, err = jsonstate.Marshal(sf, schemas)
if err != nil {
return nil, fmt.Errorf("error marshaling prior state: %s", err)
}

View File

@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/states/statefile"
"github.com/hashicorp/terraform/terraform"
)
@ -22,8 +23,9 @@ const FormatVersion = "0.1"
// state is the top-level representation of the json format of a terraform
// state.
type state struct {
FormatVersion string `json:"format_version,omitempty"`
Values stateValues `json:"values,omitempty"`
FormatVersion string `json:"format_version,omitempty"`
TerraformVersion string `json:"terraform_version"`
Values stateValues `json:"values,omitempty"`
}
// stateValues is the common representation of resolved values for both the prior
@ -109,15 +111,16 @@ func newState() *state {
}
// Marshal returns the json encoding of a terraform state.
func Marshal(s *states.State, schemas *terraform.Schemas) ([]byte, error) {
if s.Empty() {
func Marshal(sf *statefile.File, schemas *terraform.Schemas) ([]byte, error) {
if sf == nil || sf.State.Empty() {
return nil, nil
}
output := newState()
output.TerraformVersion = sf.TerraformVersion.String()
// output.StateValues
err := output.marshalStateValues(s, schemas)
err := output.marshalStateValues(sf.State, schemas)
if err != nil {
return nil, err
}

View File

@ -6,14 +6,13 @@ import (
"strings"
"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/plans/planfile"
"github.com/hashicorp/terraform/states/statefile"
"github.com/hashicorp/terraform/tfdiags"
"github.com/hashicorp/terraform/command/format"
"github.com/hashicorp/terraform/command/jsonplan"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/plans/planfile"
"github.com/hashicorp/terraform/states/statefile"
"github.com/hashicorp/terraform/states/statemgr"
"github.com/hashicorp/terraform/tfdiags"
)
// ShowCommand is a Command implementation that reads and outputs the
@ -103,7 +102,7 @@ func (c *ShowCommand) Run(args []string) int {
var planErr, stateErr error
var plan *plans.Plan
var state *states.State
var stateFile *statefile.File
// if a path was provided, try to read it as a path to a planfile
// if that fails, try to read the cli argument as a path to a statefile
@ -116,7 +115,7 @@ func (c *ShowCommand) Run(args []string) int {
c.Ui.Error("Error: JSON output not available for state")
return 1
}
state, stateErr = getStateFromPath(path)
stateFile, stateErr = getStateFromPath(path)
if stateErr != nil {
c.Ui.Error(fmt.Sprintf(
"Terraform couldn't read the given file as a state or plan file.\n"+
@ -130,9 +129,9 @@ func (c *ShowCommand) Run(args []string) int {
}
}
if state == nil {
if stateFile == nil {
env := c.Workspace()
state, stateErr = getStateFromEnv(b, env)
stateFile, stateErr = getStateFromEnv(b, env)
if err != nil {
c.Ui.Error(err.Error())
return 1
@ -142,7 +141,7 @@ func (c *ShowCommand) Run(args []string) int {
// This is an odd-looking check, because it's ok if we have a plan and an
// empty state, and we've already validated that any command-line arguments
// have been read successfully
if plan == nil && state == nil {
if plan == nil && stateFile == nil {
c.Ui.Output("No state.")
return 0
}
@ -150,7 +149,7 @@ func (c *ShowCommand) Run(args []string) int {
if plan != nil {
if jsonOutput == true {
config := ctx.Config()
jsonPlan, err := jsonplan.Marshal(config, plan, state, schemas)
jsonPlan, err := jsonplan.Marshal(config, plan, stateFile, schemas)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to marshal plan to json: %s", err))
return 1
@ -164,7 +163,7 @@ func (c *ShowCommand) Run(args []string) int {
}
c.Ui.Output(format.State(&format.StateOpts{
State: state,
State: stateFile.State,
Color: c.Colorize(),
Schemas: schemas,
}))
@ -207,8 +206,8 @@ func getPlanFromPath(path string) (*plans.Plan, error) {
return plan, nil
}
// getStateFromPath returns a State if the user-supplied path points to a statefile.
func getStateFromPath(path string) (*states.State, error) {
// getStateFromPath returns a statefile if the user-supplied path points to a statefile.
func getStateFromPath(path string) (*statefile.File, error) {
f, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("Error loading statefile: %s", err)
@ -220,11 +219,11 @@ func getStateFromPath(path string) (*states.State, error) {
if err != nil {
return nil, fmt.Errorf("Error reading %s as a statefile: %s", path, err)
}
return stateFile.State, nil
return stateFile, nil
}
// getStateFromEnv returns the State for the current workspace, if available.
func getStateFromEnv(b backend.Backend, env string) (*states.State, error) {
func getStateFromEnv(b backend.Backend, env string) (*statefile.File, error) {
// Get the state
stateStore, err := b.StateMgr(env)
if err != nil {
@ -235,6 +234,7 @@ func getStateFromEnv(b backend.Backend, env string) (*states.State, error) {
return nil, fmt.Errorf("Failed to load state: %s", err)
}
state := stateStore.State()
return state, nil
sf := statemgr.Export(stateStore)
return sf, nil
}