Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding wildcard interpolation #6351

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 12 additions & 3 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Makefile
Expand Up @@ -20,10 +20,11 @@ quickdev: generate
# target should be used.
core-dev: generate
go install github.com/hashicorp/terraform
go install -tags 'core' github.com/hashicorp/terraform

# Shorthand for quickly testing the core of Terraform (i.e. "not providers")
core-test: generate
@echo "Testing core packages..." && go test $(shell go list ./... | grep -v -E 'builtin|vendor')
@echo "Testing core packages..." && go test -tags 'core' $(shell go list ./... | grep -v -E 'builtin|vendor')

# Shorthand for building and installing just one plugin for local testing.
# Run as (for example): make plugin-dev PLUGIN=provider-aws
Expand Down Expand Up @@ -77,6 +78,7 @@ generate:
go get -u golang.org/x/tools/cmd/stringer; \
fi
go generate $$(go list ./... | grep -v /vendor/)
@go fmt command/internal_plugin_list.go > /dev/null

fmt:
gofmt -w .
Expand Down
2 changes: 1 addition & 1 deletion builtin/providers/terraform/resource_state.go
Expand Up @@ -60,7 +60,7 @@ func resourceRemoteStateRead(d *schema.ResourceData, meta interface{}) error {
return err
}

var outputs map[string]string
var outputs map[string]interface{}
if !state.State().Empty() {
outputs = state.State().RootModule().Outputs
}
Expand Down
8 changes: 7 additions & 1 deletion builtin/providers/tls/resource_cert_request_test.go
Expand Up @@ -50,7 +50,13 @@ EOT
}
`, testPrivateKey),
Check: func(s *terraform.State) error {
got := s.RootModule().Outputs["key_pem"]
gotUntyped := s.RootModule().Outputs["key_pem"]

got, ok := gotUntyped.(string)
if !ok {
return fmt.Errorf("output for \"key_pem\" is not a string")
}

if !strings.HasPrefix(got, "-----BEGIN CERTIFICATE REQUEST----") {
return fmt.Errorf("key is missing CSR PEM preamble")
}
Expand Down
6 changes: 5 additions & 1 deletion builtin/providers/tls/resource_locally_signed_cert_test.go
Expand Up @@ -47,7 +47,11 @@ EOT
}
`, testCertRequest, testCACert, testCAPrivateKey),
Check: func(s *terraform.State) error {
got := s.RootModule().Outputs["cert_pem"]
gotUntyped := s.RootModule().Outputs["cert_pem"]
got, ok := gotUntyped.(string)
if !ok {
return fmt.Errorf("output for \"cert_pem\" is not a string")
}
if !strings.HasPrefix(got, "-----BEGIN CERTIFICATE----") {
return fmt.Errorf("key is missing cert PEM preamble")
}
Expand Down
57 changes: 48 additions & 9 deletions builtin/providers/tls/resource_private_key_test.go
Expand Up @@ -29,20 +29,33 @@ func TestPrivateKeyRSA(t *testing.T) {
}
`,
Check: func(s *terraform.State) error {
gotPrivate := s.RootModule().Outputs["private_key_pem"]
gotPrivateUntyped := s.RootModule().Outputs["private_key_pem"]
gotPrivate, ok := gotPrivateUntyped.(string)
if !ok {
return fmt.Errorf("output for \"private_key_pem\" is not a string")
}

if !strings.HasPrefix(gotPrivate, "-----BEGIN RSA PRIVATE KEY----") {
return fmt.Errorf("private key is missing RSA key PEM preamble")
}
if len(gotPrivate) > 1700 {
return fmt.Errorf("private key PEM looks too long for a 2048-bit key (got %v characters)", len(gotPrivate))
}

gotPublic := s.RootModule().Outputs["public_key_pem"]
gotPublicUntyped := s.RootModule().Outputs["public_key_pem"]
gotPublic, ok := gotPublicUntyped.(string)
if !ok {
return fmt.Errorf("output for \"public_key_pem\" is not a string")
}
if !strings.HasPrefix(gotPublic, "-----BEGIN PUBLIC KEY----") {
return fmt.Errorf("public key is missing public key PEM preamble")
}

gotPublicSSH := s.RootModule().Outputs["public_key_openssh"]
gotPublicSSHUntyped := s.RootModule().Outputs["public_key_openssh"]
gotPublicSSH, ok := gotPublicSSHUntyped.(string)
if !ok {
return fmt.Errorf("output for \"public_key_openssh\" is not a string")
}
if !strings.HasPrefix(gotPublicSSH, "ssh-rsa ") {
return fmt.Errorf("SSH public key is missing ssh-rsa prefix")
}
Expand All @@ -61,7 +74,11 @@ func TestPrivateKeyRSA(t *testing.T) {
}
`,
Check: func(s *terraform.State) error {
got := s.RootModule().Outputs["key_pem"]
gotUntyped := s.RootModule().Outputs["key_pem"]
got, ok := gotUntyped.(string)
if !ok {
return fmt.Errorf("output for \"key_pem\" is not a string")
}
if !strings.HasPrefix(got, "-----BEGIN RSA PRIVATE KEY----") {
return fmt.Errorf("key is missing RSA key PEM preamble")
}
Expand Down Expand Up @@ -95,12 +112,22 @@ func TestPrivateKeyECDSA(t *testing.T) {
}
`,
Check: func(s *terraform.State) error {
gotPrivate := s.RootModule().Outputs["private_key_pem"]
gotPrivateUntyped := s.RootModule().Outputs["private_key_pem"]
gotPrivate, ok := gotPrivateUntyped.(string)
if !ok {
return fmt.Errorf("output for \"private_key_pem\" is not a string")
}

if !strings.HasPrefix(gotPrivate, "-----BEGIN EC PRIVATE KEY----") {
return fmt.Errorf("Private key is missing EC key PEM preamble")
}

gotPublic := s.RootModule().Outputs["public_key_pem"]
gotPublicUntyped := s.RootModule().Outputs["public_key_pem"]
gotPublic, ok := gotPublicUntyped.(string)
if !ok {
return fmt.Errorf("output for \"public_key_pem\" is not a string")
}

if !strings.HasPrefix(gotPublic, "-----BEGIN PUBLIC KEY----") {
return fmt.Errorf("public key is missing public key PEM preamble")
}
Expand Down Expand Up @@ -130,17 +157,29 @@ func TestPrivateKeyECDSA(t *testing.T) {
}
`,
Check: func(s *terraform.State) error {
gotPrivate := s.RootModule().Outputs["private_key_pem"]
gotPrivateUntyped := s.RootModule().Outputs["private_key_pem"]
gotPrivate, ok := gotPrivateUntyped.(string)
if !ok {
return fmt.Errorf("output for \"private_key_pem\" is not a string")
}
if !strings.HasPrefix(gotPrivate, "-----BEGIN EC PRIVATE KEY----") {
return fmt.Errorf("Private key is missing EC key PEM preamble")
}

gotPublic := s.RootModule().Outputs["public_key_pem"]
gotPublicUntyped := s.RootModule().Outputs["public_key_pem"]
gotPublic, ok := gotPublicUntyped.(string)
if !ok {
return fmt.Errorf("output for \"public_key_pem\" is not a string")
}
if !strings.HasPrefix(gotPublic, "-----BEGIN PUBLIC KEY----") {
return fmt.Errorf("public key is missing public key PEM preamble")
}

gotPublicSSH := s.RootModule().Outputs["public_key_openssh"]
gotPublicSSHUntyped := s.RootModule().Outputs["public_key_openssh"]
gotPublicSSH, ok := gotPublicSSHUntyped.(string)
if !ok {
return fmt.Errorf("output for \"public_key_openssh\" is not a string")
}
if !strings.HasPrefix(gotPublicSSH, "ecdsa-sha2-nistp256 ") {
return fmt.Errorf("P256 SSH public key is missing ecdsa prefix")
}
Expand Down
7 changes: 6 additions & 1 deletion builtin/providers/tls/resource_self_signed_cert_test.go
Expand Up @@ -60,7 +60,12 @@ EOT
}
`, testPrivateKey),
Check: func(s *terraform.State) error {
got := s.RootModule().Outputs["key_pem"]
gotUntyped := s.RootModule().Outputs["key_pem"]
got, ok := gotUntyped.(string)
if !ok {
return fmt.Errorf("output for \"public_key_openssh\" is not a string")
}

if !strings.HasPrefix(got, "-----BEGIN CERTIFICATE----") {
return fmt.Errorf("key is missing cert PEM preamble")
}
Expand Down
37 changes: 18 additions & 19 deletions command/apply.go
Expand Up @@ -251,7 +251,8 @@ func (c *ApplyCommand) Run(args []string) int {

if !c.Destroy {
if outputs := outputsAsString(state); outputs != "" {
c.Ui.Output(c.Colorize().Color(outputs))
colorOutputs := fmt.Sprintf("[reset][bold][green]\nOutputs:\n\n%s", outputs)
c.Ui.Output(c.Colorize().Color(colorOutputs))
}
}

Expand Down Expand Up @@ -384,27 +385,25 @@ func outputsAsString(state *terraform.State) string {
outputs := state.RootModule().Outputs
outputBuf := new(bytes.Buffer)
if len(outputs) > 0 {
outputBuf.WriteString("[reset][bold][green]\nOutputs:\n\n")

// Output the outputs in alphabetical order
keyLen := 0
keys := make([]string, 0, len(outputs))
for key, _ := range outputs {
keys = append(keys, key)
if len(key) > keyLen {
keyLen = len(key)
}
ks := make([]string, 0, len(outputs))
for k, _ := range outputs {
ks = append(ks, k)
}
sort.Strings(keys)
sort.Strings(ks)

for _, k := range keys {
for _, k := range ks {
v := outputs[k]

outputBuf.WriteString(fmt.Sprintf(
" %s%s = %s\n",
k,
strings.Repeat(" ", keyLen-len(k)),
v))
switch typedV := v.(type) {
case string:
outputBuf.WriteString(fmt.Sprintf("%s = %s", k, typedV))
outputBuf.WriteString("\n")
case []interface{}:
outputBuf.WriteString(formatListOutput("", k, typedV))
outputBuf.WriteString("\n")
case map[string]interface{}:
outputBuf.WriteString(formatMapOutput("", k, typedV))
outputBuf.WriteString("\n")
}
}
}

Expand Down
64 changes: 64 additions & 0 deletions command/apply_test.go
Expand Up @@ -886,6 +886,70 @@ func TestApply_stateNoExist(t *testing.T) {
}
}

func TestApply_stateFuture(t *testing.T) {
originalState := testState()
originalState.TFVersion = "99.99.99"
statePath := testStateFile(t, originalState)

p := testProvider()
ui := new(cli.MockUi)
c := &ApplyCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
testFixturePath("apply"),
}
if code := c.Run(args); code == 0 {
t.Fatal("should fail")
}

f, err := os.Open(statePath)
if err != nil {
t.Fatalf("err: %s", err)
}

newState, err := terraform.ReadState(f)
f.Close()
if err != nil {
t.Fatalf("err: %s", err)
}

if !newState.Equal(originalState) {
t.Fatalf("bad: %#v", newState)
}
if newState.TFVersion != originalState.TFVersion {
t.Fatalf("bad: %#v", newState)
}
}

func TestApply_statePast(t *testing.T) {
originalState := testState()
originalState.TFVersion = "0.1.0"
statePath := testStateFile(t, originalState)

p := testProvider()
ui := new(cli.MockUi)
c := &ApplyCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}

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

func TestApply_vars(t *testing.T) {
statePath := testTempFile(t)

Expand Down