command/import: load configurations and allow empty config dirs

Fixes #7774

This modifies the `import` command to load configuration files from the
pwd. This also augments the configuration loading section for the CLI to
have a new option (default false, same as old behavior) to
allow directories with no Terraform configurations.
For import, we allow directories with no Terraform configurations so
this option is set to true.
This commit is contained in:
Mitchell Hashimoto 2016-11-02 10:30:28 -07:00
parent 2b72882405
commit 5107c33119
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
6 changed files with 105 additions and 4 deletions

View File

@ -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"
@ -34,8 +35,16 @@ func (c *ImportCommand) Run(args []string) int {
return 1 return 1
} }
pwd, err := os.Getwd()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
return 1
}
// 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: pwd,
PathEmptyOk: true,
StatePath: c.Meta.statePath, StatePath: c.Meta.statePath,
Parallelism: c.Meta.parallelism, Parallelism: c.Meta.parallelism,
}) })

View File

@ -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,62 @@ 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 TestRefresh_badState(t *testing.T) { func TestRefresh_badState(t *testing.T) {
p := testProvider() p := testProvider()

View File

@ -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

View File

@ -0,0 +1,3 @@
provider "test" {
foo = "bar"
}

View File

@ -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.

View File

@ -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 {