github.com/ndarilek/terraform@v0.3.8-0.20150320140257-d3135c1b2bac/command/init.go (about)

     1  package command
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/config"
    10  	"github.com/hashicorp/terraform/config/module"
    11  	"github.com/hashicorp/terraform/terraform"
    12  )
    13  
    14  // InitCommand is a Command implementation that takes a Terraform
    15  // module and clones it to the working directory.
    16  type InitCommand struct {
    17  	Meta
    18  }
    19  
    20  func (c *InitCommand) Run(args []string) int {
    21  	var remoteBackend string
    22  	args = c.Meta.process(args, false)
    23  	remoteConfig := make(map[string]string)
    24  	cmdFlags := flag.NewFlagSet("init", flag.ContinueOnError)
    25  	cmdFlags.StringVar(&remoteBackend, "backend", "", "")
    26  	cmdFlags.Var((*FlagKV)(&remoteConfig), "backend-config", "config")
    27  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    28  	if err := cmdFlags.Parse(args); err != nil {
    29  		return 1
    30  	}
    31  
    32  	var path string
    33  	args = cmdFlags.Args()
    34  	if len(args) > 2 {
    35  		c.Ui.Error("The init command expects at most two arguments.\n")
    36  		cmdFlags.Usage()
    37  		return 1
    38  	} else if len(args) < 1 {
    39  		c.Ui.Error("The init command expects at least one arguments.\n")
    40  		cmdFlags.Usage()
    41  		return 1
    42  	}
    43  
    44  	if len(args) == 2 {
    45  		path = args[1]
    46  	} else {
    47  		var err error
    48  		path, err = os.Getwd()
    49  		if err != nil {
    50  			c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
    51  		}
    52  	}
    53  
    54  	source := args[0]
    55  
    56  	// Get our pwd since we need it
    57  	pwd, err := os.Getwd()
    58  	if err != nil {
    59  		c.Ui.Error(fmt.Sprintf(
    60  			"Error reading working directory: %s", err))
    61  		return 1
    62  	}
    63  
    64  	// Verify the directory is empty
    65  	if empty, err := config.IsEmptyDir(path); err != nil {
    66  		c.Ui.Error(fmt.Sprintf(
    67  			"Error checking on destination path: %s", err))
    68  		return 1
    69  	} else if !empty {
    70  		c.Ui.Error(
    71  			"The destination path has Terraform configuration files. The\n" +
    72  				"init command can only be used on a directory without existing Terraform\n" +
    73  				"files.")
    74  		return 1
    75  	}
    76  
    77  	// Detect
    78  	source, err = module.Detect(source, pwd)
    79  	if err != nil {
    80  		c.Ui.Error(fmt.Sprintf(
    81  			"Error with module source: %s", err))
    82  		return 1
    83  	}
    84  
    85  	// Get it!
    86  	if err := module.GetCopy(path, source); err != nil {
    87  		c.Ui.Error(err.Error())
    88  		return 1
    89  	}
    90  
    91  	// Handle remote state if configured
    92  	if remoteBackend != "" {
    93  		var remoteConf terraform.RemoteState
    94  		remoteConf.Type = remoteBackend
    95  		remoteConf.Config = remoteConfig
    96  
    97  		state, err := c.State()
    98  		if err != nil {
    99  			c.Ui.Error(fmt.Sprintf("Error checking for state: %s", err))
   100  			return 1
   101  		}
   102  		if state != nil {
   103  			s := state.State()
   104  			if !s.Empty() {
   105  				c.Ui.Error(fmt.Sprintf(
   106  					"State file already exists and is not empty! Please remove this\n" +
   107  						"state file before initializing. Note that removing the state file\n" +
   108  						"may result in a loss of information since Terraform uses this\n" +
   109  						"to track your infrastructure."))
   110  				return 1
   111  			}
   112  			if s.IsRemote() {
   113  				c.Ui.Error(fmt.Sprintf(
   114  					"State file already exists with remote state enabled! Please remove this\n" +
   115  						"state file before initializing. Note that removing the state file\n" +
   116  						"may result in a loss of information since Terraform uses this\n" +
   117  						"to track your infrastructure."))
   118  				return 1
   119  			}
   120  		}
   121  
   122  		// Initialize a blank state file with remote enabled
   123  		remoteCmd := &RemoteConfigCommand{
   124  			Meta:       c.Meta,
   125  			remoteConf: remoteConf,
   126  		}
   127  		return remoteCmd.initBlankState()
   128  	}
   129  	return 0
   130  }
   131  
   132  func (c *InitCommand) Help() string {
   133  	helpText := `
   134  Usage: terraform init [options] SOURCE [PATH]
   135  
   136    Downloads the module given by SOURCE into the PATH. The PATH defaults
   137    to the working directory. PATH must be empty of any Terraform files.
   138    Any conflicting non-Terraform files will be overwritten.
   139  
   140    The module downloaded is a copy. If you're downloading a module from
   141    Git, it will not preserve the Git history, it will only copy the
   142    latest files.
   143  
   144  Options:
   145  
   146    -backend=atlas         Specifies the type of remote backend. If not
   147                           specified, local storage will be used.
   148  
   149    -backend-config="k=v"  Specifies configuration for the remote storage
   150                           backend. This can be specified multiple times.
   151  
   152  `
   153  	return strings.TrimSpace(helpText)
   154  }
   155  
   156  func (c *InitCommand) Synopsis() string {
   157  	return "Initializes Terraform configuration from a module"
   158  }