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