github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/state_show.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 "github.com/hashicorp/terraform/internal/addrs" 9 "github.com/hashicorp/terraform/internal/backend" 10 "github.com/hashicorp/terraform/internal/command/arguments" 11 "github.com/hashicorp/terraform/internal/command/format" 12 "github.com/hashicorp/terraform/internal/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.`