Skip to content

Commit

Permalink
Implements import with specified provider
Browse files Browse the repository at this point in the history
This allows the import with a specified provider.
So far it was not possible to get resources imported from a different provider
than the default.
  • Loading branch information
spangenberg authored and fatmcgav committed Feb 27, 2017
1 parent c53a544 commit dd929d9
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 16 deletions.
8 changes: 6 additions & 2 deletions command/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func (c *ImportCommand) Run(args []string) int {
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path")
cmdFlags.StringVar(&configPath, "config", pwd, "path")
cmdFlags.StringVar(&c.Meta.provider, "provider", "", "provider")
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
if err := cmdFlags.Parse(args); err != nil {
return 1
Expand Down Expand Up @@ -62,8 +63,9 @@ func (c *ImportCommand) Run(args []string) int {
newState, err := ctx.Import(&terraform.ImportOpts{
Targets: []*terraform.ImportTarget{
&terraform.ImportTarget{
Addr: args[0],
ID: args[1],
Addr: args[0],
ID: args[1],
Provider: c.Meta.provider,
},
},
})
Expand Down Expand Up @@ -138,6 +140,8 @@ Options:
-state-out=path Path to write updated state file. By default, the
"-state" path will be used.
-provider=provider Provider used for import. Defaults to: ""
`
return strings.TrimSpace(helpText)
}
Expand Down
45 changes: 45 additions & 0 deletions command/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,53 @@ func TestRefresh_displaysOutputs(t *testing.T) {
}
*/

func TestImport_customProvider(t *testing.T) {
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",
},
},
}

args := []string{
"-provider", "test.alias",
"-state", statePath,
"test_instance.foo",
"bar",
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}

if !p.ImportStateCalled {
t.Fatal("ImportState should be called")
}

testStateOutput(t, statePath, testImportCustomProviderStr)
}

const testImportStr = `
test_instance.foo:
ID = yay
provider = test
`

const testImportCustomProviderStr = `
test_instance.foo:
ID = yay
provider = test.alias
`
3 changes: 3 additions & 0 deletions command/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,14 @@ type Meta struct {
// allowed when walking the graph
//
// shadow is used to enable/disable the shadow graph
//
// provider is to specify specific resource providers
statePath string
stateOutPath string
backupPath string
parallelism int
shadow bool
provider string
}

// initStatePaths is used to initialize the default values for
Expand Down
3 changes: 3 additions & 0 deletions terraform/context_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type ImportTarget struct {

// ID is the ID of the resource to import. This is resource-specific.
ID string

// Provider string
Provider string
}

// Import takes already-created external resources and brings them
Expand Down
43 changes: 42 additions & 1 deletion terraform/context_import_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// TODO
package terraform

import (
Expand Down Expand Up @@ -32,7 +33,6 @@ func TestContextImport_basic(t *testing.T) {
if err != nil {
t.Fatalf("err: %s", err)
}

actual := strings.TrimSpace(state.String())
expected := strings.TrimSpace(testImportStr)
if actual != expected {
Expand Down Expand Up @@ -621,6 +621,41 @@ func TestContextImport_multiStateSame(t *testing.T) {
}
}

func TestContextImport_customProvider(t *testing.T) {
p := testProvider("aws")
ctx := testContext2(t, &ContextOpts{
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
})

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",
Provider: "aws.alias",
},
},
})
if err != nil {
t.Fatalf("err: %s", err)
}

actual := strings.TrimSpace(state.String())
expected := strings.TrimSpace(testImportCustomProviderStr)
if actual != expected {
t.Fatalf("bad: \n%s", actual)
}
}

const testImportStr = `
aws_instance.foo:
ID = foo
Expand Down Expand Up @@ -700,3 +735,9 @@ aws_instance.foo:
provider = aws
foo = bar
`

const testImportCustomProviderStr = `
aws_instance.foo:
ID = foo
provider = aws.alias
`
30 changes: 17 additions & 13 deletions terraform/transform_import_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ func (t *ImportStateTransformer) Transform(g *Graph) error {
}

nodes = append(nodes, &graphNodeImportState{
Addr: addr,
ID: target.ID,
Addr: addr,
ID: target.ID,
Provider: target.Provider,
})
}

Expand All @@ -35,8 +36,9 @@ func (t *ImportStateTransformer) Transform(g *Graph) error {
}

type graphNodeImportState struct {
Addr *ResourceAddress // Addr is the resource address to import to
ID string // ID is the ID to import as
Addr *ResourceAddress // Addr is the resource address to import to
ID string // ID is the ID to import as
Provider string // Provider string

states []*InstanceState
}
Expand All @@ -46,7 +48,7 @@ func (n *graphNodeImportState) Name() string {
}

func (n *graphNodeImportState) ProvidedBy() []string {
return []string{resourceProvider(n.Addr.Type, "")}
return []string{resourceProvider(n.Addr.Type, n.Provider)}
}

// GraphNodeSubPath
Expand Down Expand Up @@ -147,9 +149,10 @@ func (n *graphNodeImportState) DynamicExpand(ctx EvalContext) (*Graph, error) {
// is safe.
for i, state := range n.states {
g.Add(&graphNodeImportStateSub{
Target: addrs[i],
Path_: n.Path(),
State: state,
Target: addrs[i],
Path_: n.Path(),
State: state,
Provider: n.Provider,
})
}

Expand All @@ -167,9 +170,10 @@ func (n *graphNodeImportState) DynamicExpand(ctx EvalContext) (*Graph, error) {
// and is part of the subgraph. This node is responsible for refreshing
// and adding a resource to the state once it is imported.
type graphNodeImportStateSub struct {
Target *ResourceAddress
State *InstanceState
Path_ []string
Target *ResourceAddress
State *InstanceState
Path_ []string
Provider string
}

func (n *graphNodeImportStateSub) Name() string {
Expand Down Expand Up @@ -212,7 +216,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode {
return &EvalSequence{
Nodes: []EvalNode{
&EvalGetProvider{
Name: resourceProvider(info.Type, ""),
Name: resourceProvider(info.Type, n.Provider),
Output: &provider,
},
&EvalRefresh{
Expand All @@ -229,7 +233,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode {
&EvalWriteState{
Name: key.String(),
ResourceType: info.Type,
Provider: resourceProvider(info.Type, ""),
Provider: resourceProvider(info.Type, n.Provider),
State: &state,
},
},
Expand Down
3 changes: 3 additions & 0 deletions website/source/docs/commands/import.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ The command-line flags are all optional. The list of available flags are:
the state path. Ignored when [remote state](/docs/state/remote/index.html) is
used.

* `-provider=provider` - Provider used for import. Defaults to the default
provider of the resource to import.

## Provider Configuration

Terraform will attempt to load configuration files that configure the
Expand Down

0 comments on commit dd929d9

Please sign in to comment.