github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/command/providers.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/hashicorp/terraform/moduledeps"
     8  	"github.com/hashicorp/terraform/terraform"
     9  	"github.com/xlab/treeprint"
    10  )
    11  
    12  // ProvidersCommand is a Command implementation that prints out information
    13  // about the providers used in the current configuration/state.
    14  type ProvidersCommand struct {
    15  	Meta
    16  }
    17  
    18  func (c *ProvidersCommand) Help() string {
    19  	return providersCommandHelp
    20  }
    21  
    22  func (c *ProvidersCommand) Synopsis() string {
    23  	return "Prints a tree of the providers used in the configuration"
    24  }
    25  
    26  func (c *ProvidersCommand) Run(args []string) int {
    27  	c.Meta.process(args, false)
    28  
    29  	cmdFlags := c.Meta.flagSet("providers")
    30  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    31  	if err := cmdFlags.Parse(args); err != nil {
    32  		return 1
    33  	}
    34  
    35  	configPath, err := ModulePath(cmdFlags.Args())
    36  	if err != nil {
    37  		c.Ui.Error(err.Error())
    38  		return 1
    39  	}
    40  
    41  	// Load the config
    42  	root, diags := c.Module(configPath)
    43  	if diags.HasErrors() {
    44  		c.showDiagnostics(diags)
    45  		return 1
    46  	}
    47  	if root == nil {
    48  		c.Ui.Error(fmt.Sprintf(
    49  			"No configuration files found in the directory: %s\n\n"+
    50  				"This command requires configuration to run.",
    51  			configPath))
    52  		return 1
    53  	}
    54  
    55  	// Load the backend
    56  	b, err := c.Backend(&BackendOpts{
    57  		Config: root.Config(),
    58  	})
    59  	if err != nil {
    60  		c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
    61  		return 1
    62  	}
    63  
    64  	// Get the state
    65  	env := c.Workspace()
    66  	state, err := b.State(env)
    67  	if err != nil {
    68  		c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
    69  		return 1
    70  	}
    71  	if err := state.RefreshState(); err != nil {
    72  		c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
    73  		return 1
    74  	}
    75  
    76  	s := state.State()
    77  
    78  	depTree := terraform.ModuleTreeDependencies(root, s)
    79  	depTree.SortDescendents()
    80  
    81  	printRoot := treeprint.New()
    82  	providersCommandPopulateTreeNode(printRoot, depTree)
    83  
    84  	c.Ui.Output(printRoot.String())
    85  
    86  	c.showDiagnostics(diags)
    87  	if diags.HasErrors() {
    88  		return 1
    89  	}
    90  
    91  	return 0
    92  }
    93  
    94  func providersCommandPopulateTreeNode(node treeprint.Tree, deps *moduledeps.Module) {
    95  	names := make([]string, 0, len(deps.Providers))
    96  	for name := range deps.Providers {
    97  		names = append(names, string(name))
    98  	}
    99  	sort.Strings(names)
   100  
   101  	for _, name := range names {
   102  		dep := deps.Providers[moduledeps.ProviderInstance(name)]
   103  		versionsStr := dep.Constraints.String()
   104  		if versionsStr != "" {
   105  			versionsStr = " " + versionsStr
   106  		}
   107  		var reasonStr string
   108  		switch dep.Reason {
   109  		case moduledeps.ProviderDependencyInherited:
   110  			reasonStr = " (inherited)"
   111  		case moduledeps.ProviderDependencyFromState:
   112  			reasonStr = " (from state)"
   113  		}
   114  		node.AddNode(fmt.Sprintf("provider.%s%s%s", name, versionsStr, reasonStr))
   115  	}
   116  
   117  	for _, child := range deps.Children {
   118  		childNode := node.AddBranch(fmt.Sprintf("module.%s", child.Name))
   119  		providersCommandPopulateTreeNode(childNode, child)
   120  	}
   121  }
   122  
   123  const providersCommandHelp = `
   124  Usage: terraform providers [dir]
   125  
   126    Prints out a tree of modules in the referenced configuration annotated with
   127    their provider requirements.
   128  
   129    This provides an overview of all of the provider requirements across all
   130    referenced modules, as an aid to understanding why particular provider
   131    plugins are needed and why particular versions are selected.
   132  
   133  `