github.com/jrperritt/terraform@v0.1.1-0.20170525065507-96f391dafc38/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 TestAccAWSRDSCluster_iamAuth(t *testing.T) {
   229  	var v rds.DBCluster
   230  
   231  	resource.Test(t, resource.TestCase{
   232  		PreCheck:     func() { testAccPreCheck(t) },
   233  		Providers:    testAccProviders,
   234  		CheckDestroy: testAccCheckAWSClusterDestroy,
   235  		Steps: []resource.TestStep{
   236  			{
   237  				Config: testAccAWSClusterConfig_iamAuth(acctest.RandInt()),
   238  				Check: resource.ComposeTestCheckFunc(
   239  					testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
   240  					resource.TestCheckResourceAttr(
   241  						"aws_rds_cluster.default", "iam_database_authentication_enabled", "true"),
   242  				),
   243  			},
   244  		},
   245  	})
   246  }
   247  
   248  func testAccCheckAWSClusterDestroy(s *terraform.State) error {
   249  	for _, rs := range s.RootModule().Resources {
   250  		if rs.Type != "aws_rds_cluster" {
   251  			continue
   252  		}
   253  
   254  		// Try to find the Group
   255  		conn := testAccProvider.Meta().(*AWSClient).rdsconn
   256  		var err error
   257  		resp, err := conn.DescribeDBClusters(
   258  			&rds.DescribeDBClustersInput{
   259  				DBClusterIdentifier: aws.String(rs.Primary.ID),
   260  			})
   261  
   262  		if err == nil {
   263  			if len(resp.DBClusters) != 0 &&
   264  				*resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID {
   265  				return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID)
   266  			}
   267  		}
   268  
   269  		// Return nil if the cluster is already destroyed
   270  		if awsErr, ok := err.(awserr.Error); ok {
   271  			if awsErr.Code() == "DBClusterNotFoundFault" {
   272  				return nil
   273  			}
   274  		}
   275  
   276  		return err
   277  	}
   278  
   279  	return nil
   280  }
   281  
   282  func testAccCheckAWSClusterSnapshot(rInt int) resource.TestCheckFunc {
   283  	return func(s *terraform.State) error {
   284  		for _, rs := range s.RootModule().Resources {
   285  			if rs.Type != "aws_rds_cluster" {
   286  				continue
   287  			}
   288  
   289  			// Try and delete the snapshot before we check for the cluster not found
   290  			snapshot_identifier := fmt.Sprintf("tf-acctest-rdscluster-snapshot-%d", rInt)
   291  
   292  			awsClient := testAccProvider.Meta().(*AWSClient)
   293  			conn := awsClient.rdsconn
   294  
   295  			arn, arnErr := buildRDSClusterARN(snapshot_identifier, awsClient.partition, awsClient.accountid, awsClient.region)
   296  			tagsARN := strings.Replace(arn, ":cluster:", ":snapshot:", 1)
   297  			if arnErr != nil {
   298  				return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, arnErr)
   299  			}
   300  
   301  			log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier)
   302  			_, snapDeleteErr := conn.DeleteDBClusterSnapshot(
   303  				&rds.DeleteDBClusterSnapshotInput{
   304  					DBClusterSnapshotIdentifier: aws.String(snapshot_identifier),
   305  				})
   306  			if snapDeleteErr != nil {
   307  				return snapDeleteErr
   308  			}
   309  
   310  			// Try to find the Group
   311  			var err error
   312  			resp, err := conn.DescribeDBClusters(
   313  				&rds.DescribeDBClustersInput{
   314  					DBClusterIdentifier: aws.String(rs.Primary.ID),
   315  				})
   316  
   317  			if err == nil {
   318  				if len(resp.DBClusters) != 0 &&
   319  					*resp.DBClusters[0].DBClusterIdentifier == rs.Primary.ID {
   320  					return fmt.Errorf("DB Cluster %s still exists", rs.Primary.ID)
   321  				}
   322  			}
   323  
   324  			// Return nil if the cluster is already destroyed
   325  			if awsErr, ok := err.(awserr.Error); ok {
   326  				if awsErr.Code() == "DBClusterNotFoundFault" {
   327  					return nil
   328  				}
   329  			}
   330  
   331  			return err
   332  		}
   333  
   334  		return nil
   335  	}
   336  }
   337  
   338  func testAccCheckAWSClusterExists(n string, v *rds.DBCluster) resource.TestCheckFunc {
   339  	return func(s *terraform.State) error {
   340  		rs, ok := s.RootModule().Resources[n]
   341  		if !ok {
   342  			return fmt.Errorf("Not found: %s", n)
   343  		}
   344  
   345  		if rs.Primary.ID == "" {
   346  			return fmt.Errorf("No DB Instance ID is set")
   347  		}
   348  
   349  		conn := testAccProvider.Meta().(*AWSClient).rdsconn
   350  		resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{
   351  			DBClusterIdentifier: aws.String(rs.Primary.ID),
   352  		})
   353  
   354  		if err != nil {
   355  			return err
   356  		}
   357  
   358  		for _, c := range resp.DBClusters {
   359  			if *c.DBClusterIdentifier == rs.Primary.ID {
   360  				*v = *c
   361  				return nil
   362  			}
   363  		}
   364  
   365  		return fmt.Errorf("DB Cluster (%s) not found", rs.Primary.ID)
   366  	}
   367  }
   368  
   369  func testAccAWSClusterConfig(n int) string {
   370  	return fmt.Sprintf(`
   371  resource "aws_rds_cluster" "default" {
   372    cluster_identifier = "tf-aurora-cluster-%d"
   373    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   374    database_name = "mydb"
   375    master_username = "foo"
   376    master_password = "mustbeeightcharaters"
   377    db_cluster_parameter_group_name = "default.aurora5.6"
   378    skip_final_snapshot = true
   379    tags {
   380      Environment = "production"
   381    }
   382  }`, n)
   383  }
   384  
   385  func testAccAWSClusterConfig_namePrefix(n int) string {
   386  	return fmt.Sprintf(`
   387  resource "aws_rds_cluster" "test" {
   388    cluster_identifier_prefix = "tf-test-"
   389    master_username = "root"
   390    master_password = "password"
   391    db_subnet_group_name = "${aws_db_subnet_group.test.name}"
   392    skip_final_snapshot = true
   393  }
   394  
   395  resource "aws_vpc" "test" {
   396    cidr_block = "10.0.0.0/16"
   397  	tags {
   398  		Name = "testAccAWSClusterConfig_namePrefix"
   399  	}
   400  }
   401  
   402  resource "aws_subnet" "a" {
   403    vpc_id = "${aws_vpc.test.id}"
   404    cidr_block = "10.0.0.0/24"
   405    availability_zone = "us-west-2a"
   406  }
   407  
   408  resource "aws_subnet" "b" {
   409    vpc_id = "${aws_vpc.test.id}"
   410    cidr_block = "10.0.1.0/24"
   411    availability_zone = "us-west-2b"
   412  }
   413  
   414  resource "aws_db_subnet_group" "test" {
   415    name = "tf-test-%d"
   416    subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
   417  }
   418  `, n)
   419  }
   420  
   421  func testAccAWSClusterConfig_generatedName(n int) string {
   422  	return fmt.Sprintf(`
   423  resource "aws_rds_cluster" "test" {
   424    master_username = "root"
   425    master_password = "password"
   426    db_subnet_group_name = "${aws_db_subnet_group.test.name}"
   427    skip_final_snapshot = true
   428  }
   429  
   430  resource "aws_vpc" "test" {
   431    cidr_block = "10.0.0.0/16"
   432  	tags {
   433  		Name = "testAccAWSClusterConfig_generatedName"
   434  	}
   435  }
   436  
   437  resource "aws_subnet" "a" {
   438    vpc_id = "${aws_vpc.test.id}"
   439    cidr_block = "10.0.0.0/24"
   440    availability_zone = "us-west-2a"
   441  }
   442  
   443  resource "aws_subnet" "b" {
   444    vpc_id = "${aws_vpc.test.id}"
   445    cidr_block = "10.0.1.0/24"
   446    availability_zone = "us-west-2b"
   447  }
   448  
   449  resource "aws_db_subnet_group" "test" {
   450    name = "tf-test-%d"
   451    subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
   452  }
   453  `, n)
   454  }
   455  
   456  func testAccAWSClusterConfigWithFinalSnapshot(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    final_snapshot_identifier = "tf-acctest-rdscluster-snapshot-%d"
   466    tags {
   467      Environment = "production"
   468    }
   469  }`, n, n)
   470  }
   471  
   472  func testAccAWSClusterConfigWithoutUserNameAndPassword(n int) string {
   473  	return fmt.Sprintf(`
   474  resource "aws_rds_cluster" "default" {
   475    cluster_identifier = "tf-aurora-cluster-%d"
   476    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   477    database_name = "mydb"
   478    skip_final_snapshot = true
   479  }`, n)
   480  }
   481  
   482  func testAccAWSClusterConfigUpdatedTags(n int) string {
   483  	return fmt.Sprintf(`
   484  resource "aws_rds_cluster" "default" {
   485    cluster_identifier = "tf-aurora-cluster-%d"
   486    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   487    database_name = "mydb"
   488    master_username = "foo"
   489    master_password = "mustbeeightcharaters"
   490    db_cluster_parameter_group_name = "default.aurora5.6"
   491    skip_final_snapshot = true
   492    tags {
   493      Environment = "production"
   494      AnotherTag = "test"
   495    }
   496  }`, n)
   497  }
   498  
   499  func testAccAWSClusterConfig_kmsKey(n int) string {
   500  	return fmt.Sprintf(`
   501  
   502   resource "aws_kms_key" "foo" {
   503       description = "Terraform acc test %d"
   504       policy = <<POLICY
   505   {
   506     "Version": "2012-10-17",
   507     "Id": "kms-tf-1",
   508     "Statement": [
   509       {
   510         "Sid": "Enable IAM User Permissions",
   511         "Effect": "Allow",
   512         "Principal": {
   513           "AWS": "*"
   514         },
   515         "Action": "kms:*",
   516         "Resource": "*"
   517       }
   518     ]
   519   }
   520   POLICY
   521   }
   522  
   523   resource "aws_rds_cluster" "default" {
   524     cluster_identifier = "tf-aurora-cluster-%d"
   525     availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   526     database_name = "mydb"
   527     master_username = "foo"
   528     master_password = "mustbeeightcharaters"
   529     db_cluster_parameter_group_name = "default.aurora5.6"
   530     storage_encrypted = true
   531     kms_key_id = "${aws_kms_key.foo.arn}"
   532     skip_final_snapshot = true
   533   }`, n, n)
   534  }
   535  
   536  func testAccAWSClusterConfig_encrypted(n int) string {
   537  	return fmt.Sprintf(`
   538  resource "aws_rds_cluster" "default" {
   539    cluster_identifier = "tf-aurora-cluster-%d"
   540    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   541    database_name = "mydb"
   542    master_username = "foo"
   543    master_password = "mustbeeightcharaters"
   544    storage_encrypted = true
   545    skip_final_snapshot = true
   546  }`, n)
   547  }
   548  
   549  func testAccAWSClusterConfig_backups(n int) string {
   550  	return fmt.Sprintf(`
   551  resource "aws_rds_cluster" "default" {
   552    cluster_identifier = "tf-aurora-cluster-%d"
   553    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   554    database_name = "mydb"
   555    master_username = "foo"
   556    master_password = "mustbeeightcharaters"
   557    backup_retention_period = 5
   558    preferred_backup_window = "07:00-09:00"
   559    preferred_maintenance_window = "tue:04:00-tue:04:30"
   560    skip_final_snapshot = true
   561  }`, n)
   562  }
   563  
   564  func testAccAWSClusterConfig_backupsUpdate(n int) string {
   565  	return fmt.Sprintf(`
   566  resource "aws_rds_cluster" "default" {
   567    cluster_identifier = "tf-aurora-cluster-%d"
   568    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   569    database_name = "mydb"
   570    master_username = "foo"
   571    master_password = "mustbeeightcharaters"
   572    backup_retention_period = 10
   573    preferred_backup_window = "03:00-09:00"
   574    preferred_maintenance_window = "wed:01:00-wed:01:30"
   575    apply_immediately = true
   576    skip_final_snapshot = true
   577  }`, n)
   578  }
   579  
   580  func testAccAWSClusterConfig_iamAuth(n int) string {
   581  	return fmt.Sprintf(`
   582  resource "aws_rds_cluster" "default" {
   583    cluster_identifier = "tf-aurora-cluster-%d"
   584    availability_zones = ["us-west-2a","us-west-2b","us-west-2c"]
   585    database_name = "mydb"
   586    master_username = "foo"
   587    master_password = "mustbeeightcharaters"
   588    iam_database_authentication_enabled = true
   589    skip_final_snapshot = true
   590  }`, n)
   591  }