github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_rds_cluster_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"regexp"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/helper/acctest"
    11  	"github.com/hashicorp/terraform/helper/resource"
    12  	"github.com/hashicorp/terraform/terraform"
    13  
    14  	"github.com/aws/aws-sdk-go/aws"
    15  	"github.com/aws/aws-sdk-go/aws/awserr"
    16  	"github.com/aws/aws-sdk-go/service/rds"
    17  )
    18  
    19  func TestAccAWSRDSCluster_basic(t *testing.T) {
    20  	var v rds.DBCluster
    21  
    22  	resource.Test(t, resource.TestCase{
    23  		PreCheck:     func() { testAccPreCheck(t) },
    24  		Providers:    testAccProviders,
    25  		CheckDestroy: testAccCheckAWSClusterDestroy,
    26  		Steps: []resource.TestStep{
    27  			{
    28  				Config: testAccAWSClusterConfig(acctest.RandInt()),
    29  				Check: resource.ComposeTestCheckFunc(
    30  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
    31  					resource.TestCheckResourceAttr(
    32  						"aws_rds_cluster.default", "storage_encrypted", "false"),
    33  					resource.TestCheckResourceAttr(
    34  						"aws_rds_cluster.default", "db_cluster_parameter_group_name", "default.aurora5.6"),
    35  					resource.TestCheckResourceAttrSet(
    36  						"aws_rds_cluster.default", "reader_endpoint"),
    37  				),
    38  			},
    39  		},
    40  	})
    41  }
    42  
    43  func TestAccAWSRDSCluster_namePrefix(t *testing.T) {
    44  	var v rds.DBCluster
    45  
    46  	resource.Test(t, resource.TestCase{
    47  		PreCheck:     func() { testAccPreCheck(t) },
    48  		Providers:    testAccProviders,
    49  		CheckDestroy: testAccCheckAWSClusterDestroy,
    50  		Steps: []resource.TestStep{
    51  			{
    52  				Config: testAccAWSClusterConfig_namePrefix(acctest.RandInt()),
    53  				Check: resource.ComposeTestCheckFunc(
    54  					testAccCheckAWSClusterExists("aws_rds_cluster.test", &v),
    55  					resource.TestMatchResourceAttr(
    56  						"aws_rds_cluster.test", "cluster_identifier", regexp.MustCompile("^tf-test-")),
    57  				),
    58  			},
    59  		},
    60  	})
    61  }
    62  
    63  func TestAccAWSRDSCluster_generatedName(t *testing.T) {
    64  	var v rds.DBCluster
    65  
    66  	resource.Test(t, resource.TestCase{
    67  		PreCheck:     func() { testAccPreCheck(t) },
    68  		Providers:    testAccProviders,
    69  		CheckDestroy: testAccCheckAWSClusterDestroy,
    70  		Steps: []resource.TestStep{
    71  			{
    72  				Config: testAccAWSClusterConfig_generatedName(acctest.RandInt()),
    73  				Check: resource.ComposeTestCheckFunc(
    74  					testAccCheckAWSClusterExists("aws_rds_cluster.test", &v),
    75  					resource.TestMatchResourceAttr(
    76  						"aws_rds_cluster.test", "cluster_identifier", regexp.MustCompile("^tf-")),
    77  				),
    78  			},
    79  		},
    80  	})
    81  }
    82  
    83  func TestAccAWSRDSCluster_takeFinalSnapshot(t *testing.T) {
    84  	var v rds.DBCluster
    85  	rInt := acctest.RandInt()
    86  
    87  	resource.Test(t, resource.TestCase{
    88  		PreCheck:     func() { testAccPreCheck(t) },
    89  		Providers:    testAccProviders,
    90  		CheckDestroy: testAccCheckAWSClusterSnapshot(rInt),
    91  		Steps: []resource.TestStep{
    92  			{
    93  				Config: testAccAWSClusterConfigWithFinalSnapshot(rInt),
    94  				Check: resource.ComposeTestCheckFunc(
    95  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
    96  				),
    97  			},
    98  		},
    99  	})
   100  }
   101  
   102  /// This is a regression test to make sure that we always cover the scenario as hightlighted in
   103  /// https://github.com/hashicorp/terraform/issues/11568
   104  func TestAccAWSRDSCluster_missingUserNameCausesError(t *testing.T) {
   105  	resource.Test(t, resource.TestCase{
   106  		PreCheck:     func() { testAccPreCheck(t) },
   107  		Providers:    testAccProviders,
   108  		CheckDestroy: testAccCheckAWSClusterDestroy,
   109  		Steps: []resource.TestStep{
   110  			{
   111  				Config:      testAccAWSClusterConfigWithoutUserNameAndPassword(acctest.RandInt()),
   112  				ExpectError: regexp.MustCompile(`required field is not set`),
   113  			},
   114  		},
   115  	})
   116  }
   117  
   118  func TestAccAWSRDSCluster_updateTags(t *testing.T) {
   119  	var v rds.DBCluster
   120  	ri := acctest.RandInt()
   121  
   122  	resource.Test(t, resource.TestCase{
   123  		PreCheck:     func() { testAccPreCheck(t) },
   124  		Providers:    testAccProviders,
   125  		CheckDestroy: testAccCheckAWSClusterDestroy,
   126  		Steps: []resource.TestStep{
   127  			{
   128  				Config: testAccAWSClusterConfig(ri),
   129  				Check: resource.ComposeTestCheckFunc(
   130  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   131  					resource.TestCheckResourceAttr(
   132  						"aws_rds_cluster.default", "tags.%", "1"),
   133  				),
   134  			},
   135  			{
   136  				Config: testAccAWSClusterConfigUpdatedTags(ri),
   137  				Check: resource.ComposeTestCheckFunc(
   138  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   139  					resource.TestCheckResourceAttr(
   140  						"aws_rds_cluster.default", "tags.%", "2"),
   141  				),
   142  			},
   143  		},
   144  	})
   145  }
   146  
   147  func TestAccAWSRDSCluster_kmsKey(t *testing.T) {
   148  	var v rds.DBCluster
   149  	keyRegex := regexp.MustCompile("^arn:aws:kms:")
   150  
   151  	resource.Test(t, resource.TestCase{
   152  		PreCheck:     func() { testAccPreCheck(t) },
   153  		Providers:    testAccProviders,
   154  		CheckDestroy: testAccCheckAWSClusterDestroy,
   155  		Steps: []resource.TestStep{
   156  			{
   157  				Config: testAccAWSClusterConfig_kmsKey(acctest.RandInt()),
   158  				Check: resource.ComposeTestCheckFunc(
   159  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   160  					resource.TestMatchResourceAttr(
   161  						"aws_rds_cluster.default", "kms_key_id", keyRegex),
   162  				),
   163  			},
   164  		},
   165  	})
   166  }
   167  
   168  func TestAccAWSRDSCluster_encrypted(t *testing.T) {
   169  	var v rds.DBCluster
   170  
   171  	resource.Test(t, resource.TestCase{
   172  		PreCheck:     func() { testAccPreCheck(t) },
   173  		Providers:    testAccProviders,
   174  		CheckDestroy: testAccCheckAWSClusterDestroy,
   175  		Steps: []resource.TestStep{
   176  			{
   177  				Config: testAccAWSClusterConfig_encrypted(acctest.RandInt()),
   178  				Check: resource.ComposeTestCheckFunc(
   179  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   180  					resource.TestCheckResourceAttr(
   181  						"aws_rds_cluster.default", "storage_encrypted", "true"),
   182  					resource.TestCheckResourceAttr(
   183  						"aws_rds_cluster.default", "db_cluster_parameter_group_name", "default.aurora5.6"),
   184  				),
   185  			},
   186  		},
   187  	})
   188  }
   189  
   190  func TestAccAWSRDSCluster_backupsUpdate(t *testing.T) {
   191  	var v rds.DBCluster
   192  
   193  	ri := acctest.RandInt()
   194  	resource.Test(t, resource.TestCase{
   195  		PreCheck:     func() { testAccPreCheck(t) },
   196  		Providers:    testAccProviders,
   197  		CheckDestroy: testAccCheckAWSClusterDestroy,
   198  		Steps: []resource.TestStep{
   199  			{
   200  				Config: testAccAWSClusterConfig_backups(ri),
   201  				Check: resource.ComposeTestCheckFunc(
   202  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   203  					resource.TestCheckResourceAttr(
   204  						"aws_rds_cluster.default", "preferred_backup_window", "07:00-09:00"),
   205  					resource.TestCheckResourceAttr(
   206  						"aws_rds_cluster.default", "backup_retention_period", "5"),
   207  					resource.TestCheckResourceAttr(
   208  						"aws_rds_cluster.default", "preferred_maintenance_window", "tue:04:00-tue:04:30"),
   209  				),
   210  			},
   211  
   212  			resource.TestStep{
   213  				Config: testAccAWSClusterConfig_backupsUpdate(ri),
   214  				Check: resource.ComposeTestCheckFunc(
   215  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   216  					resource.TestCheckResourceAttr(
   217  						"aws_rds_cluster.default", "preferred_backup_window", "03:00-09:00"),
   218  					resource.TestCheckResourceAttr(
   219  						"aws_rds_cluster.default", "backup_retention_period", "10"),
   220  					resource.TestCheckResourceAttr(
   221  						"aws_rds_cluster.default", "preferred_maintenance_window", "wed:01:00-wed:01:30"),
   222  				),
   223  			},
   224  		},
   225  	})
   226  }
   227  
   228  func testAccCheckAWSClusterDestroy(s *terraform.State) error {
   229  	for _, rs := range s.RootModule().Resources {
   230  		if rs.Type != "aws_rds_cluster" {
   231  			continue
   232  		}
   233  
   234  		// Try to find the Group
   235  		conn := testAccProvider.Meta().(*AWSClient).rdsconn
   236  		var err error
   237  		resp, err := conn.DescribeDBClusters(
   238  			&rds.DescribeDBClustersInput{
   239  				DBClusterIdentifier: aws.String(rs.Primary.ID),
   240  			})
   241  
   242  		if err == nil {
   243  			if len(resp.DBClusters) != 0 &&
   244  				*resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID {
   245  				return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID)
   246  			}
   247  		}
   248  
   249  		// Return nil if the cluster is already destroyed
   250  		if awsErr, ok := err.(awserr.Error); ok {
   251  			if awsErr.Code() == "DBClusterNotFoundFault" {
   252  				return nil
   253  			}
   254  		}
   255  
   256  		return err
   257  	}
   258  
   259  	return nil
   260  }
   261  
   262  func testAccCheckAWSClusterSnapshot(rInt int) resource.TestCheckFunc {
   263  	return func(s *terraform.State) error {
   264  		for _, rs := range s.RootModule().Resources {
   265  			if rs.Type != "aws_rds_cluster" {
   266  				continue
   267  			}
   268  
   269  			// Try and delete the snapshot before we check for the cluster not found
   270  			snapshot_identifier := fmt.Sprintf("tf-acctest-rdscluster-snapshot-%d", rInt)
   271  
   272  			awsClient := testAccProvider.Meta().(*AWSClient)
   273  			conn := awsClient.rdsconn
   274  
   275  			arn, arnErr := buildRDSClusterARN(snapshot_identifier, awsClient.partition, awsClient.accountid, awsClient.region)
   276  			tagsARN := strings.Replace(arn, ":cluster:", ":snapshot:", 1)
   277  			if arnErr != nil {
   278  				return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, arnErr)
   279  			}
   280  
   281  			log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier)
   282  			_, snapDeleteErr := conn.DeleteDBClusterSnapshot(
   283  				&rds.DeleteDBClusterSnapshotInput{
   284  					DBClusterSnapshotIdentifier: aws.String(snapshot_identifier),
   285  				})
   286  			if snapDeleteErr != nil {
   287  				return snapDeleteErr
   288  			}
   289  
   290  			// Try to find the Group
   291  			var err error
   292  			resp, err := conn.DescribeDBClusters(
   293  				&rds.DescribeDBClustersInput{
   294  					DBClusterIdentifier: aws.String(rs.Primary.ID),
   295  				})
   296  
   297  			if err == nil {
   298  				if len(resp.DBClusters) != 0 &&
   299  					*resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID {
   300  					return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID)
   301  				}
   302  			}
   303  
   304  			// Return nil if the cluster is already destroyed
   305  			if awsErr, ok := err.(awserr.Error); ok {
   306  				if awsErr.Code() == "DBClusterNotFoundFault" {
   307  					return nil
   308  				}
   309  			}
   310  
   311  			return err
   312  		}
   313  
   314  		return nil
   315  	}
   316  }
   317  
   318  func testAccCheckAWSClusterExists(n string, v *rds.DBCluster) resource.TestCheckFunc {
   319  	return func(s *terraform.State) error {
   320  		rs, ok := s.RootModule().Resources[n]
   321  		if !ok {
   322  			return fmt.Errorf("Not found: %s", n)
   323  		}
   324  
   325  		if rs.Primary.ID == "" {
   326  			return fmt.Errorf("No DB Instance ID is set")
   327  		}
   328  
   329  		conn := testAccProvider.Meta().(*AWSClient).rdsconn
   330  		resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{
   331  			DBClusterIdentifier: aws.String(rs.Primary.ID),
   332  		})
   333  
   334  		if err != nil {
   335  			return err
   336  		}
   337  
   338  		for _, c := range resp.DBClusters {
   339  			if *c.DBClusterIdentifier == rs.Primary.ID {
   340  				*v = *c
   341  				return nil
   342  			}
   343  		}
   344  
   345  		return fmt.Errorf("DB Cluster (%s) not found", rs.Primary.ID)
   346  	}
   347  }
   348  
   349  func testAccAWSClusterConfig(n int) string {
   350  	return fmt.Sprintf(`
   351  resource "aws_rds_cluster" "default" {
   352    cluster_identifier = "tf-aurora-cluster-%d"
   353    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   354    database_name = "mydb"
   355    master_username = "foo"
   356    master_password = "mustbeeightcharaters"
   357    db_cluster_parameter_group_name = "default.aurora5.6"
   358    skip_final_snapshot = true
   359    tags {
   360      Environment = "production"
   361    }
   362  }`, n)
   363  }
   364  
   365  func testAccAWSClusterConfig_namePrefix(n int) string {
   366  	return fmt.Sprintf(`
   367  resource "aws_rds_cluster" "test" {
   368    cluster_identifier_prefix = "tf-test-"
   369    master_username = "root"
   370    master_password = "password"
   371    db_subnet_group_name = "${aws_db_subnet_group.test.name}"
   372    skip_final_snapshot = true
   373  }
   374  
   375  resource "aws_vpc" "test" {
   376    cidr_block = "10.0.0.0/16"
   377  }
   378  
   379  resource "aws_subnet" "a" {
   380    vpc_id = "${aws_vpc.test.id}"
   381    cidr_block = "10.0.0.0/24"
   382    availability_zone = "us-west-2a"
   383  }
   384  
   385  resource "aws_subnet" "b" {
   386    vpc_id = "${aws_vpc.test.id}"
   387    cidr_block = "10.0.1.0/24"
   388    availability_zone = "us-west-2b"
   389  }
   390  
   391  resource "aws_db_subnet_group" "test" {
   392    name = "tf-test-%d"
   393    subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
   394  }
   395  `, n)
   396  }
   397  
   398  func testAccAWSClusterConfig_generatedName(n int) string {
   399  	return fmt.Sprintf(`
   400  resource "aws_rds_cluster" "test" {
   401    master_username = "root"
   402    master_password = "password"
   403    db_subnet_group_name = "${aws_db_subnet_group.test.name}"
   404    skip_final_snapshot = true
   405  }
   406  
   407  resource "aws_vpc" "test" {
   408    cidr_block = "10.0.0.0/16"
   409  }
   410  
   411  resource "aws_subnet" "a" {
   412    vpc_id = "${aws_vpc.test.id}"
   413    cidr_block = "10.0.0.0/24"
   414    availability_zone = "us-west-2a"
   415  }
   416  
   417  resource "aws_subnet" "b" {
   418    vpc_id = "${aws_vpc.test.id}"
   419    cidr_block = "10.0.1.0/24"
   420    availability_zone = "us-west-2b"
   421  }
   422  
   423  resource "aws_db_subnet_group" "test" {
   424    name = "tf-test-%d"
   425    subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
   426  }
   427  `, n)
   428  }
   429  
   430  func testAccAWSClusterConfigWithFinalSnapshot(n int) string {
   431  	return fmt.Sprintf(`
   432  resource "aws_rds_cluster" "default" {
   433    cluster_identifier = "tf-aurora-cluster-%d"
   434    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   435    database_name = "mydb"
   436    master_username = "foo"
   437    master_password = "mustbeeightcharaters"
   438    db_cluster_parameter_group_name = "default.aurora5.6"
   439    final_snapshot_identifier = "tf-acctest-rdscluster-snapshot-%d"
   440    tags {
   441      Environment = "production"
   442    }
   443  }`, n, n)
   444  }
   445  
   446  func testAccAWSClusterConfigWithoutUserNameAndPassword(n int) string {
   447  	return fmt.Sprintf(`
   448  resource "aws_rds_cluster" "default" {
   449    cluster_identifier = "tf-aurora-cluster-%d"
   450    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   451    database_name = "mydb"
   452    skip_final_snapshot = true
   453  }`, n)
   454  }
   455  
   456  func testAccAWSClusterConfigUpdatedTags(n int) string {
   457  	return fmt.Sprintf(`
   458  resource "aws_rds_cluster" "default" {
   459    cluster_identifier = "tf-aurora-cluster-%d"
   460    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   461    database_name = "mydb"
   462    master_username = "foo"
   463    master_password = "mustbeeightcharaters"
   464    db_cluster_parameter_group_name = "default.aurora5.6"
   465    skip_final_snapshot = true
   466    tags {
   467      Environment = "production"
   468      AnotherTag = "test"
   469    }
   470  }`, n)
   471  }
   472  
   473  func testAccAWSClusterConfig_kmsKey(n int) string {
   474  	return fmt.Sprintf(`
   475  
   476   resource "aws_kms_key" "foo" {
   477       description = "Terraform acc test %d"
   478       policy = <<POLICY
   479   {
   480     "Version": "2012-10-17",
   481     "Id": "kms-tf-1",
   482     "Statement": [
   483       {
   484         "Sid": "Enable IAM User Permissions",
   485         "Effect": "Allow",
   486         "Principal": {
   487           "AWS": "*"
   488         },
   489         "Action": "kms:*",
   490         "Resource": "*"
   491       }
   492     ]
   493   }
   494   POLICY
   495   }
   496  
   497   resource "aws_rds_cluster" "default" {
   498     cluster_identifier = "tf-aurora-cluster-%d"
   499     availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   500     database_name = "mydb"
   501     master_username = "foo"
   502     master_password = "mustbeeightcharaters"
   503     db_cluster_parameter_group_name = "default.aurora5.6"
   504     storage_encrypted = true
   505     kms_key_id = "${aws_kms_key.foo.arn}"
   506     skip_final_snapshot = true
   507   }`, n, n)
   508  }
   509  
   510  func testAccAWSClusterConfig_encrypted(n int) string {
   511  	return fmt.Sprintf(`
   512  resource "aws_rds_cluster" "default" {
   513    cluster_identifier = "tf-aurora-cluster-%d"
   514    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   515    database_name = "mydb"
   516    master_username = "foo"
   517    master_password = "mustbeeightcharaters"
   518    storage_encrypted = true
   519    skip_final_snapshot = true
   520  }`, n)
   521  }
   522  
   523  func testAccAWSClusterConfig_backups(n int) string {
   524  	return fmt.Sprintf(`
   525  resource "aws_rds_cluster" "default" {
   526    cluster_identifier = "tf-aurora-cluster-%d"
   527    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   528    database_name = "mydb"
   529    master_username = "foo"
   530    master_password = "mustbeeightcharaters"
   531    backup_retention_period = 5
   532    preferred_backup_window = "07:00-09:00"
   533    preferred_maintenance_window = "tue:04:00-tue:04:30"
   534    skip_final_snapshot = true
   535  }`, n)
   536  }
   537  
   538  func testAccAWSClusterConfig_backupsUpdate(n int) string {
   539  	return fmt.Sprintf(`
   540  resource "aws_rds_cluster" "default" {
   541    cluster_identifier = "tf-aurora-cluster-%d"
   542    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   543    database_name = "mydb"
   544    master_username = "foo"
   545    master_password = "mustbeeightcharaters"
   546    backup_retention_period = 10
   547    preferred_backup_window = "03:00-09:00"
   548    preferred_maintenance_window = "wed:01:00-wed:01:30"
   549    apply_immediately = true
   550    skip_final_snapshot = true
   551  }`, n)
   552  }