change init args to remove source copy

When init was modified in 0.9 to initialize a terraform working
directory, the legacy behavior was kept to copy or fetch module sources.
This left the init command without the ability that the plan and apply
commands have to target a specific directory for the operation.

This commit removes the legacy behavior altogether, and allows init to
target a directory for initialization, bringing it into parity with plan
and apply. If one want to copy a module to the target or current
directory, that will have to be done manually before calling init. We
can later reintroduce fetching modules with init without breaking this
new behavior, by adding the source as an optional second argument.

The unit tests testing the copying of sources with init have been
removed, as well as some out of date (and commented out) init tests
regarding remote states.
This commit is contained in:
James Bardin 2017-06-02 16:13:11 -04:00
parent 73139ba6aa
commit 2bfcdbbd08
3 changed files with 17 additions and 411 deletions

View File

@ -378,73 +378,6 @@ func TestApply_error(t *testing.T) {
}
}
func TestApply_init(t *testing.T) {
// Change to the temporary directory
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("err: %s", err)
}
dir := tempDir(t)
if err := os.MkdirAll(dir, 0755); err != nil {
t.Fatalf("err: %s", err)
}
if err := os.Chdir(dir); err != nil {
t.Fatalf("err: %s", err)
}
defer os.Chdir(cwd)
// Create the test fixtures
statePath := testTempFile(t)
ln := testHttpServer(t)
defer ln.Close()
// Initialize the command
p := testProvider()
ui := new(cli.MockUi)
c := &ApplyCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}
// Build the URL to the init
var u url.URL
u.Scheme = "http"
u.Host = ln.Addr().String()
u.Path = "/header"
args := []string{
"-state", statePath,
u.String(),
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
if _, err := os.Stat("hello.tf"); err != nil {
t.Fatalf("err: %s", err)
}
if _, err := os.Stat(statePath); err != nil {
t.Fatalf("err: %s", err)
}
f, err := os.Open(statePath)
if err != nil {
t.Fatalf("err: %s", err)
}
defer f.Close()
state, err := terraform.ReadState(f)
if err != nil {
t.Fatalf("err: %s", err)
}
if state == nil {
t.Fatal("state should not be nil")
}
}
func TestApply_input(t *testing.T) {
// Disable test mode so input would be asked
test = false

View File

@ -8,7 +8,6 @@ import (
"sort"
"strings"
getter "github.com/hashicorp/go-getter"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/config"
@ -58,8 +57,8 @@ func (c *InitCommand) Run(args []string) int {
// Validate the arg count
args = cmdFlags.Args()
if len(args) > 2 {
c.Ui.Error("The init command expects at most two arguments.\n")
if len(args) > 1 {
c.Ui.Error("The init command expects at most one argument.\n")
cmdFlags.Usage()
return 1
}
@ -73,21 +72,10 @@ func (c *InitCommand) Run(args []string) int {
}
// Get the path and source module to copy
var path string
var source string
switch len(args) {
case 0:
path = pwd
case 1:
path = pwd
source = args[0]
case 2:
source = args[0]
path = args[1]
default:
panic("assertion failed on arg count")
path := pwd
if len(args) == 1 {
path = args[0]
}
// Set the state out path to be the path requested for the module
// to be copied. This ensures any remote states gets setup in the
// proper directory.
@ -97,20 +85,6 @@ func (c *InitCommand) Run(args []string) int {
// to output a newline before the success message
var header bool
// If we have a source, copy it
if source != "" {
c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
"[reset][bold]"+
"Initializing configuration from: %q...", source)))
if err := c.copySource(path, source, pwd); err != nil {
c.Ui.Error(fmt.Sprintf(
"Error copying source: %s", err))
return 1
}
header = true
}
// If our directory is empty, then we're done. We can't get or setup
// the backend with an empty directory.
if empty, err := config.IsEmptyDir(path); err != nil {
@ -302,27 +276,9 @@ func (c *InitCommand) getProviders(path string, state *terraform.State) error {
return nil
}
func (c *InitCommand) copySource(dst, src, pwd string) error {
// Verify the directory is empty
if empty, err := config.IsEmptyDir(dst); err != nil {
return fmt.Errorf("Error checking on destination path: %s", err)
} else if !empty {
return fmt.Errorf(strings.TrimSpace(errInitCopyNotEmpty))
}
// Detect
source, err := getter.Detect(src, pwd, getter.Detectors)
if err != nil {
return fmt.Errorf("Error with module source: %s", err)
}
// Get it!
return module.GetCopy(dst, source)
}
func (c *InitCommand) Help() string {
helpText := `
Usage: terraform init [options] [SOURCE] [PATH]
Usage: terraform init [options] [DIR]
Initialize a new or existing Terraform working directory by creating
initial files, loading any remote state, downloading modules, etc.
@ -340,14 +296,6 @@ Usage: terraform init [options] [SOURCE] [PATH]
If no arguments are given, the configuration in this working directory
is initialized.
If one or two arguments are given, the first is a SOURCE of a module to
download to the second argument PATH. After downloading the module to PATH,
the configuration will be initialized as if this command were called pointing
only to that PATH. PATH must be empty of any Terraform files. Any
conflicting non-Terraform files will be overwritten. The module download
is a copy. If you're downloading a module from Git, it will not preserve
Git history.
Options:
-backend=true Configure the backend for this configuration.

View File

@ -14,66 +14,6 @@ import (
"github.com/mitchellh/cli"
)
func TestInit(t *testing.T) {
dir := tempDir(t)
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
testFixturePath("init"),
dir,
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
if _, err := os.Stat(filepath.Join(dir, "hello.tf")); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestInit_cwd(t *testing.T) {
dir := tempDir(t)
if err := os.MkdirAll(dir, 0755); err != nil {
t.Fatalf("err: %s", err)
}
// Change to the temporary directory
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("err: %s", err)
}
if err := os.Chdir(dir); err != nil {
t.Fatalf("err: %s", err)
}
defer os.Chdir(cwd)
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
testFixturePath("init"),
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
if _, err := os.Stat("hello.tf"); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestInit_empty(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
@ -113,48 +53,6 @@ func TestInit_multipleArgs(t *testing.T) {
}
}
// https://github.com/hashicorp/terraform/issues/518
func TestInit_dstInSrc(t *testing.T) {
dir := tempDir(t)
if err := os.MkdirAll(dir, 0755); err != nil {
t.Fatalf("err: %s", err)
}
// Change to the temporary directory
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("err: %s", err)
}
if err := os.Chdir(dir); err != nil {
t.Fatalf("err: %s", err)
}
defer os.Chdir(cwd)
if _, err := os.Create("issue518.tf"); err != nil {
t.Fatalf("err: %s", err)
}
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
".",
"foo",
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
if _, err := os.Stat(filepath.Join(dir, "foo", "issue518.tf")); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestInit_get(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
@ -182,39 +80,6 @@ func TestInit_get(t *testing.T) {
}
}
func TestInit_copyGet(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
os.MkdirAll(td, 0755)
defer os.RemoveAll(td)
defer testChdir(t, td)()
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
testFixturePath("init-get"),
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
// Check copy
if _, err := os.Stat("main.tf"); err != nil {
t.Fatalf("err: %s", err)
}
output := ui.OutputWriter.String()
if !strings.Contains(output, "Get: file://") {
t.Fatalf("doesn't look like get: %s", output)
}
}
func TestInit_backend(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
@ -380,13 +245,16 @@ func TestInit_backendConfigKV(t *testing.T) {
}
}
func TestInit_copyBackendDst(t *testing.T) {
func TestInit_targetSubdir(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
os.MkdirAll(td, 0755)
defer os.RemoveAll(td)
defer testChdir(t, td)()
// copy the source into a subdir
copy.CopyDir(testFixturePath("init-backend"), filepath.Join(td, "source"))
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
@ -396,15 +264,18 @@ func TestInit_copyBackendDst(t *testing.T) {
}
args := []string{
testFixturePath("init-backend"),
"dst",
"source",
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
if _, err := os.Stat(filepath.Join(
"dst", DefaultDataDir, DefaultStateFilename)); err != nil {
if _, err := os.Stat(filepath.Join(td, "source", DefaultDataDir, DefaultStateFilename)); err != nil {
t.Fatalf("err: %s", err)
}
// a data directory should not have been added to out working dir
if _, err := os.Stat(filepath.Join(td, DefaultDataDir)); !os.IsNotExist(err) {
t.Fatalf("err: %s", err)
}
}
@ -700,149 +571,3 @@ func TestInit_providerLockFile(t *testing.T) {
t.Errorf("wrong provider lock file contents\ngot: %s\nwant: %s", buf, wantLockFile)
}
}
/*
func TestInit_remoteState(t *testing.T) {
tmp, cwd := testCwd(t)
defer testFixCwd(t, tmp, cwd)
s := terraform.NewState()
conf, srv := testRemoteState(t, s, 200)
defer srv.Close()
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
"-backend", "HTTP",
"-backend-config", "address=" + conf.Config["address"],
testFixturePath("init"),
tmp,
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
if _, err := os.Stat(filepath.Join(tmp, "hello.tf")); err != nil {
t.Fatalf("err: %s", err)
}
if _, err := os.Stat(filepath.Join(tmp, DefaultDataDir, DefaultStateFilename)); err != nil {
t.Fatalf("missing state: %s", err)
}
}
func TestInit_remoteStateSubdir(t *testing.T) {
tmp, cwd := testCwd(t)
defer testFixCwd(t, tmp, cwd)
subdir := filepath.Join(tmp, "subdir")
s := terraform.NewState()
conf, srv := testRemoteState(t, s, 200)
defer srv.Close()
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
"-backend", "http",
"-backend-config", "address=" + conf.Config["address"],
testFixturePath("init"),
subdir,
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
if _, err := os.Stat(filepath.Join(subdir, "hello.tf")); err != nil {
t.Fatalf("err: %s", err)
}
if _, err := os.Stat(filepath.Join(subdir, DefaultDataDir, DefaultStateFilename)); err != nil {
t.Fatalf("missing state: %s", err)
}
}
func TestInit_remoteStateWithLocal(t *testing.T) {
tmp, cwd := testCwd(t)
defer testFixCwd(t, tmp, cwd)
statePath := filepath.Join(tmp, DefaultStateFilename)
// Write some state
f, err := os.Create(statePath)
if err != nil {
t.Fatalf("err: %s", err)
}
err = terraform.WriteState(testState(), f)
f.Close()
if err != nil {
t.Fatalf("err: %s", err)
}
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
"-backend", "http",
"-backend-config", "address=http://google.com",
testFixturePath("init"),
}
if code := c.Run(args); code == 0 {
t.Fatalf("should have failed: \n%s", ui.OutputWriter.String())
}
}
func TestInit_remoteStateWithRemote(t *testing.T) {
tmp, cwd := testCwd(t)
defer testFixCwd(t, tmp, cwd)
statePath := filepath.Join(tmp, DefaultDataDir, DefaultStateFilename)
if err := os.MkdirAll(filepath.Dir(statePath), 0755); err != nil {
t.Fatalf("err: %s", err)
}
// Write some state
f, err := os.Create(statePath)
if err != nil {
t.Fatalf("err: %s", err)
}
err = terraform.WriteState(testState(), f)
f.Close()
if err != nil {
t.Fatalf("err: %s", err)
}
ui := new(cli.MockUi)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
args := []string{
"-backend", "http",
"-backend-config", "address=http://google.com",
testFixturePath("init"),
}
if code := c.Run(args); code == 0 {
t.Fatalf("should have failed: \n%s", ui.OutputWriter.String())
}
}
*/