github.com/opentofu/opentofu@v1.7.1/internal/command/state_list.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package command
     7  
     8  import (
     9  	"fmt"
    10  	"strings"
    11  
    12  	"github.com/mitchellh/cli"
    13  
    14  	"github.com/opentofu/opentofu/internal/addrs"
    15  	"github.com/opentofu/opentofu/internal/states"
    16  	"github.com/opentofu/opentofu/internal/tfdiags"
    17  )
    18  
    19  // StateListCommand is a Command implementation that lists the resources
    20  // within a state file.
    21  type StateListCommand struct {
    22  	Meta
    23  	StateMeta
    24  }
    25  
    26  func (c *StateListCommand) Run(args []string) int {
    27  	args = c.Meta.process(args)
    28  	var statePath string
    29  	cmdFlags := c.Meta.defaultFlagSet("state list")
    30  	cmdFlags.StringVar(&statePath, "state", "", "path")
    31  	lookupId := cmdFlags.String("id", "", "Restrict output to paths with a resource having the specified ID.")
    32  	if err := cmdFlags.Parse(args); err != nil {
    33  		c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
    34  		return cli.RunResultHelp
    35  	}
    36  	args = cmdFlags.Args()
    37  
    38  	if statePath != "" {
    39  		c.Meta.statePath = statePath
    40  	}
    41  
    42  	// Load the encryption configuration
    43  	enc, encDiags := c.Encryption()
    44  	if encDiags.HasErrors() {
    45  		c.showDiagnostics(encDiags)
    46  		return 1
    47  	}
    48  
    49  	// Load the backend
    50  	b, backendDiags := c.Backend(nil, enc.State())
    51  	if backendDiags.HasErrors() {
    52  		c.showDiagnostics(backendDiags)
    53  		return 1
    54  	}
    55  
    56  	// This is a read-only command
    57  	c.ignoreRemoteVersionConflict(b)
    58  
    59  	// Get the state
    60  	env, err := c.Workspace()
    61  	if err != nil {
    62  		c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
    63  		return 1
    64  	}
    65  	stateMgr, err := b.StateMgr(env)
    66  	if err != nil {
    67  		c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
    68  		return 1
    69  	}
    70  	if err := stateMgr.RefreshState(); err != nil {
    71  		c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
    72  		return 1
    73  	}
    74  
    75  	state := stateMgr.State()
    76  	if state == nil {
    77  		c.Ui.Error(errStateNotFound)
    78  		return 1
    79  	}
    80  
    81  	var addrs []addrs.AbsResourceInstance
    82  	var diags tfdiags.Diagnostics
    83  	if len(args) == 0 {
    84  		addrs, diags = c.lookupAllResourceInstanceAddrs(state)
    85  	} else {
    86  		addrs, diags = c.lookupResourceInstanceAddrs(state, args...)
    87  	}
    88  	if diags.HasErrors() {
    89  		c.showDiagnostics(diags)
    90  		return 1
    91  	}
    92  
    93  	for _, addr := range addrs {
    94  		if is := state.ResourceInstance(addr); is != nil {
    95  			if *lookupId == "" || *lookupId == states.LegacyInstanceObjectID(is.Current) {
    96  				c.Ui.Output(addr.String())
    97  			}
    98  		}
    99  	}
   100  
   101  	c.showDiagnostics(diags)
   102  
   103  	return 0
   104  }
   105  
   106  func (c *StateListCommand) Help() string {
   107  	helpText := `
   108  Usage: tofu [global options] state (list|ls) [options] [address...]
   109  
   110    List resources in the OpenTofu state.
   111  
   112    This command lists resource instances in the OpenTofu state. The address
   113    argument can be used to filter the instances by resource or module. If
   114    no pattern is given, all resource instances are listed.
   115  
   116    The addresses must either be module addresses or absolute resource
   117    addresses, such as:
   118        aws_instance.example
   119        module.example
   120        module.example.module.child
   121        module.example.aws_instance.example
   122  
   123    An error will be returned if any of the resources or modules given as
   124    filter addresses do not exist in the state.
   125  
   126  Options:
   127  
   128    -state=statefile    Path to a OpenTofu state file to use to look
   129                        up OpenTofu-managed resources. By default, OpenTofu
   130                        will consult the state of the currently-selected
   131                        workspace.
   132  
   133    -id=ID              Filters the results to include only instances whose
   134                        resource types have an attribute named "id" whose value
   135                        equals the given id string.
   136  
   137  `
   138  	return strings.TrimSpace(helpText)
   139  }
   140  
   141  func (c *StateListCommand) Synopsis() string {
   142  	return "List resources in the state"
   143  }
   144  
   145  const errStateLoadingState = `Error loading the state: %[1]s
   146  
   147  Please ensure that your OpenTofu state exists and that you've
   148  configured it properly. You can use the "-state" flag to point
   149  OpenTofu at another state file.`
   150  
   151  const errStateNotFound = `No state file was found!
   152  
   153  State management commands require a state file. Run this command
   154  in a directory where OpenTofu has been run or use the -state flag
   155  to point the command to a specific state location.`