github.com/nalum/terraform@v0.3.2-0.20141223102918-aa2c22ffeff6/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/remote"
    12  	"github.com/hashicorp/terraform/terraform"
    13  )
    14  
    15  // InitCommand is a Command implementation that takes a Terraform
    16  // module and clones it to the working directory.
    17  type InitCommand struct {
    18  	Meta
    19  }
    20  
    21  func (c *InitCommand) Run(args []string) int {
    22  	var remoteBackend, remoteAddress, remoteAccessToken, remoteName, remotePath string
    23  	args = c.Meta.process(args, false)
    24  	cmdFlags := flag.NewFlagSet("init", flag.ContinueOnError)
    25  	cmdFlags.StringVar(&remoteBackend, "backend", "atlas", "")
    26  	cmdFlags.StringVar(&remoteAddress, "address", "", "")
    27  	cmdFlags.StringVar(&remoteAccessToken, "access-token", "", "")
    28  	cmdFlags.StringVar(&remoteName, "name", "", "")
    29  	cmdFlags.StringVar(&remotePath, "path", "", "")
    30  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    31  	if err := cmdFlags.Parse(args); err != nil {
    32  		return 1
    33  	}
    34  
    35  	var path string
    36  	args = cmdFlags.Args()
    37  	if len(args) > 2 {
    38  		c.Ui.Error("The init command expects at most two arguments.\n")
    39  		cmdFlags.Usage()
    40  		return 1
    41  	} else if len(args) < 1 {
    42  		c.Ui.Error("The init command expects at least one arguments.\n")
    43  		cmdFlags.Usage()
    44  		return 1
    45  	}
    46  
    47  	if len(args) == 2 {
    48  		path = args[1]
    49  	} else {
    50  		var err error
    51  		path, err = os.Getwd()
    52  		if err != nil {
    53  			c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
    54  		}
    55  	}
    56  
    57  	source := args[0]
    58  
    59  	// Get our pwd since we need it
    60  	pwd, err := os.Getwd()
    61  	if err != nil {
    62  		c.Ui.Error(fmt.Sprintf(
    63  			"Error reading working directory: %s", err))
    64  		return 1
    65  	}
    66  
    67  	// Verify the directory is empty
    68  	if empty, err := config.IsEmptyDir(path); err != nil {
    69  		c.Ui.Error(fmt.Sprintf(
    70  			"Error checking on destination path: %s", err))
    71  		return 1
    72  	} else if !empty {
    73  		c.Ui.Error(
    74  			"The destination path has Terraform configuration files. The\n" +
    75  				"init command can only be used on a directory without existing Terraform\n" +
    76  				"files.")
    77  		return 1
    78  	}
    79  
    80  	// Detect
    81  	source, err = module.Detect(source, pwd)
    82  	if err != nil {
    83  		c.Ui.Error(fmt.Sprintf(
    84  			"Error with module source: %s", err))
    85  		return 1
    86  	}
    87  
    88  	// Get it!
    89  	if err := module.GetCopy(path, source); err != nil {
    90  		c.Ui.Error(err.Error())
    91  		return 1
    92  	}
    93  
    94  	// Handle remote state if configured
    95  	if remoteAddress != "" || remoteAccessToken != "" || remoteName != "" || remotePath != "" {
    96  		var remoteConf terraform.RemoteState
    97  		remoteConf.Type = remoteBackend
    98  		remoteConf.Config = map[string]string{
    99  			"address":      remoteAddress,
   100  			"access_token": remoteAccessToken,
   101  			"name":         remoteName,
   102  			"path":         remotePath,
   103  		}
   104  
   105  		// Ensure remote state is not already enabled
   106  		haveLocal, err := remote.HaveLocalState()
   107  		if err != nil {
   108  			c.Ui.Error(fmt.Sprintf("Failed to check for local state: %v", err))
   109  			return 1
   110  		}
   111  		if haveLocal {
   112  			c.Ui.Error("Remote state is already enabled. Aborting.")
   113  			return 1
   114  		}
   115  
   116  		// Check if we have the non-managed state file
   117  		haveNonManaged, err := remote.ExistsFile(DefaultStateFilename)
   118  		if err != nil {
   119  			c.Ui.Error(fmt.Sprintf("Failed to check for state file: %v", err))
   120  			return 1
   121  		}
   122  		if haveNonManaged {
   123  			c.Ui.Error(fmt.Sprintf("Existing state file '%s' found. Aborting.",
   124  				DefaultStateFilename))
   125  			return 1
   126  		}
   127  
   128  		// Initialize a blank state file with remote enabled
   129  		remoteCmd := &RemoteCommand{
   130  			Meta:       c.Meta,
   131  			remoteConf: remoteConf,
   132  		}
   133  		return remoteCmd.initBlankState()
   134  	}
   135  	return 0
   136  }
   137  
   138  func (c *InitCommand) Help() string {
   139  	helpText := `
   140  Usage: terraform init [options] SOURCE [PATH]
   141  
   142    Downloads the module given by SOURCE into the PATH. The PATH defaults
   143    to the working directory. PATH must be empty of any Terraform files.
   144    Any conflicting non-Terraform files will be overwritten.
   145  
   146    The module downloaded is a copy. If you're downloading a module from
   147    Git, it will not preserve the Git history, it will only copy the
   148    latest files.
   149  
   150  Options:
   151  
   152    -address=url           URL of the remote storage server.
   153                           Required for HTTP backend, optional for Atlas and Consul.
   154  
   155    -access-token=token    Authentication token for state storage server.
   156                           Required for Atlas backend, optional for Consul.
   157  
   158    -backend=atlas         Specifies the type of remote backend. Must be one
   159                           of Atlas, Consul, or HTTP. Defaults to atlas.
   160  
   161    -name=name             Name of the state file in the state storage server.
   162                           Required for Atlas backend.
   163  
   164    -path=path             Path of the remote state in Consul. Required for the
   165                           Consul backend.
   166  
   167  `
   168  	return strings.TrimSpace(helpText)
   169  }
   170  
   171  func (c *InitCommand) Synopsis() string {
   172  	return "Initializes Terraform configuration from a module"
   173  }