github.com/anuaimi/terraform@v0.6.4-0.20150904235404-2bf9aec61da8/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 -no-color If specified, output won't contain any color. 153 154 ` 155 return strings.TrimSpace(helpText) 156 } 157 158 func (c *InitCommand) Synopsis() string { 159 return "Initializes Terraform configuration from a module" 160 }