github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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  }