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