github.com/sixgill/terraform@v0.9.0-beta2.0.20170316214032-033f6226ae50/command/env_new.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 "github.com/hashicorp/terraform/state" 9 "github.com/hashicorp/terraform/terraform" 10 "github.com/mitchellh/cli" 11 12 clistate "github.com/hashicorp/terraform/command/state" 13 ) 14 15 type EnvNewCommand struct { 16 Meta 17 } 18 19 func (c *EnvNewCommand) Run(args []string) int { 20 args = c.Meta.process(args, true) 21 22 statePath := "" 23 24 cmdFlags := c.Meta.flagSet("env new") 25 cmdFlags.StringVar(&statePath, "state", "", "terraform state file") 26 cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } 27 if err := cmdFlags.Parse(args); err != nil { 28 return 1 29 } 30 args = cmdFlags.Args() 31 if len(args) == 0 { 32 c.Ui.Error("Expected a single argument: NAME.\n") 33 return cli.RunResultHelp 34 } 35 36 newEnv := args[0] 37 38 configPath, err := ModulePath(args[1:]) 39 if err != nil { 40 c.Ui.Error(err.Error()) 41 return 1 42 } 43 44 // Load the backend 45 b, err := c.Backend(&BackendOpts{ConfigPath: configPath}) 46 if err != nil { 47 c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) 48 return 1 49 } 50 51 states, err := b.States() 52 for _, s := range states { 53 if newEnv == s { 54 c.Ui.Error(fmt.Sprintf(envExists, newEnv)) 55 return 1 56 } 57 } 58 59 _, err = b.State(newEnv) 60 if err != nil { 61 c.Ui.Error(err.Error()) 62 return 1 63 } 64 65 // now save the current env locally 66 if err := c.SetEnv(newEnv); err != nil { 67 c.Ui.Error(fmt.Sprintf("error saving new environment name: %s", err)) 68 return 1 69 } 70 71 c.Ui.Output(c.Colorize().Color(fmt.Sprintf( 72 strings.TrimSpace(envCreated), newEnv))) 73 74 if statePath == "" { 75 // if we're not loading a state, then we're done 76 return 0 77 } 78 79 // load the new Backend state 80 sMgr, err := b.State(newEnv) 81 if err != nil { 82 c.Ui.Error(err.Error()) 83 return 1 84 } 85 86 // Lock the state if we can 87 lockInfo := state.NewLockInfo() 88 lockInfo.Operation = "env new" 89 lockID, err := clistate.Lock(sMgr, lockInfo, c.Ui, c.Colorize()) 90 if err != nil { 91 c.Ui.Error(fmt.Sprintf("Error locking state: %s", err)) 92 return 1 93 } 94 defer clistate.Unlock(sMgr, lockID, c.Ui, c.Colorize()) 95 96 // read the existing state file 97 stateFile, err := os.Open(statePath) 98 if err != nil { 99 c.Ui.Error(err.Error()) 100 return 1 101 } 102 103 s, err := terraform.ReadState(stateFile) 104 if err != nil { 105 c.Ui.Error(err.Error()) 106 return 1 107 } 108 109 // save the existing state in the new Backend. 110 err = sMgr.WriteState(s) 111 if err != nil { 112 c.Ui.Error(err.Error()) 113 return 1 114 } 115 116 return 0 117 } 118 119 func (c *EnvNewCommand) Help() string { 120 helpText := ` 121 Usage: terraform env new [OPTIONS] NAME [DIR] 122 123 Create a new Terraform environment. 124 125 126 Options: 127 128 -state=path Copy an existing state file into the new environment. 129 ` 130 return strings.TrimSpace(helpText) 131 } 132 133 func (c *EnvNewCommand) Synopsis() string { 134 return "Create a new environment" 135 }