Merge pull request #8640 from TimeIncOSS/f-aws-cloudformation-data-source

provider/aws: Add cloudformation_stack data source
This commit is contained in:
James Nugent 2016-09-03 14:16:46 -07:00 committed by GitHub
commit 54784864fc
6 changed files with 248 additions and 0 deletions

View File

@ -0,0 +1,109 @@
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSourceAwsCloudFormationStack() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsCloudFormationStackRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"template_body": {
Type: schema.TypeString,
Computed: true,
StateFunc: normalizeJson,
},
"capabilities": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"disable_rollback": {
Type: schema.TypeBool,
Computed: true,
},
"notification_arns": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"parameters": {
Type: schema.TypeMap,
Computed: true,
},
"outputs": {
Type: schema.TypeMap,
Computed: true,
},
"timeout_in_minutes": {
Type: schema.TypeInt,
Computed: true,
},
"tags": {
Type: schema.TypeMap,
Computed: true,
},
},
}
}
func dataSourceAwsCloudFormationStackRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cfconn
name := d.Get("name").(string)
input := cloudformation.DescribeStacksInput{
StackName: aws.String(name),
}
out, err := conn.DescribeStacks(&input)
if err != nil {
return fmt.Errorf("Failed describing CloudFormation stack (%s): %s", name, err)
}
if l := len(out.Stacks); l != 1 {
return fmt.Errorf("Expected 1 CloudFormation stack (%s), found %d", name, l)
}
stack := out.Stacks[0]
d.SetId(*stack.StackId)
d.Set("description", stack.Description)
d.Set("disable_rollback", stack.DisableRollback)
d.Set("timeout_in_minutes", stack.TimeoutInMinutes)
if len(stack.NotificationARNs) > 0 {
d.Set("notification_arns", schema.NewSet(schema.HashString, flattenStringList(stack.NotificationARNs)))
}
d.Set("parameters", flattenAllCloudFormationParameters(stack.Parameters))
d.Set("tags", flattenCloudFormationTags(stack.Tags))
d.Set("outputs", flattenCloudFormationOutputs(stack.Outputs))
if len(stack.Capabilities) > 0 {
d.Set("capabilities", schema.NewSet(schema.HashString, flattenStringList(stack.Capabilities)))
}
tInput := cloudformation.GetTemplateInput{
StackName: aws.String(name),
}
tOut, err := conn.GetTemplate(&tInput)
if err != nil {
return err
}
d.Set("template_body", normalizeJson(*tOut.TemplateBody))
return nil
}

View File

@ -0,0 +1,78 @@
package aws
import (
"regexp"
"testing"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccAWSCloudFormationStack_dataSource_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckAwsCloudFormationStackDataSourceConfig_basic,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "outputs.%", "1"),
resource.TestMatchResourceAttr("data.aws_cloudformation_stack.network", "outputs.VPCId",
regexp.MustCompile("^vpc-[a-z0-9]{8}$")),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "capabilities.#", "0"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "disable_rollback", "false"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "notification_arns.#", "0"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "parameters.%", "1"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "parameters.CIDR", "10.10.10.0/24"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "timeout_in_minutes", "6"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "tags.%", "2"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "tags.Name", "Form the Cloud"),
resource.TestCheckResourceAttr("data.aws_cloudformation_stack.network", "tags.Second", "meh"),
),
},
},
})
}
const testAccCheckAwsCloudFormationStackDataSourceConfig_basic = `
resource "aws_cloudformation_stack" "cfs" {
name = "tf-acc-ds-networking-stack"
parameters {
CIDR = "10.10.10.0/24"
}
timeout_in_minutes = 6
template_body = <<STACK
{
"Parameters": {
"CIDR": {
"Type": "String"
}
},
"Resources" : {
"myvpc": {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : { "Ref" : "CIDR" },
"Tags" : [
{"Key": "Name", "Value": "Primary_CF_VPC"}
]
}
}
},
"Outputs" : {
"VPCId" : {
"Value" : { "Ref" : "myvpc" },
"Description" : "VPC ID"
}
}
}
STACK
tags {
Name = "Form the Cloud"
Second = "meh"
}
}
data "aws_cloudformation_stack" "network" {
name = "${aws_cloudformation_stack.cfs.name}"
}
`

