github.com/arvindram03/terraform@v0.3.7-0.20150212015210-408f838db36d/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 }