github.com/ggriffiths/terraform@v0.9.0-beta1.0.20170222213024-79c4935604cb/command/import.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/backend"
    10  	"github.com/hashicorp/terraform/config/module"
    11  	"github.com/hashicorp/terraform/terraform"
    12  )
    13  
    14  // ImportCommand is a cli.Command implementation that imports resources
    15  // into the Terraform state.
    16  type ImportCommand struct {
    17  	Meta
    18  }
    19  
    20  func (c *ImportCommand) Run(args []string) int {
    21  	// Get the pwd since its our default -config flag value
    22  	pwd, err := os.Getwd()
    23  	if err != nil {
    24  		c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
    25  		return 1
    26  	}
    27  
    28  	var configPath string
    29  	args = c.Meta.process(args, true)
    30  
    31  	cmdFlags := c.Meta.flagSet("import")
    32  	cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism")
    33  	cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
    34  	cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
    35  	cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path")
    36  	cmdFlags.StringVar(&configPath, "config", pwd, "path")
    37  	cmdFlags.StringVar(&c.Meta.provider, "provider", "", "provider")
    38  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    39  	if err := cmdFlags.Parse(args); err != nil {
    40  		return 1
    41  	}
    42  
    43  	args = cmdFlags.Args()
    44  	if len(args) != 2 {
    45  		c.Ui.Error("The import command expects two arguments.")
    46  		cmdFlags.Usage()
    47  		return 1
    48  	}
    49  
    50  	// Load the module
    51  	var mod *module.Tree
    52  	if configPath != "" {
    53  		var err error
    54  		mod, err = c.Module(configPath)
    55  		if err != nil {
    56  			c.Ui.Error(fmt.Sprintf("Failed to load root config module: %s", err))
    57  			return 1
    58  		}
    59  	}
    60  
    61  	// Load the backend
    62  	b, err := c.Backend(&BackendOpts{ConfigPath: configPath})
    63  	if err != nil {
    64  		c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
    65  		return 1
    66  	}
    67  
    68  	// We require a local backend
    69  	local, ok := b.(backend.Local)
    70  	if !ok {
    71  		c.Ui.Error(ErrUnsupportedLocalOp)
    72  		return 1
    73  	}
    74  
    75  	// Build the operation
    76  	opReq := c.Operation()
    77  	opReq.Module = mod
    78  
    79  	// Get the context
    80  	ctx, state, err := local.Context(opReq)
    81  	if err != nil {
    82  		c.Ui.Error(err.Error())
    83  		return 1
    84  	}
    85  
    86  	// Perform the import. Note that as you can see it is possible for this
    87  	// API to import more than one resource at once. For now, we only allow
    88  	// one while we stabilize this feature.
    89  	newState, err := ctx.Import(&terraform.ImportOpts{
    90  		Targets: []*terraform.ImportTarget{
    91  			&terraform.ImportTarget{
    92  				Addr:     args[0],
    93  				ID:       args[1],
    94  				Provider: c.Meta.provider,
    95  			},
    96  		},
    97  	})
    98  	if err != nil {
    99  		c.Ui.Error(fmt.Sprintf("Error importing: %s", err))
   100  		return 1
   101  	}
   102  
   103  	// Persist the final state
   104  	log.Printf("[INFO] Writing state output to: %s", c.Meta.StateOutPath())
   105  	if err := state.WriteState(newState); err != nil {
   106  		c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
   107  		return 1
   108  	}
   109  	if err := state.PersistState(); err != nil {
   110  		c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
   111  		return 1
   112  	}
   113  
   114  	c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
   115  		"[reset][green]\n" +
   116  			"Import success! The resources imported are shown above. These are\n" +
   117  			"now in your Terraform state. Import does not currently generate\n" +
   118  			"configuration, so you must do this next. If you do not create configuration\n" +
   119  			"for the above resources, then the next `terraform plan` will mark\n" +
   120  			"them for destruction.")))
   121  
   122  	return 0
   123  }
   124  
   125  func (c *ImportCommand) Help() string {
   126  	helpText := `
   127  Usage: terraform import [options] ADDR ID
   128  
   129    Import existing infrastructure into your Terraform state.
   130  
   131    This will find and import the specified resource into your Terraform
   132    state, allowing existing infrastructure to come under Terraform
   133    management without having to be initially created by Terraform.
   134  
   135    The ADDR specified is the address to import the resource to. Please
   136    see the documentation online for resource addresses. The ID is a
   137    resource-specific ID to identify that resource being imported. Please
   138    reference the documentation for the resource type you're importing to
   139    determine the ID syntax to use. It typically matches directly to the ID
   140    that the provider uses.
   141  
   142    In the current state of Terraform import, the resource is only imported
   143    into your state file. Once it is imported, you must manually write
   144    configuration for the new resource or Terraform will mark it for destruction.
   145    Future versions of Terraform will expand the functionality of Terraform
   146    import.
   147  
   148    This command will not modify your infrastructure, but it will make
   149    network requests to inspect parts of your infrastructure relevant to
   150    the resource being imported.
   151  
   152  Options:
   153  
   154    -backup=path        Path to backup the existing state file before
   155                        modifying. Defaults to the "-state-out" path with
   156                        ".backup" extension. Set to "-" to disable backup.
   157  
   158    -config=path        Path to a directory of Terraform configuration files
   159                        to use to configure the provider. Defaults to pwd.
   160                        If no config files are present, they must be provided
   161                        via the input prompts or env vars.
   162  
   163    -input=true         Ask for input for variables if not directly set.
   164  
   165    -no-color           If specified, output won't contain any color.
   166  
   167    -provider=provider  Specific provider to use for import. This is used for
   168                        specifying aliases, such as "aws.eu". Defaults to the
   169                        normal provider prefix of the resource being imported.
   170  
   171    -state=path         Path to read and save state (unless state-out
   172                        is specified). Defaults to "terraform.tfstate".
   173  
   174    -state-out=path     Path to write updated state file. By default, the
   175                        "-state" path will be used.
   176  
   177    -var 'foo=bar'      Set a variable in the Terraform configuration. This
   178                        flag can be set multiple times. This is only useful
   179                        with the "-config" flag.
   180  
   181    -var-file=foo       Set variables in the Terraform configuration from
   182                        a file. If "terraform.tfvars" is present, it will be
   183                        automatically loaded if this flag is not specified.
   184  
   185  
   186  `
   187  	return strings.TrimSpace(helpText)
   188  }
   189  
   190  func (c *ImportCommand) Synopsis() string {
   191  	return "Import existing infrastructure into Terraform"
   192  }