diff --git a/builtin/providers/aws/data_source_aws_elasticache_cluster.go b/builtin/providers/aws/data_source_aws_elasticache_cluster.go new file mode 100644 index 0000000000..eaa539d3a5 --- /dev/null +++ b/builtin/providers/aws/data_source_aws_elasticache_cluster.go @@ -0,0 +1,236 @@ +package aws + +import ( + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/elasticache" + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceAwsElastiCacheCluster() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsElastiCacheClusterRead, + + Schema: map[string]*schema.Schema{ + "cluster_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: func(v interface{}) string { + value := v.(string) + return strings.ToLower(value) + }, + }, + + "node_type": { + Type: schema.TypeString, + Computed: true, + }, + + "num_cache_nodes": { + Type: schema.TypeInt, + Computed: true, + }, + + "subnet_group_name": { + Type: schema.TypeString, + Computed: true, + }, + + "engine": { + Type: schema.TypeString, + Computed: true, + }, + + "engine_version": { + Type: schema.TypeString, + Computed: true, + }, + + "parameter_group_name": { + Type: schema.TypeString, + Computed: true, + }, + + "replication_group_id": { + Type: schema.TypeString, + Computed: true, + }, + + "security_group_names": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "security_group_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "maintenance_window": { + Type: schema.TypeString, + Computed: true, + }, + + "snapshot_window": { + Type: schema.TypeString, + Computed: true, + }, + + "snapshot_retention_limit": { + Type: schema.TypeInt, + Computed: true, + }, + + "availability_zone": { + Type: schema.TypeString, + Computed: true, + }, + + "notification_topic_arn": { + Type: schema.TypeString, + Computed: true, + }, + + "port": { + Type: schema.TypeInt, + Computed: true, + }, + + "configuration_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "cluster_address": { + Type: schema.TypeString, + Computed: true, + }, + + "arn": { + Type: schema.TypeString, + Computed: true, + }, + + "cache_nodes": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "address": { + Type: schema.TypeString, + Computed: true, + }, + "port": { + Type: schema.TypeInt, + Computed: true, + }, + "availability_zone": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "tags": tagsSchemaComputed(), + }, + } +} + +func dataSourceAwsElastiCacheClusterRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).elasticacheconn + + req := &elasticache.DescribeCacheClustersInput{ + CacheClusterId: aws.String(d.Get("cluster_id").(string)), + ShowCacheNodeInfo: aws.Bool(true), + } + + resp, err := conn.DescribeCacheClusters(req) + if err != nil { + return err + } + + if len(resp.CacheClusters) < 1 { + return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.") + } + if len(resp.CacheClusters) > 1 { + return fmt.Errorf("Your query returned more than one result. Please try a more specific search criteria.") + } + + cluster := resp.CacheClusters[0] + + d.SetId(*cluster.CacheClusterId) + + d.Set("cluster_id", cluster.CacheClusterId) + d.Set("node_type", cluster.CacheNodeType) + d.Set("num_cache_nodes", cluster.NumCacheNodes) + d.Set("subnet_group_name", cluster.CacheSubnetGroupName) + d.Set("engine", cluster.Engine) + d.Set("engine_version", cluster.EngineVersion) + d.Set("security_group_names", flattenElastiCacheSecurityGroupNames(cluster.CacheSecurityGroups)) + d.Set("security_group_ids", flattenElastiCacheSecurityGroupIds(cluster.SecurityGroups)) + + if cluster.CacheParameterGroup != nil { + d.Set("parameter_group_name", cluster.CacheParameterGroup.CacheParameterGroupName) + } + + if cluster.ReplicationGroupId != nil { + d.Set("replication_group_id", cluster.ReplicationGroupId) + } + + d.Set("maintenance_window", cluster.PreferredMaintenanceWindow) + d.Set("snapshot_window", cluster.SnapshotWindow) + d.Set("snapshot_retention_limit", cluster.SnapshotRetentionLimit) + d.Set("availability_zone", cluster.PreferredAvailabilityZone) + + if cluster.NotificationConfiguration != nil { + if *cluster.NotificationConfiguration.TopicStatus == "active" { + d.Set("notification_topic_arn", cluster.NotificationConfiguration.TopicArn) + } + } + + if cluster.ConfigurationEndpoint != nil { + d.Set("port", cluster.ConfigurationEndpoint.Port) + d.Set("configuration_endpoint", aws.String(fmt.Sprintf("%s:%d", *cluster.ConfigurationEndpoint.Address, *cluster.ConfigurationEndpoint.Port))) + d.Set("cluster_address", aws.String(fmt.Sprintf("%s", *cluster.ConfigurationEndpoint.Address))) + } + + if err := setCacheNodeData(d, cluster); err != nil { + return err + } + + arn, err := buildECARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region) + if err != nil { + log.Printf("[DEBUG] Error building ARN for ElastiCache Cluster %s", *cluster.CacheClusterId) + } + d.Set("arn", arn) + + tagResp, err := conn.ListTagsForResource(&elasticache.ListTagsForResourceInput{ + ResourceName: aws.String(arn), + }) + + if err != nil { + log.Printf("[DEBUG] Error retrieving tags for ARN: %s", arn) + } + + var et []*elasticache.Tag + if len(tagResp.TagList) > 0 { + et = tagResp.TagList + } + d.Set("tags", tagsToMapEC(et)) + + return nil + +} diff --git a/builtin/providers/aws/data_source_aws_elasticache_cluster_test.go b/builtin/providers/aws/data_source_aws_elasticache_cluster_test.go new file mode 100644 index 0000000000..57791cf05c --- /dev/null +++ b/builtin/providers/aws/data_source_aws_elasticache_cluster_test.go @@ -0,0 +1,72 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSDataElasticacheCluster_basic(t *testing.T) { + rInt := acctest.RandInt() + rString := acctest.RandString(10) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAWSElastiCacheClusterConfigWithDataSource(rString, rInt), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_elasticache_cluster.bar", "engine", "memcached"), + resource.TestCheckResourceAttr("data.aws_elasticache_cluster.bar", "node_type", "cache.m1.small"), + resource.TestCheckResourceAttr("data.aws_elasticache_cluster.bar", "port", "11211"), + resource.TestCheckResourceAttr("data.aws_elasticache_cluster.bar", "num_cache_nodes", "1"), + resource.TestCheckResourceAttrSet("data.aws_elasticache_cluster.bar", "configuration_endpoint"), + resource.TestCheckResourceAttrSet("data.aws_elasticache_cluster.bar", "cluster_address"), + resource.TestCheckResourceAttrSet("data.aws_elasticache_cluster.bar", "availability_zone"), + ), + }, + }, + }) +} + +func testAccAWSElastiCacheClusterConfigWithDataSource(rString string, rInt int) string { + return fmt.Sprintf(` +provider "aws" { + region = "us-east-1" +} + +resource "aws_security_group" "bar" { + name = "tf-test-security-group-%d" + description = "tf-test-security-group-descr" + ingress { + from_port = -1 + to_port = -1 + protocol = "icmp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_elasticache_security_group" "bar" { + name = "tf-test-security-group-%d" + description = "tf-test-security-group-descr" + security_group_names = ["${aws_security_group.bar.name}"] +} + +resource "aws_elasticache_cluster" "bar" { + cluster_id = "tf-%s" + engine = "memcached" + node_type = "cache.m1.small" + num_cache_nodes = 1 + port = 11211 + parameter_group_name = "default.memcached1.4" + security_group_names = ["${aws_elasticache_security_group.bar.name}"] +} + +data "aws_elasticache_cluster" "bar" { + cluster_id = "${aws_elasticache_cluster.bar.cluster_id}" +} + +`, rInt, rInt, rString) +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 94ab3429aa..d1426a3f04 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -181,6 +181,7 @@ func Provider() terraform.ResourceProvider { "aws_ecs_task_definition": dataSourceAwsEcsTaskDefinition(), "aws_efs_file_system": dataSourceAwsEfsFileSystem(), "aws_eip": dataSourceAwsEip(), + "aws_elasticache_cluster": dataSourceAwsElastiCacheCluster(), "aws_elb_hosted_zone_id": dataSourceAwsElbHostedZoneId(), "aws_elb_service_account": dataSourceAwsElbServiceAccount(), "aws_iam_account_alias": dataSourceAwsIamAccountAlias(), diff --git a/builtin/providers/aws/resource_aws_elasticache_cluster_test.go b/builtin/providers/aws/resource_aws_elasticache_cluster_test.go index 479819ea8d..4c4b89b150 100644 --- a/builtin/providers/aws/resource_aws_elasticache_cluster_test.go +++ b/builtin/providers/aws/resource_aws_elasticache_cluster_test.go @@ -20,7 +20,7 @@ func TestAccAWSElasticacheCluster_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSElasticacheClusterDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSElasticacheClusterConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), @@ -47,7 +47,7 @@ func TestAccAWSElasticacheCluster_snapshotsWithUpdates(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSElasticacheClusterDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: preConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), @@ -59,7 +59,7 @@ func TestAccAWSElasticacheCluster_snapshotsWithUpdates(t *testing.T) { ), }, - resource.TestStep{ + { Config: postConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), @@ -86,7 +86,7 @@ func TestAccAWSElasticacheCluster_decreasingCacheNodes(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSElasticacheClusterDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: preConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), @@ -96,7 +96,7 @@ func TestAccAWSElasticacheCluster_decreasingCacheNodes(t *testing.T) { ), }, - resource.TestStep{ + { Config: postConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), @@ -117,7 +117,7 @@ func TestAccAWSElasticacheCluster_vpc(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSElasticacheClusterDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSElasticacheClusterInVPCConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar", &csg), @@ -139,7 +139,7 @@ func TestAccAWSElasticacheCluster_multiAZInVpc(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSElasticacheClusterDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSElasticacheClusterMultiAZInVPCConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar", &csg), diff --git a/website/source/docs/providers/aws/d/elasticache_cluster.html.markdown b/website/source/docs/providers/aws/d/elasticache_cluster.html.markdown new file mode 100644 index 0000000000..576f2102fa --- /dev/null +++ b/website/source/docs/providers/aws/d/elasticache_cluster.html.markdown @@ -0,0 +1,55 @@ +--- +layout: "aws" +page_title: "AWS: aws_elasticache_cluster" +sidebar_current: "docs-aws-datasource-elasticache-cluster" +description: |- + Get information on an ElastiCache Cluster resource. +--- + +# aws_elasticache_cluster + +Use this data source to get information about an Elasticache Cluster + +## Example Usage + +```hcl +data "aws_elasticache_cluster" "my_cluster" { + cluster_id = "my-cluster-id" +} + +## Argument Reference + +The following arguments are supported: + +* `cluster_id` – (Required) Group identifier. + + +## Attributes Reference + +The following attributes are exported: + +* `node_type` – The cluster node type. +* `num_cache_nodes` – The number of cache nodes that the cache cluster has. +* `engine` – Name of the cache engine. +* `engine_version` – Version number of the cache engine. +* `subnet_group_name` – Name of the subnet group associated to the cache cluster. +* `security_group_names` – List of security group names associated with this cache cluster. +* `security_group_ids` – List VPC security groups associated with the cache cluster. +* `parameter_group_name` – Name of the parameter group associated with this cache cluster. +* `replication_group_id` - The replication group to which this cache cluster belongs. +* `maintenance_window` – Specifies the weekly time range for when maintenance +on the cache cluster is performed. +* `snapshot_window` - The daily time range (in UTC) during which ElastiCache will +begin taking a daily snapshot of the cache cluster. +* `snapshot_retention_limit` - The number of days for which ElastiCache will +retain automatic cache cluster snapshots before deleting them. +* `availability_zone` - The Availability Zone for the cache cluster. +* `notification_topic_arn` – An Amazon Resource Name (ARN) of an +SNS topic that ElastiCache notifications get sent to. +* `port` – The port number on which each of the cache nodes will +accept connections. +* `configuration_endpoint` - The configuration endpoint to allow host discovery. +* `cluster_address` - The DNS name of the cache cluster without the port appended. +* `cache_nodes` - List of node objects including `id`, `address`, `port` and `availability_zone`. + Referenceable e.g. as `${data.aws_elasticache_cluster.bar.cache_nodes.0.address}` +* `tags` - The tags assigned to the resource diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index e7e04c6042..837273a4d7 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -80,6 +80,9 @@