Merge pull request #9809 from hashicorp/f-import-provider
command/import: allow configuration from files
This commit is contained in:
commit
ec55cecc70
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -15,13 +16,22 @@ type ImportCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ImportCommand) Run(args []string) int {
|
func (c *ImportCommand) Run(args []string) int {
|
||||||
|
// Get the pwd since its our default -config flag value
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var configPath string
|
||||||
args = c.Meta.process(args, true)
|
args = c.Meta.process(args, true)
|
||||||
|
|
||||||
cmdFlags := c.Meta.flagSet("import")
|
cmdFlags := c.Meta.flagSet("import")
|
||||||
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
|
||||||
cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism")
|
cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism")
|
||||||
|
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
||||||
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
|
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
|
||||||
cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path")
|
cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path")
|
||||||
|
cmdFlags.StringVar(&configPath, "config", pwd, "path")
|
||||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := cmdFlags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
|
@ -36,6 +46,8 @@ func (c *ImportCommand) Run(args []string) int {
|
||||||
|
|
||||||
// Build the context based on the arguments given
|
// Build the context based on the arguments given
|
||||||
ctx, _, err := c.Context(contextOpts{
|
ctx, _, err := c.Context(contextOpts{
|
||||||
|
Path: configPath,
|
||||||
|
PathEmptyOk: true,
|
||||||
StatePath: c.Meta.statePath,
|
StatePath: c.Meta.statePath,
|
||||||
Parallelism: c.Meta.parallelism,
|
Parallelism: c.Meta.parallelism,
|
||||||
})
|
})
|
||||||
|
@ -111,6 +123,11 @@ Options:
|
||||||
modifying. Defaults to the "-state-out" path with
|
modifying. Defaults to the "-state-out" path with
|
||||||
".backup" extension. Set to "-" to disable backup.
|
".backup" extension. Set to "-" to disable backup.
|
||||||
|
|
||||||
|
-config=path Path to a directory of Terraform configuration files
|
||||||
|
to use to configure the provider. Defaults to pwd.
|
||||||
|
If no config files are present, they must be provided
|
||||||
|
via the input prompts or env vars.
|
||||||
|
|
||||||
-input=true Ask for input for variables if not directly set.
|
-input=true Ask for input for variables if not directly set.
|
||||||
|
|
||||||
-no-color If specified, output won't contain any color.
|
-no-color If specified, output won't contain any color.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -45,6 +46,119 @@ func TestImport(t *testing.T) {
|
||||||
testStateOutput(t, statePath, testImportStr)
|
testStateOutput(t, statePath, testImportStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImport_providerConfig(t *testing.T) {
|
||||||
|
defer testChdir(t, testFixturePath("import-provider"))()
|
||||||
|
|
||||||
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
|
p := testProvider()
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &ImportCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(p),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
p.ImportStateFn = nil
|
||||||
|
p.ImportStateReturn = []*terraform.InstanceState{
|
||||||
|
&terraform.InstanceState{
|
||||||
|
ID: "yay",
|
||||||
|
Ephemeral: terraform.EphemeralState{
|
||||||
|
Type: "test_instance",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
configured := false
|
||||||
|
p.ConfigureFn = func(c *terraform.ResourceConfig) error {
|
||||||
|
configured = true
|
||||||
|
|
||||||
|
if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
|
||||||
|
return fmt.Errorf("bad value: %#v", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-state", statePath,
|
||||||
|
"test_instance.foo",
|
||||||
|
"bar",
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that we were called
|
||||||
|
if !configured {
|
||||||
|
t.Fatal("Configure should be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.ImportStateCalled {
|
||||||
|
t.Fatal("ImportState should be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
testStateOutput(t, statePath, testImportStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImport_providerConfigDisable(t *testing.T) {
|
||||||
|
defer testChdir(t, testFixturePath("import-provider"))()
|
||||||
|
|
||||||
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
|
p := testProvider()
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &ImportCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(p),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
p.ImportStateFn = nil
|
||||||
|
p.ImportStateReturn = []*terraform.InstanceState{
|
||||||
|
&terraform.InstanceState{
|
||||||
|
ID: "yay",
|
||||||
|
Ephemeral: terraform.EphemeralState{
|
||||||
|
Type: "test_instance",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
configured := false
|
||||||
|
p.ConfigureFn = func(c *terraform.ResourceConfig) error {
|
||||||
|
configured = true
|
||||||
|
|
||||||
|
if v, ok := c.Get("foo"); ok {
|
||||||
|
return fmt.Errorf("bad value: %#v", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-state", statePath,
|
||||||
|
"-config", "",
|
||||||
|
"test_instance.foo",
|
||||||
|
"bar",
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that we were called
|
||||||
|
if !configured {
|
||||||
|
t.Fatal("Configure should be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.ImportStateCalled {
|
||||||
|
t.Fatal("ImportState should be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
testStateOutput(t, statePath, testImportStr)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func TestRefresh_badState(t *testing.T) {
|
func TestRefresh_badState(t *testing.T) {
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
|
|
|
@ -5,11 +5,14 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/go-getter"
|
"github.com/hashicorp/go-getter"
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/helper/experiment"
|
"github.com/hashicorp/terraform/helper/experiment"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/state"
|
||||||
|
@ -163,6 +166,17 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
|
||||||
var mod *module.Tree
|
var mod *module.Tree
|
||||||
if copts.Path != "" {
|
if copts.Path != "" {
|
||||||
mod, err = module.NewTreeModule("", copts.Path)
|
mod, err = module.NewTreeModule("", copts.Path)
|
||||||
|
|
||||||
|
// Check for the error where we have no config files but
|
||||||
|
// allow that. If that happens, clear the error.
|
||||||
|
if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) &&
|
||||||
|
copts.PathEmptyOk {
|
||||||
|
log.Printf(
|
||||||
|
"[WARN] Empty configuration dir, ignoring: %s", copts.Path)
|
||||||
|
err = nil
|
||||||
|
mod = module.NewEmptyTree()
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("Error loading config: %s", err)
|
return nil, false, fmt.Errorf("Error loading config: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -495,7 +509,11 @@ func (m *Meta) outputShadowError(err error, output bool) bool {
|
||||||
// contextOpts are the options used to load a context from a command.
|
// contextOpts are the options used to load a context from a command.
|
||||||
type contextOpts struct {
|
type contextOpts struct {
|
||||||
// Path to the directory where the root module is.
|
// Path to the directory where the root module is.
|
||||||
|
//
|
||||||
|
// PathEmptyOk, when set, will allow paths that have no Terraform
|
||||||
|
// configurations. The result in that case will be an empty module.
|
||||||
Path string
|
Path string
|
||||||
|
PathEmptyOk bool
|
||||||
|
|
||||||
// StatePath is the path to the state file. If this is empty, then
|
// StatePath is the path to the state file. If this is empty, then
|
||||||
// no state will be loaded. It is also okay for this to be a path to
|
// no state will be loaded. It is also okay for this to be a path to
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
provider "test" {
|
||||||
|
foo = "bar"
|
||||||
|
}
|
|
@ -12,6 +12,18 @@ import (
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrNoConfigsFound is the error returned by LoadDir if no
|
||||||
|
// Terraform configuration files were found in the given directory.
|
||||||
|
type ErrNoConfigsFound struct {
|
||||||
|
Dir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrNoConfigsFound) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"No Terraform configuration files found in directory: %s",
|
||||||
|
e.Dir)
|
||||||
|
}
|
||||||
|
|
||||||
// LoadJSON loads a single Terraform configuration from a given JSON document.
|
// LoadJSON loads a single Terraform configuration from a given JSON document.
|
||||||
//
|
//
|
||||||
// The document must be a complete Terraform configuration. This function will
|
// The document must be a complete Terraform configuration. This function will
|
||||||
|
@ -69,9 +81,7 @@ func LoadDir(root string) (*Config, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
return nil, fmt.Errorf(
|
return nil, &ErrNoConfigsFound{Dir: root}
|
||||||
"No Terraform configuration files found in directory: %s",
|
|
||||||
root)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the absolute path to the directory.
|
// Determine the absolute path to the directory.
|
||||||
|
|
|
@ -8,6 +8,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestErrNoConfigsFound_impl(t *testing.T) {
|
||||||
|
var _ error = new(ErrNoConfigsFound)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsEmptyDir(t *testing.T) {
|
func TestIsEmptyDir(t *testing.T) {
|
||||||
val, err := IsEmptyDir(fixtureDir)
|
val, err := IsEmptyDir(fixtureDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -43,10 +43,17 @@ func (c *Context) Import(opts *ImportOpts) (*State, error) {
|
||||||
// Copy our own state
|
// Copy our own state
|
||||||
c.state = c.state.DeepCopy()
|
c.state = c.state.DeepCopy()
|
||||||
|
|
||||||
|
// If no module is given, default to the module configured with
|
||||||
|
// the Context.
|
||||||
|
module := opts.Module
|
||||||
|
if module == nil {
|
||||||
|
module = c.module
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize our graph builder
|
// Initialize our graph builder
|
||||||
builder := &ImportGraphBuilder{
|
builder := &ImportGraphBuilder{
|
||||||
ImportTargets: opts.Targets,
|
ImportTargets: opts.Targets,
|
||||||
Module: opts.Module,
|
Module: module,
|
||||||
Providers: c.components.ResourceProviders(),
|
Providers: c.components.ResourceProviders(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,91 @@ func TestContextImport_moduleProvider(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that import will interpolate provider configuration and use
|
||||||
|
// that configuration for import.
|
||||||
|
func TestContextImport_providerVarConfig(t *testing.T) {
|
||||||
|
p := testProvider("aws")
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Module: testModule(t, "import-provider-vars"),
|
||||||
|
Providers: map[string]ResourceProviderFactory{
|
||||||
|
"aws": testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
Variables: map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
configured := false
|
||||||
|
p.ConfigureFn = func(c *ResourceConfig) error {
|
||||||
|
configured = true
|
||||||
|
|
||||||
|
if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
|
||||||
|
return fmt.Errorf("bad value: %#v", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p.ImportStateReturn = []*InstanceState{
|
||||||
|
&InstanceState{
|
||||||
|
ID: "foo",
|
||||||
|
Ephemeral: EphemeralState{Type: "aws_instance"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
state, err := ctx.Import(&ImportOpts{
|
||||||
|
Targets: []*ImportTarget{
|
||||||
|
&ImportTarget{
|
||||||
|
Addr: "aws_instance.foo",
|
||||||
|
ID: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !configured {
|
||||||
|
t.Fatal("didn't configure provider")
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(state.String())
|
||||||
|
expected := strings.TrimSpace(testImportStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad: \n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that provider configs can't reference resources.
|
||||||
|
func TestContextImport_providerNonVarConfig(t *testing.T) {
|
||||||
|
p := testProvider("aws")
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Module: testModule(t, "import-provider-non-vars"),
|
||||||
|
Providers: map[string]ResourceProviderFactory{
|
||||||
|
"aws": testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
p.ImportStateReturn = []*InstanceState{
|
||||||
|
&InstanceState{
|
||||||
|
ID: "foo",
|
||||||
|
Ephemeral: EphemeralState{Type: "aws_instance"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ctx.Import(&ImportOpts{
|
||||||
|
Targets: []*ImportTarget{
|
||||||
|
&ImportTarget{
|
||||||
|
Addr: "aws_instance.foo",
|
||||||
|
ID: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContextImport_refresh(t *testing.T) {
|
func TestContextImport_refresh(t *testing.T) {
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
ctx := testContext2(t, &ContextOpts{
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
|
|
@ -36,6 +36,14 @@ func (b *ImportGraphBuilder) Steps() []GraphTransformer {
|
||||||
mod = module.NewEmptyTree()
|
mod = module.NewEmptyTree()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom factory for creating providers.
|
||||||
|
providerFactory := func(name string, path []string) GraphNodeProvider {
|
||||||
|
return &NodeApplyableProvider{
|
||||||
|
NameValue: name,
|
||||||
|
PathValue: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
steps := []GraphTransformer{
|
steps := []GraphTransformer{
|
||||||
// Create all our resources from the configuration and state
|
// Create all our resources from the configuration and state
|
||||||
&ConfigTransformerOld{Module: mod},
|
&ConfigTransformerOld{Module: mod},
|
||||||
|
@ -44,17 +52,18 @@ func (b *ImportGraphBuilder) Steps() []GraphTransformer {
|
||||||
&ImportStateTransformer{Targets: b.ImportTargets},
|
&ImportStateTransformer{Targets: b.ImportTargets},
|
||||||
|
|
||||||
// Provider-related transformations
|
// Provider-related transformations
|
||||||
&MissingProviderTransformer{Providers: b.Providers},
|
&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
|
||||||
&ProviderTransformer{},
|
&ProviderTransformer{},
|
||||||
&DisableProviderTransformerOld{},
|
&DisableProviderTransformerOld{},
|
||||||
&PruneProviderTransformer{},
|
&PruneProviderTransformer{},
|
||||||
|
&AttachProviderConfigTransformer{Module: mod},
|
||||||
|
|
||||||
|
// This validates that the providers only depend on variables
|
||||||
|
&ImportProviderValidateTransformer{},
|
||||||
|
|
||||||
// Single root
|
// Single root
|
||||||
&RootTransformer{},
|
&RootTransformer{},
|
||||||
|
|
||||||
// Insert nodes to close opened plugin connections
|
|
||||||
&CloseProviderTransformer{},
|
|
||||||
|
|
||||||
// Optimize
|
// Optimize
|
||||||
&TransitiveReductionTransformer{},
|
&TransitiveReductionTransformer{},
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
provider "aws" {
|
||||||
|
foo = "${aws_instance.foo.bar}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "foo" {
|
||||||
|
bar = "value"
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
variable "foo" {}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
foo = "${var.foo}"
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ImportProviderValidateTransformer is a GraphTransformer that goes through
|
||||||
|
// the providers in the graph and validates that they only depend on variables.
|
||||||
|
type ImportProviderValidateTransformer struct{}
|
||||||
|
|
||||||
|
func (t *ImportProviderValidateTransformer) Transform(g *Graph) error {
|
||||||
|
for _, v := range g.Vertices() {
|
||||||
|
// We only care about providers
|
||||||
|
pv, ok := v.(GraphNodeProvider)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only care about providers that reference things
|
||||||
|
rn, ok := pv.(GraphNodeReferencer)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ref := range rn.References() {
|
||||||
|
if !strings.HasPrefix(ref, "var.") {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Provider %q depends on non-var %q. Providers for import can currently\n"+
|
||||||
|
"only depend on variables or must be hardcoded. You can stop import\n"+
|
||||||
|
"from loading configurations by specifying `-config=\"\"`.",
|
||||||
|
pv.ProviderName(), ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -35,6 +35,11 @@ The command-line flags are all optional. The list of available flags are:
|
||||||
the `-state-out` path with the ".backup" extension. Set to "-" to disable
|
the `-state-out` path with the ".backup" extension. Set to "-" to disable
|
||||||
backups.
|
backups.
|
||||||
|
|
||||||
|
* `-config=path` - Path to directory of Terraform configuration files that
|
||||||
|
configure the provider for import. This defaults to your working directory.
|
||||||
|
If this directory contains no Terraform configuration files, the provider
|
||||||
|
must be configured via manual input or environmental variables.
|
||||||
|
|
||||||
* `-input=true` - Whether to ask for input for provider configuration.
|
* `-input=true` - Whether to ask for input for provider configuration.
|
||||||
|
|
||||||
* `-state=path` - The path to read and save state files (unless state-out is
|
* `-state=path` - The path to read and save state files (unless state-out is
|
||||||
|
@ -46,12 +51,35 @@ The command-line flags are all optional. The list of available flags are:
|
||||||
|
|
||||||
## Provider Configuration
|
## Provider Configuration
|
||||||
|
|
||||||
To access the provider that the resource is being imported from, Terraform
|
Terraform will attempt to load configuration files that configure the
|
||||||
will ask you for access credentials. If you don't want to be asked for input,
|
provider being used for import. If no configuration files are present or
|
||||||
verify that all environment variables for your provider are set.
|
no configuration for that specific provider is present, Terraform will
|
||||||
|
prompt you for access credentials. You may also specify environmental variables
|
||||||
|
to configure the provider.
|
||||||
|
|
||||||
The import command cannot read provider configuration from a Terraform
|
The only limitation Terraform has when reading the configuration files
|
||||||
configuration file.
|
is that the import provider configurations must not depend on non-variable
|
||||||
|
inputs. For example, a provider configuration cannot depend on a data
|
||||||
|
source.
|
||||||
|
|
||||||
|
As a working example, if you're importing AWS resources and you have a
|
||||||
|
configuration file with the contents below, then Terraform will configure
|
||||||
|
the AWS provider with this file.
|
||||||
|
|
||||||
|
```
|
||||||
|
variable "access_key" {}
|
||||||
|
variable "secret_key" {}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
access_key = "${var.access_key}"
|
||||||
|
secret_key = "${var.secret_key}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can force Terraform to explicitly not load your configuration by
|
||||||
|
specifying `-config=""` (empty string). This is useful in situations where
|
||||||
|
you want to manually configure the provider because your configuration
|
||||||
|
may not be valid.
|
||||||
|
|
||||||
## Example: AWS Instance
|
## Example: AWS Instance
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,6 @@ $ terraform import aws_instance.bar i-abcd1234
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
~> **Note:** In order to import resources, the provider should be configured with environment variables.
|
|
||||||
We currently do not support passing credentials directly to the provider.
|
|
||||||
|
|
||||||
The above command imports an AWS instance with the given ID to the
|
The above command imports an AWS instance with the given ID to the
|
||||||
address `aws_instance.bar`. You can also import resources into modules.
|
address `aws_instance.bar`. You can also import resources into modules.
|
||||||
See the [resource addressing](/docs/internals/resource-addressing.html)
|
See the [resource addressing](/docs/internals/resource-addressing.html)
|
||||||
|
|
Loading…
Reference in New Issue