| package tfexec | 
 |  | 
 | import ( | 
 | 	"context" | 
 | 	"fmt" | 
 | 	"os/exec" | 
 | 	"strings" | 
 |  | 
 | 	tfjson "github.com/hashicorp/terraform-json" | 
 | ) | 
 |  | 
 | type showConfig struct { | 
 | 	reattachInfo ReattachInfo | 
 | } | 
 |  | 
 | var defaultShowOptions = showConfig{} | 
 |  | 
 | type ShowOption interface { | 
 | 	configureShow(*showConfig) | 
 | } | 
 |  | 
 | func (opt *ReattachOption) configureShow(conf *showConfig) { | 
 | 	conf.reattachInfo = opt.info | 
 | } | 
 |  | 
 | // Show reads the default state path and outputs the state. | 
 | // To read a state or plan file, ShowState or ShowPlan must be used instead. | 
 | func (tf *Terraform) Show(ctx context.Context, opts ...ShowOption) (*tfjson.State, error) { | 
 | 	err := tf.compatible(ctx, tf0_12_0, nil) | 
 | 	if err != nil { | 
 | 		return nil, fmt.Errorf("terraform show -json was added in 0.12.0: %w", err) | 
 | 	} | 
 |  | 
 | 	c := defaultShowOptions | 
 |  | 
 | 	for _, o := range opts { | 
 | 		o.configureShow(&c) | 
 | 	} | 
 |  | 
 | 	mergeEnv := map[string]string{} | 
 | 	if c.reattachInfo != nil { | 
 | 		reattachStr, err := c.reattachInfo.marshalString() | 
 | 		if err != nil { | 
 | 			return nil, err | 
 | 		} | 
 | 		mergeEnv[reattachEnvVar] = reattachStr | 
 | 	} | 
 |  | 
 | 	showCmd := tf.showCmd(ctx, true, mergeEnv) | 
 |  | 
 | 	var ret tfjson.State | 
 | 	ret.UseJSONNumber(true) | 
 | 	err = tf.runTerraformCmdJSON(ctx, showCmd, &ret) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 |  | 
 | 	err = ret.Validate() | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 |  | 
 | 	return &ret, nil | 
 | } | 
 |  | 
 | // ShowStateFile reads a given state file and outputs the state. | 
 | func (tf *Terraform) ShowStateFile(ctx context.Context, statePath string, opts ...ShowOption) (*tfjson.State, error) { | 
 | 	err := tf.compatible(ctx, tf0_12_0, nil) | 
 | 	if err != nil { | 
 | 		return nil, fmt.Errorf("terraform show -json was added in 0.12.0: %w", err) | 
 | 	} | 
 |  | 
 | 	if statePath == "" { | 
 | 		return nil, fmt.Errorf("statePath cannot be blank: use Show() if not passing statePath") | 
 | 	} | 
 |  | 
 | 	c := defaultShowOptions | 
 |  | 
 | 	for _, o := range opts { | 
 | 		o.configureShow(&c) | 
 | 	} | 
 |  | 
 | 	mergeEnv := map[string]string{} | 
 | 	if c.reattachInfo != nil { | 
 | 		reattachStr, err := c.reattachInfo.marshalString() | 
 | 		if err != nil { | 
 | 			return nil, err | 
 | 		} | 
 | 		mergeEnv[reattachEnvVar] = reattachStr | 
 | 	} | 
 |  | 
 | 	showCmd := tf.showCmd(ctx, true, mergeEnv, statePath) | 
 |  | 
 | 	var ret tfjson.State | 
 | 	ret.UseJSONNumber(true) | 
 | 	err = tf.runTerraformCmdJSON(ctx, showCmd, &ret) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 |  | 
 | 	err = ret.Validate() | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 |  | 
 | 	return &ret, nil | 
 | } | 
 |  | 
 | // ShowPlanFile reads a given plan file and outputs the plan. | 
 | func (tf *Terraform) ShowPlanFile(ctx context.Context, planPath string, opts ...ShowOption) (*tfjson.Plan, error) { | 
 | 	err := tf.compatible(ctx, tf0_12_0, nil) | 
 | 	if err != nil { | 
 | 		return nil, fmt.Errorf("terraform show -json was added in 0.12.0: %w", err) | 
 | 	} | 
 |  | 
 | 	if planPath == "" { | 
 | 		return nil, fmt.Errorf("planPath cannot be blank: use Show() if not passing planPath") | 
 | 	} | 
 |  | 
 | 	c := defaultShowOptions | 
 |  | 
 | 	for _, o := range opts { | 
 | 		o.configureShow(&c) | 
 | 	} | 
 |  | 
 | 	mergeEnv := map[string]string{} | 
 | 	if c.reattachInfo != nil { | 
 | 		reattachStr, err := c.reattachInfo.marshalString() | 
 | 		if err != nil { | 
 | 			return nil, err | 
 | 		} | 
 | 		mergeEnv[reattachEnvVar] = reattachStr | 
 | 	} | 
 |  | 
 | 	showCmd := tf.showCmd(ctx, true, mergeEnv, planPath) | 
 |  | 
 | 	var ret tfjson.Plan | 
 | 	err = tf.runTerraformCmdJSON(ctx, showCmd, &ret) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 |  | 
 | 	err = ret.Validate() | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 |  | 
 | 	return &ret, nil | 
 |  | 
 | } | 
 |  | 
 | // ShowPlanFileRaw reads a given plan file and outputs the plan in a | 
 | // human-friendly, opaque format. | 
 | func (tf *Terraform) ShowPlanFileRaw(ctx context.Context, planPath string, opts ...ShowOption) (string, error) { | 
 | 	if planPath == "" { | 
 | 		return "", fmt.Errorf("planPath cannot be blank: use Show() if not passing planPath") | 
 | 	} | 
 |  | 
 | 	c := defaultShowOptions | 
 |  | 
 | 	for _, o := range opts { | 
 | 		o.configureShow(&c) | 
 | 	} | 
 |  | 
 | 	mergeEnv := map[string]string{} | 
 | 	if c.reattachInfo != nil { | 
 | 		reattachStr, err := c.reattachInfo.marshalString() | 
 | 		if err != nil { | 
 | 			return "", err | 
 | 		} | 
 | 		mergeEnv[reattachEnvVar] = reattachStr | 
 | 	} | 
 |  | 
 | 	showCmd := tf.showCmd(ctx, false, mergeEnv, planPath) | 
 |  | 
 | 	var outBuf strings.Builder | 
 | 	showCmd.Stdout = &outBuf | 
 | 	err := tf.runTerraformCmd(ctx, showCmd) | 
 | 	if err != nil { | 
 | 		return "", err | 
 | 	} | 
 |  | 
 | 	return outBuf.String(), nil | 
 |  | 
 | } | 
 |  | 
 | func (tf *Terraform) showCmd(ctx context.Context, jsonOutput bool, mergeEnv map[string]string, args ...string) *exec.Cmd { | 
 | 	allArgs := []string{"show"} | 
 | 	if jsonOutput { | 
 | 		allArgs = append(allArgs, "-json") | 
 | 	} | 
 | 	allArgs = append(allArgs, "-no-color") | 
 | 	allArgs = append(allArgs, args...) | 
 |  | 
 | 	return tf.buildTerraformCmd(ctx, mergeEnv, allArgs...) | 
 | } |