github.com/pulumi/terraform@v1.4.0/pkg/command/state_show.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/pulumi/terraform/pkg/addrs"
     9  	"github.com/pulumi/terraform/pkg/backend"
    10  	"github.com/pulumi/terraform/pkg/command/arguments"
    11  	"github.com/pulumi/terraform/pkg/command/format"
    12  	"github.com/pulumi/terraform/pkg/states"
    13  	"github.com/mitchellh/cli"
    14  )
    15  
    16  // StateShowCommand is a Command implementation that shows a single resource.
    17  type StateShowCommand struct {
    18  	Meta
    19  	StateMeta
    20  }
    21  
    22  func (c *StateShowCommand) Run(args []string) int {
    23  	args = c.Meta.process(args)
    24  	cmdFlags := c.Meta.defaultFlagSet("state show")
    25  	cmdFlags.StringVar(&c.Meta.statePath, "state", "", "path")
    26  	if err := cmdFlags.Parse(args); err != nil {
    27  		c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
    28  		return 1
    29  	}
    30  	args = cmdFlags.Args()
    31  	if len(args) != 1 {
    32  		c.Ui.Error("Exactly one argument expected.\n")
    33  		return cli.RunResultHelp
    34  	}
    35  
    36  	// Check for user-supplied plugin path
    37  	var err error
    38  	if c.pluginPath, err = c.loadPluginPath(); err != nil {
    39  		c.Ui.Error(fmt.Sprintf("Error loading plugin path: %s", err))
    40  		return 1
    41  	}
    42  
    43  	// Load the backend
    44  	b, backendDiags := c.Backend(nil)
    45  	if backendDiags.HasErrors() {
    46  		c.showDiagnostics(backendDiags)
    47  		return 1
    48  	}
    49  
    50  	// We require a local backend
    51  	local, ok := b.(backend.Local)
    52  	if !ok {
    53  		c.Ui.Error(ErrUnsupportedLocalOp)
    54  		return 1
    55  	}
    56  
    57  	// This is a read-only command
    58  	c.ignoreRemoteVersionConflict(b)
    59  
    60  	// Check if the address can be parsed
    61  	addr, addrDiags := addrs.ParseAbsResourceInstanceStr(args[0])
    62  	if addrDiags.HasErrors() {
    63  		c.Ui.Error(fmt.Sprintf(errParsingAddress, args[0]))
    64  		return 1
    65  	}
    66  
    67  	// We expect the config dir to always be the cwd
    68  	cwd, err := os.Getwd()
    69  	if err != nil {
    70  		c.Ui.Error(fmt.Sprintf("Error getting cwd: %s", err))
    71  		return 1
    72  	}
    73  
    74  	// Build the operation (required to get the schemas)
    75  	opReq := c.Operation(b, arguments.ViewHuman)
    76  	opReq.AllowUnsetVariables = true
    77  	opReq.ConfigDir = cwd
    78  
    79  	opReq.ConfigLoader, err = c.initConfigLoader()
    80  	if err != nil {
    81  		c.Ui.Error(fmt.Sprintf("Error initializing config loader: %s", err))
    82  		return 1
    83  	}
    84  
    85  	// Get the context (required to get the schemas)
    86  	lr, _, ctxDiags := local.LocalRun(opReq)
    87  	if ctxDiags.HasErrors() {
    88  		c.showDiagnostics(ctxDiags)
    89  		return 1
    90  	}
    91  
    92  	// Get the schemas from the context
    93  	schemas, diags := lr.Core.Schemas(lr.Config, lr.InputState)
    94  	if diags.HasErrors() {
    95  		c.showDiagnostics(diags)
    96  		return 1
    97  	}
    98  
    99  	// Get the state
   100  	env, err := c.Workspace()
   101  	if err != nil {
   102  		c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
   103  		return 1
   104  	}
   105  	stateMgr, err := b.StateMgr(env)
   106  	if err != nil {
   107  		c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
   108  		return 1
   109  	}
   110  	if err := stateMgr.RefreshState(); err != nil {
   111  		c.Ui.Error(fmt.Sprintf("Failed to refresh state: %s", err))
   112  		return 1
   113  	}
   114  
   115  	state := stateMgr.State()
   116  	if state == nil {
   117  		c.Ui.Error(errStateNotFound)
   118  		return 1
   119  	}
   120  
   121  	is := state.ResourceInstance(addr)
   122  	if !is.HasCurrent() {
   123  		c.Ui.Error(errNoInstanceFound)
   124  		return 1
   125  	}
   126  
   127  	// check if the resource has a configured provider, otherwise this will use the default provider
   128  	rs := state.Resource(addr.ContainingResource())
   129  	absPc := addrs.AbsProviderConfig{
   130  		Provider: rs.ProviderConfig.Provider,
   131  		Alias:    rs.ProviderConfig.Alias,
   132  		Module:   addrs.RootModule,
   133  	}
   134  	singleInstance := states.NewState()
   135  	singleInstance.EnsureModule(addr.Module).SetResourceInstanceCurrent(
   136  		addr.Resource,
   137  		is.Current,
   138  		absPc,
   139  	)
   140  
   141  	output := format.State(&format.StateOpts{
   142  		State:   singleInstance,
   143  		Color:   c.Colorize(),
   144  		Schemas: schemas,
   145  	})
   146  	c.Ui.Output(output[strings.Index(output, "#"):])
   147  
   148  	return 0
   149  }
   150  
   151  func (c *StateShowCommand) Help() string {
   152  	helpText := `
   153  Usage: terraform [global options] state show [options] ADDRESS
   154  
   155    Shows the attributes of a resource in the Terraform state.
   156  
   157    This command shows the attributes of a single resource in the Terraform
   158    state. The address argument must be used to specify a single resource.
   159    You can view the list of available resources with "terraform state list".
   160  
   161  Options:
   162  
   163    -state=statefile    Path to a Terraform state file to use to look
   164                        up Terraform-managed resources. By default it will
   165                        use the state "terraform.tfstate" if it exists.
   166  
   167  `
   168  	return strings.TrimSpace(helpText)
   169  }
   170  
   171  func (c *StateShowCommand) Synopsis() string {
   172  	return "Show a resource in the state"
   173  }
   174  
   175  const errNoInstanceFound = `No instance found for the given address!
   176  
   177  This command requires that the address references one specific instance.
   178  To view the available instances, use "terraform state list". Please modify 
   179  the address to reference a specific instance.`
   180  
   181  const errParsingAddress = `Error parsing instance address: %s
   182  
   183  This command requires that the address references one specific instance.
   184  To view the available instances, use "terraform state list". Please modify 
   185  the address to reference a specific instance.`