View File

@ -146,6 +146,7 @@ func Provider() terraform.ResourceProvider {
"aws_ami": dataSourceAwsAmi(), "aws_ami": dataSourceAwsAmi(),
"aws_availability_zones": dataSourceAwsAvailabilityZones(), "aws_availability_zones": dataSourceAwsAvailabilityZones(),
"aws_caller_identity": dataSourceAwsCallerIdentity(), "aws_caller_identity": dataSourceAwsCallerIdentity(),
"aws_cloudformation_stack": dataSourceAwsCloudFormationStack(),
"aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(), "aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(),
"aws_elb_service_account": dataSourceAwsElbServiceAccount(), "aws_elb_service_account": dataSourceAwsElbServiceAccount(),
"aws_iam_policy_document": dataSourceAwsIamPolicyDocument(), "aws_iam_policy_document": dataSourceAwsIamPolicyDocument(),

View File

@ -991,6 +991,14 @@ func flattenCloudFormationParameters(cfParams []*cloudformation.Parameter,
return params return params
} }
func flattenAllCloudFormationParameters(cfParams []*cloudformation.Parameter) map[string]interface{} {
params := make(map[string]interface{}, len(cfParams))
for _, p := range cfParams {
params[*p.ParameterKey] = *p.ParameterValue
}
return params
}
func expandCloudFormationTags(tags map[string]interface{}) []*cloudformation.Tag { func expandCloudFormationTags(tags map[string]interface{}) []*cloudformation.Tag {
var cfTags []*cloudformation.Tag var cfTags []*cloudformation.Tag
for k, v := range tags { for k, v := range tags {

View File

@ -0,0 +1,49 @@
---
layout: "aws"
page_title: "AWS: aws_cloudformation_stack"
sidebar_current: "docs-aws-datasource-cloudformation-stack"
description: |-
Provides metadata of a CloudFormation stack (e.g. outputs)
---
# aws\_cloudformation\_stack
The CloudFormation Stack data source allows access to stack
outputs and other useful data including the template body.
## Example Usage
```
data "aws_cloudformation_stack" "network" {
name = "my-network-stack"
}
resource "aws_instance" "web" {
ami = "ami-abb07bcb"
instance_type = "t1.micro"
subnet_id = "${data.aws_cloudformation_stack.network.outputs["SubnetId"]}"
tags {
Name = "HelloWorld"
}
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name of the stack
## Attributes Reference
The following attributes are exported:
* `capabilities` - A list of capabilities
* `description` - Description of the stack
* `disable_rollback` - Whether the rollback of the stack is disabled when stack creation fails
* `notification_arns` - A list of SNS topic ARNs to publish stack related events
* `outputs` - A map of outputs from the stack.
* `parameters` - A map of parameters that specify input parameters for the stack.
* `tags` - A map of tags associated with this stack.
* `template_body` - Structure containing the template body.
* `timeout_in_minutes` - The amount of time that can pass before the stack status becomes `CREATE_FAILED`

View File

@ -23,6 +23,9 @@
<li<%= sidebar_current("docs-aws-datasource-caller-identity") %>> <li<%= sidebar_current("docs-aws-datasource-caller-identity") %>>
<a href="/docs/providers/aws/d/caller_identity.html">aws_caller_identity</a> <a href="/docs/providers/aws/d/caller_identity.html">aws_caller_identity</a>
</li> </li>
<li<%= sidebar_current("docs-aws-datasource-cloudformation-stack") %>>
<a href="/docs/providers/aws/d/cloudformation_stack.html">aws_cloudformation_stack</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-ecs-container-definition") %>> <li<%= sidebar_current("docs-aws-datasource-ecs-container-definition") %>>
<a href="/docs/providers/aws/d/ecs_container_definition.html">aws_ecs_container_definition</a> <a href="/docs/providers/aws/d/ecs_container_definition.html">aws_ecs_container_definition</a>
</li> </li>