command/apply: allow `terraform apply SOURCE` as shortcut for init

This commit is contained in:
Mitchell Hashimoto 2014-09-29 15:55:28 -07:00
parent a8c730d7a4
commit 3572b8ff2f
2 changed files with 121 additions and 5 deletions

View File

@ -8,6 +8,7 @@ import (
"sort"
"strings"
"github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/terraform"
)
@ -35,6 +36,12 @@ func (c *ApplyCommand) Run(args []string) int {
return 1
}
pwd, err := os.Getwd()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
return 1
}
var configPath string
args = cmdFlags.Args()
if len(args) > 1 {
@ -44,11 +51,7 @@ func (c *ApplyCommand) Run(args []string) int {
} else if len(args) == 1 {
configPath = args[0]
} else {
var err error
configPath, err = os.Getwd()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
}
configPath = pwd
}
// Prepare the extra hooks to count resources
@ -67,6 +70,24 @@ func (c *ApplyCommand) Run(args []string) int {
backupPath = stateOutPath + DefaultBackupExtention
}
// Do a detect to determine if we need to do an init + apply.
if detected, err := module.Detect(configPath, pwd); err != nil {
c.Ui.Error(fmt.Sprintf(
"Invalid path: %s", err))
return 1
} else if !strings.HasPrefix(detected, "file") {
// If this isn't a file URL then we're doing an init +
// apply.
var init InitCommand
init.Meta = c.Meta
if code := init.Run([]string{detected}); code != 0 {
return code
}
// Change the config path to be the cwd
configPath = pwd
}
// Build the context based on the arguments given
ctx, planned, err := c.Context(contextOpts{
Path: configPath,

View File

@ -3,6 +3,9 @@ package command
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"reflect"
@ -196,6 +199,73 @@ 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{
ContextOpts: testCtxConfig(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_noArgs(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
@ -942,6 +1012,31 @@ func TestApply_disableBackup(t *testing.T) {
}
}
func testHttpServer(t *testing.T) net.Listener {
ln, err := net.Listen("tcp", ":0")
if err != nil {
t.Fatalf("err: %s", err)
}
mux := http.NewServeMux()
mux.HandleFunc("/header", testHttpHandlerHeader)
var server http.Server
server.Handler = mux
go server.Serve(ln)
return ln
}
func testHttpHandlerHeader(w http.ResponseWriter, r *http.Request) {
var url url.URL
url.Scheme = "file"
url.Path = testFixturePath("init")
w.Header().Add("X-Terraform-Get", url.String())
w.WriteHeader(200)
}
const applyVarFile = `
foo = "bar"
`