From 84040750f6f22ba11ee6138657dd3278c9295d06 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 1 Oct 2020 15:49:59 -0400 Subject: [PATCH] New Data Source: aws_redshift_orderable_cluster Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/15435 Output from acceptance testing in AWS Commercial: ``` --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_NodeType (13.92s) --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_ClusterVersion (14.05s) --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_PreferredNodeTypes (14.05s) --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_ClusterType (14.19s) ``` Output from acceptance testing in AWS GovCloud (US): ``` --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_ClusterType (18.30s) --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_NodeType (18.32s) --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_ClusterVersion (18.42s) --- PASS: TestAccAWSRedshiftOrderableClusterDataSource_PreferredNodeTypes (18.43s) ``` --- ...a_source_aws_redshift_orderable_cluster.go | 132 ++++++++++++++++ ...rce_aws_redshift_orderable_cluster_test.go | 141 ++++++++++++++++++ aws/provider.go | 1 + .../redshift_orderable_cluster.html.markdown | 35 +++++ 4 files changed, 309 insertions(+) create mode 100644 aws/data_source_aws_redshift_orderable_cluster.go create mode 100644 aws/data_source_aws_redshift_orderable_cluster_test.go create mode 100644 website/docs/d/redshift_orderable_cluster.html.markdown diff --git a/aws/data_source_aws_redshift_orderable_cluster.go b/aws/data_source_aws_redshift_orderable_cluster.go new file mode 100644 index 00000000000..d0ef0d8f5d7 --- /dev/null +++ b/aws/data_source_aws_redshift_orderable_cluster.go @@ -0,0 +1,132 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/redshift" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceAwsRedshiftOrderableCluster() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsRedshiftOrderableClusterRead, + Schema: map[string]*schema.Schema{ + "availability_zones": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "cluster_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "cluster_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "node_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "preferred_node_types": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceAwsRedshiftOrderableClusterRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).redshiftconn + + input := &redshift.DescribeOrderableClusterOptionsInput{} + + if v, ok := d.GetOk("cluster_version"); ok { + input.ClusterVersion = aws.String(v.(string)) + } + + if v, ok := d.GetOk("node_type"); ok { + input.NodeType = aws.String(v.(string)) + } + + var orderableClusterOptions []*redshift.OrderableClusterOption + + err := conn.DescribeOrderableClusterOptionsPages(input, func(page *redshift.DescribeOrderableClusterOptionsOutput, lastPage bool) bool { + for _, orderableClusterOption := range page.OrderableClusterOptions { + if orderableClusterOption == nil { + continue + } + + if v, ok := d.GetOk("cluster_type"); ok { + if aws.StringValue(orderableClusterOption.ClusterType) != v.(string) { + continue + } + } + + orderableClusterOptions = append(orderableClusterOptions, orderableClusterOption) + } + return !lastPage + }) + + if err != nil { + return fmt.Errorf("error reading Redshift Orderable Cluster Options: %w", err) + } + + if len(orderableClusterOptions) == 0 { + return fmt.Errorf("no Redshift Orderable Cluster Options found matching criteria; try different search") + } + + var orderableClusterOption *redshift.OrderableClusterOption + preferredNodeTypes := d.Get("preferred_node_types").([]interface{}) + if len(preferredNodeTypes) > 0 { + for _, preferredNodeTypeRaw := range preferredNodeTypes { + preferredNodeType, ok := preferredNodeTypeRaw.(string) + + if !ok { + continue + } + + for _, option := range orderableClusterOptions { + if preferredNodeType == aws.StringValue(option.NodeType) { + orderableClusterOption = option + break + } + } + + if orderableClusterOption != nil { + break + } + } + } + + if orderableClusterOption == nil && len(orderableClusterOptions) > 1 { + return fmt.Errorf("multiple Redshift Orderable Cluster Options (%v) match the criteria; try a different search", orderableClusterOptions) + } + + if orderableClusterOption == nil && len(orderableClusterOptions) == 1 { + orderableClusterOption = orderableClusterOptions[0] + } + + if orderableClusterOption == nil { + return fmt.Errorf("no Redshift Orderable Cluster Options match the criteria; try a different search") + } + + d.SetId(aws.StringValue(orderableClusterOption.NodeType)) + + var availabilityZones []string + for _, az := range orderableClusterOption.AvailabilityZones { + availabilityZones = append(availabilityZones, aws.StringValue(az.Name)) + } + d.Set("availability_zones", availabilityZones) + + d.Set("cluster_type", orderableClusterOption.ClusterType) + d.Set("cluster_version", orderableClusterOption.ClusterVersion) + d.Set("node_type", orderableClusterOption.NodeType) + + return nil +} diff --git a/aws/data_source_aws_redshift_orderable_cluster_test.go b/aws/data_source_aws_redshift_orderable_cluster_test.go new file mode 100644 index 00000000000..48ba04454c0 --- /dev/null +++ b/aws/data_source_aws_redshift_orderable_cluster_test.go @@ -0,0 +1,141 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/redshift" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccAWSRedshiftOrderableClusterDataSource_ClusterType(t *testing.T) { + dataSourceName := "data.aws_redshift_orderable_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAWSRedshiftOrderableClusterPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAWSRedshiftOrderableClusterDataSourceConfig_ClusterType("multi-node"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "cluster_type", "multi-node"), + ), + }, + }, + }) +} + +func TestAccAWSRedshiftOrderableClusterDataSource_ClusterVersion(t *testing.T) { + dataSourceName := "data.aws_redshift_orderable_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAWSRedshiftOrderableClusterPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAWSRedshiftOrderableClusterDataSourceConfig_ClusterVersion("1.0"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "cluster_version", "1.0"), + ), + }, + }, + }) +} + +func TestAccAWSRedshiftOrderableClusterDataSource_NodeType(t *testing.T) { + dataSourceName := "data.aws_redshift_orderable_cluster.test" + nodeType := "dc2.8xlarge" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAWSRedshiftOrderableClusterPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAWSRedshiftOrderableClusterDataSourceConfig_NodeType(nodeType), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "node_type", nodeType), + ), + }, + }, + }) +} + +func TestAccAWSRedshiftOrderableClusterDataSource_PreferredNodeTypes(t *testing.T) { + dataSourceName := "data.aws_redshift_orderable_cluster.test" + preferredNodeType := "dc2.8xlarge" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAWSRedshiftOrderableClusterPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAWSRedshiftOrderableClusterDataSourceConfig_PreferredNodeTypes(preferredNodeType), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "node_type", preferredNodeType), + ), + }, + }, + }) +} + +func testAccAWSRedshiftOrderableClusterPreCheck(t *testing.T) { + conn := testAccProvider.Meta().(*AWSClient).redshiftconn + + input := &redshift.DescribeOrderableClusterOptionsInput{ + MaxRecords: aws.Int64(20), + } + + _, err := conn.DescribeOrderableClusterOptions(input) + + if testAccPreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccAWSRedshiftOrderableClusterDataSourceConfig_ClusterType(clusterType string) string { + return fmt.Sprintf(` +data "aws_redshift_orderable_cluster" "test" { + cluster_type = %[1]q + preferred_node_types = ["dc2.large", "ds2.xlarge"] +} +`, clusterType) +} + +func testAccAWSRedshiftOrderableClusterDataSourceConfig_ClusterVersion(clusterVersion string) string { + return fmt.Sprintf(` +data "aws_redshift_orderable_cluster" "test" { + cluster_version = %[1]q + preferred_node_types = ["dc2.8xlarge", "ds2.8xlarge"] +} +`, clusterVersion) +} + +func testAccAWSRedshiftOrderableClusterDataSourceConfig_NodeType(nodeType string) string { + return fmt.Sprintf(` +data "aws_redshift_orderable_cluster" "test" { + node_type = %[1]q + preferred_node_types = ["dc2.8xlarge", "ds2.8xlarge"] +} +`, nodeType) +} + +func testAccAWSRedshiftOrderableClusterDataSourceConfig_PreferredNodeTypes(preferredNodeType string) string { + return fmt.Sprintf(` +data "aws_redshift_orderable_cluster" "test" { + preferred_node_types = [ + "non-existent", + %[1]q, + "try-again", + ] +} +`, preferredNodeType) +} diff --git a/aws/provider.go b/aws/provider.go index 35985e977b6..d71984193be 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -310,6 +310,7 @@ func Provider() *schema.Provider { "aws_rds_engine_version": dataSourceAwsRdsEngineVersion(), "aws_rds_orderable_db_instance": dataSourceAwsRdsOrderableDbInstance(), "aws_redshift_cluster": dataSourceAwsRedshiftCluster(), + "aws_redshift_orderable_cluster": dataSourceAwsRedshiftOrderableCluster(), "aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(), "aws_region": dataSourceAwsRegion(), "aws_regions": dataSourceAwsRegions(), diff --git a/website/docs/d/redshift_orderable_cluster.html.markdown b/website/docs/d/redshift_orderable_cluster.html.markdown new file mode 100644 index 00000000000..b22dd82f8df --- /dev/null +++ b/website/docs/d/redshift_orderable_cluster.html.markdown @@ -0,0 +1,35 @@ +--- +subcategory: "Redshift" +layout: "aws" +page_title: "AWS: aws_redshift_orderable_cluster" +description: |- + Information about RDS orderable DB instances. +--- + +# Data Source: aws_redshift_orderable_cluster + +Information about Redshift Orderable Clusters and valid parameter combinations. + +## Example Usage + +```hcl +data "aws_redshift_orderable_cluster" "test" { + cluster_type = "multi-node" + preferred_node_types = ["dc2.large", "ds2.xlarge"] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cluster_type` - (Optional) Reshift Cluster type. e.g. `multi-node` or `single-node` +* `cluster_version` - (Optional) Redshift Cluster version. e.g. `1.0` +* `node_type` - (Optional) Redshift Cluster node type. e.g. `dc2.8xlarge` +* `preferred_node_types` - (Optional) Ordered list of preferred Redshift Cluster node types. The first match in this list will be returned. If no preferred matches are found and the original search returned more than one result, an error is returned. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `availability_zones` - List of Availability Zone names where the Redshit Cluster is available.