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