github.com/jdextraze/terraform@v0.6.17-0.20160511153921-e33847c8a8af/builtin/providers/aws/resource_aws_db_instance_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"math/rand"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/hashicorp/terraform/helper/acctest"
    13  	"github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/terraform"
    15  
    16  	"github.com/aws/aws-sdk-go/aws"
    17  	"github.com/aws/aws-sdk-go/aws/awserr"
    18  	"github.com/aws/aws-sdk-go/service/rds"
    19  )
    20  
    21  func TestAccAWSDBInstance_basic(t *testing.T) {
    22  	var v rds.DBInstance
    23  
    24  	resource.Test(t, resource.TestCase{
    25  		PreCheck:     func() { testAccPreCheck(t) },
    26  		Providers:    testAccProviders,
    27  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
    28  		Steps: []resource.TestStep{
    29  			resource.TestStep{
    30  				Config: testAccAWSDBInstanceConfig,
    31  				Check: resource.ComposeTestCheckFunc(
    32  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
    33  					testAccCheckAWSDBInstanceAttributes(&v),
    34  					resource.TestCheckResourceAttr(
    35  						"aws_db_instance.bar", "allocated_storage", "10"),
    36  					resource.TestCheckResourceAttr(
    37  						"aws_db_instance.bar", "engine", "mysql"),
    38  					resource.TestCheckResourceAttr(
    39  						"aws_db_instance.bar", "license_model", "general-public-license"),
    40  					resource.TestCheckResourceAttr(
    41  						"aws_db_instance.bar", "instance_class", "db.t1.micro"),
    42  					resource.TestCheckResourceAttr(
    43  						"aws_db_instance.bar", "name", "baz"),
    44  					resource.TestCheckResourceAttr(
    45  						"aws_db_instance.bar", "username", "foo"),
    46  					resource.TestCheckResourceAttr(
    47  						"aws_db_instance.bar", "parameter_group_name", "default.mysql5.6"),
    48  				),
    49  			},
    50  		},
    51  	})
    52  }
    53  
    54  func TestAccAWSDBInstance_optionGroup(t *testing.T) {
    55  	var v rds.DBInstance
    56  
    57  	resource.Test(t, resource.TestCase{
    58  		PreCheck:     func() { testAccPreCheck(t) },
    59  		Providers:    testAccProviders,
    60  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
    61  		Steps: []resource.TestStep{
    62  			resource.TestStep{
    63  				Config: testAccAWSDBInstanceConfigWithOptionGroup,
    64  				Check: resource.ComposeTestCheckFunc(
    65  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
    66  					testAccCheckAWSDBInstanceAttributes(&v),
    67  					resource.TestCheckResourceAttr(
    68  						"aws_db_instance.bar", "option_group_name", "option-group-test-terraform"),
    69  				),
    70  			},
    71  		},
    72  	})
    73  }
    74  
    75  func TestAccAWSDBInstanceReplica(t *testing.T) {
    76  	var s, r rds.DBInstance
    77  
    78  	resource.Test(t, resource.TestCase{
    79  		PreCheck:     func() { testAccPreCheck(t) },
    80  		Providers:    testAccProviders,
    81  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
    82  		Steps: []resource.TestStep{
    83  			resource.TestStep{
    84  				Config: testAccReplicaInstanceConfig(rand.New(rand.NewSource(time.Now().UnixNano())).Int()),
    85  				Check: resource.ComposeTestCheckFunc(
    86  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &s),
    87  					testAccCheckAWSDBInstanceExists("aws_db_instance.replica", &r),
    88  					testAccCheckAWSDBInstanceReplicaAttributes(&s, &r),
    89  				),
    90  			},
    91  		},
    92  	})
    93  }
    94  
    95  func TestAccAWSDBInstanceSnapshot(t *testing.T) {
    96  	var snap rds.DBInstance
    97  
    98  	resource.Test(t, resource.TestCase{
    99  		PreCheck:  func() { testAccPreCheck(t) },
   100  		Providers: testAccProviders,
   101  		// testAccCheckAWSDBInstanceSnapshot verifies a database snapshot is
   102  		// created, and subequently deletes it
   103  		CheckDestroy: testAccCheckAWSDBInstanceSnapshot,
   104  		Steps: []resource.TestStep{
   105  			resource.TestStep{
   106  				Config: testAccSnapshotInstanceConfig(),
   107  				Check: resource.ComposeTestCheckFunc(
   108  					testAccCheckAWSDBInstanceExists("aws_db_instance.snapshot", &snap),
   109  				),
   110  			},
   111  		},
   112  	})
   113  }
   114  
   115  func TestAccAWSDBInstanceNoSnapshot(t *testing.T) {
   116  	var nosnap rds.DBInstance
   117  
   118  	resource.Test(t, resource.TestCase{
   119  		PreCheck:     func() { testAccPreCheck(t) },
   120  		Providers:    testAccProviders,
   121  		CheckDestroy: testAccCheckAWSDBInstanceNoSnapshot,
   122  		Steps: []resource.TestStep{
   123  			resource.TestStep{
   124  				Config: testAccNoSnapshotInstanceConfig(),
   125  				Check: resource.ComposeTestCheckFunc(
   126  					testAccCheckAWSDBInstanceExists("aws_db_instance.no_snapshot", &nosnap),
   127  				),
   128  			},
   129  		},
   130  	})
   131  }
   132  
   133  func TestAccAWSDBInstance_enhancedMonitoring(t *testing.T) {
   134  	var dbInstance rds.DBInstance
   135  
   136  	resource.Test(t, resource.TestCase{
   137  		PreCheck:     func() { testAccPreCheck(t) },
   138  		Providers:    testAccProviders,
   139  		CheckDestroy: testAccCheckAWSDBInstanceNoSnapshot,
   140  		Steps: []resource.TestStep{
   141  			resource.TestStep{
   142  				Config: testAccSnapshotInstanceConfig_enhancedMonitoring,
   143  				Check: resource.ComposeTestCheckFunc(
   144  					testAccCheckAWSDBInstanceExists("aws_db_instance.enhanced_monitoring", &dbInstance),
   145  					resource.TestCheckResourceAttr(
   146  						"aws_db_instance.enhanced_monitoring", "monitoring_interval", "5"),
   147  				),
   148  			},
   149  		},
   150  	})
   151  }
   152  
   153  func testAccCheckAWSDBInstanceDestroy(s *terraform.State) error {
   154  	conn := testAccProvider.Meta().(*AWSClient).rdsconn
   155  
   156  	for _, rs := range s.RootModule().Resources {
   157  		if rs.Type != "aws_db_instance" {
   158  			continue
   159  		}
   160  
   161  		// Try to find the Group
   162  		var err error
   163  		resp, err := conn.DescribeDBInstances(
   164  			&rds.DescribeDBInstancesInput{
   165  				DBInstanceIdentifier: aws.String(rs.Primary.ID),
   166  			})
   167  
   168  		if ae, ok := err.(awserr.Error); ok && ae.Code() == "DBInstanceNotFound" {
   169  			continue
   170  		}
   171  
   172  		if err == nil {
   173  			if len(resp.DBInstances) != 0 &&
   174  				*resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID {
   175  				return fmt.Errorf("DB Instance still exists")
   176  			}
   177  		}
   178  
   179  		// Verify the error
   180  		newerr, ok := err.(awserr.Error)
   181  		if !ok {
   182  			return err
   183  		}
   184  		if newerr.Code() != "DBInstanceNotFound" {
   185  			return err
   186  		}
   187  	}
   188  
   189  	return nil
   190  }
   191  
   192  func testAccCheckAWSDBInstanceAttributes(v *rds.DBInstance) resource.TestCheckFunc {
   193  	return func(s *terraform.State) error {
   194  
   195  		if *v.Engine != "mysql" {
   196  			return fmt.Errorf("bad engine: %#v", *v.Engine)
   197  		}
   198  
   199  		if *v.EngineVersion == "" {
   200  			return fmt.Errorf("bad engine_version: %#v", *v.EngineVersion)
   201  		}
   202  
   203  		if *v.BackupRetentionPeriod != 0 {
   204  			return fmt.Errorf("bad backup_retention_period: %#v", *v.BackupRetentionPeriod)
   205  		}
   206  
   207  		return nil
   208  	}
   209  }
   210  
   211  func testAccCheckAWSDBInstanceReplicaAttributes(source, replica *rds.DBInstance) resource.TestCheckFunc {
   212  	return func(s *terraform.State) error {
   213  
   214  		if replica.ReadReplicaSourceDBInstanceIdentifier != nil && *replica.ReadReplicaSourceDBInstanceIdentifier != *source.DBInstanceIdentifier {
   215  			return fmt.Errorf("bad source identifier for replica, expected: '%s', got: '%s'", *source.DBInstanceIdentifier, *replica.ReadReplicaSourceDBInstanceIdentifier)
   216  		}
   217  
   218  		return nil
   219  	}
   220  }
   221  
   222  func testAccCheckAWSDBInstanceSnapshot(s *terraform.State) error {
   223  	conn := testAccProvider.Meta().(*AWSClient).rdsconn
   224  
   225  	for _, rs := range s.RootModule().Resources {
   226  		if rs.Type != "aws_db_instance" {
   227  			continue
   228  		}
   229  
   230  		var err error
   231  		resp, err := conn.DescribeDBInstances(
   232  			&rds.DescribeDBInstancesInput{
   233  				DBInstanceIdentifier: aws.String(rs.Primary.ID),
   234  			})
   235  
   236  		if err != nil {
   237  			newerr, _ := err.(awserr.Error)
   238  			if newerr.Code() != "DBInstanceNotFound" {
   239  				return err
   240  			}
   241  
   242  		} else {
   243  			if len(resp.DBInstances) != 0 &&
   244  				*resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID {
   245  				return fmt.Errorf("DB Instance still exists")
   246  			}
   247  		}
   248  
   249  		log.Printf("[INFO] Trying to locate the DBInstance Final Snapshot")
   250  		snapshot_identifier := "foobarbaz-test-terraform-final-snapshot-1"
   251  		_, snapErr := conn.DescribeDBSnapshots(
   252  			&rds.DescribeDBSnapshotsInput{
   253  				DBSnapshotIdentifier: aws.String(snapshot_identifier),
   254  			})
   255  
   256  		if snapErr != nil {
   257  			newerr, _ := snapErr.(awserr.Error)
   258  			if newerr.Code() == "DBSnapshotNotFound" {
   259  				return fmt.Errorf("Snapshot %s not found", snapshot_identifier)
   260  			}
   261  		} else { // snapshot was found
   262  			// verify we have the tags copied to the snapshot
   263  			instanceARN, err := buildRDSARN(snapshot_identifier, testAccProvider.Meta())
   264  			// tags have a different ARN, just swapping :db: for :snapshot:
   265  			tagsARN := strings.Replace(instanceARN, ":db:", ":snapshot:", 1)
   266  			if err != nil {
   267  				return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, err)
   268  			}
   269  			resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{
   270  				ResourceName: aws.String(tagsARN),
   271  			})
   272  			if err != nil {
   273  				return fmt.Errorf("Error retrieving tags for ARN (%s): %s", tagsARN, err)
   274  			}
   275  
   276  			if resp.TagList == nil || len(resp.TagList) == 0 {
   277  				return fmt.Errorf("Tag list is nil or zero: %s", resp.TagList)
   278  			}
   279  
   280  			var found bool
   281  			for _, t := range resp.TagList {
   282  				if *t.Key == "Name" && *t.Value == "tf-tags-db" {
   283  					found = true
   284  				}
   285  			}
   286  			if !found {
   287  				return fmt.Errorf("Expected to find tag Name (%s), but wasn't found. Tags: %s", "tf-tags-db", resp.TagList)
   288  			}
   289  			// end tag search
   290  
   291  			log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier)
   292  			_, snapDeleteErr := conn.DeleteDBSnapshot(
   293  				&rds.DeleteDBSnapshotInput{
   294  					DBSnapshotIdentifier: aws.String(snapshot_identifier),
   295  				})
   296  			if snapDeleteErr != nil {
   297  				return err
   298  			}
   299  		} // end snapshot was found
   300  	}
   301  
   302  	return nil
   303  }
   304  
   305  func testAccCheckAWSDBInstanceNoSnapshot(s *terraform.State) error {
   306  	conn := testAccProvider.Meta().(*AWSClient).rdsconn
   307  
   308  	for _, rs := range s.RootModule().Resources {
   309  		if rs.Type != "aws_db_instance" {
   310  			continue
   311  		}
   312  
   313  		var err error
   314  		resp, err := conn.DescribeDBInstances(
   315  			&rds.DescribeDBInstancesInput{
   316  				DBInstanceIdentifier: aws.String(rs.Primary.ID),
   317  			})
   318  
   319  		if err != nil {
   320  			newerr, _ := err.(awserr.Error)
   321  			if newerr.Code() != "DBInstanceNotFound" {
   322  				return err
   323  			}
   324  
   325  		} else {
   326  			if len(resp.DBInstances) != 0 &&
   327  				*resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID {
   328  				return fmt.Errorf("DB Instance still exists")
   329  			}
   330  		}
   331  
   332  		snapshot_identifier := "foobarbaz-test-terraform-final-snapshot-2"
   333  		_, snapErr := conn.DescribeDBSnapshots(
   334  			&rds.DescribeDBSnapshotsInput{
   335  				DBSnapshotIdentifier: aws.String(snapshot_identifier),
   336  			})
   337  
   338  		if snapErr != nil {
   339  			newerr, _ := snapErr.(awserr.Error)
   340  			if newerr.Code() != "DBSnapshotNotFound" {
   341  				return fmt.Errorf("Snapshot %s found and it shouldn't have been", snapshot_identifier)
   342  			}
   343  		}
   344  	}
   345  
   346  	return nil
   347  }
   348  
   349  func testAccCheckAWSDBInstanceExists(n string, v *rds.DBInstance) resource.TestCheckFunc {
   350  	return func(s *terraform.State) error {
   351  		rs, ok := s.RootModule().Resources[n]
   352  		if !ok {
   353  			return fmt.Errorf("Not found: %s", n)
   354  		}
   355  
   356  		if rs.Primary.ID == "" {
   357  			return fmt.Errorf("No DB Instance ID is set")
   358  		}
   359  
   360  		conn := testAccProvider.Meta().(*AWSClient).rdsconn
   361  
   362  		opts := rds.DescribeDBInstancesInput{
   363  			DBInstanceIdentifier: aws.String(rs.Primary.ID),
   364  		}
   365  
   366  		resp, err := conn.DescribeDBInstances(&opts)
   367  
   368  		if err != nil {
   369  			return err
   370  		}
   371  
   372  		if len(resp.DBInstances) != 1 ||
   373  			*resp.DBInstances[0].DBInstanceIdentifier != rs.Primary.ID {
   374  			return fmt.Errorf("DB Instance not found")
   375  		}
   376  
   377  		*v = *resp.DBInstances[0]
   378  
   379  		return nil
   380  	}
   381  }
   382  
   383  // Database names cannot collide, and deletion takes so long, that making the
   384  // name a bit random helps so able we can kill a test that's just waiting for a
   385  // delete and not be blocked on kicking off another one.
   386  var testAccAWSDBInstanceConfig = `
   387  resource "aws_db_instance" "bar" {
   388  	allocated_storage = 10
   389  	engine = "MySQL"
   390  	engine_version = "5.6.21"
   391  	instance_class = "db.t1.micro"
   392  	name = "baz"
   393  	password = "barbarbarbar"
   394  	username = "foo"
   395  
   396  
   397  	# Maintenance Window is stored in lower case in the API, though not strictly 
   398  	# documented. Terraform will downcase this to match (as opposed to throw a 
   399  	# validation error).
   400  	maintenance_window = "Fri:09:00-Fri:09:30"
   401  
   402  	backup_retention_period = 0
   403  
   404  	parameter_group_name = "default.mysql5.6"
   405  }`
   406  
   407  var testAccAWSDBInstanceConfigWithOptionGroup = fmt.Sprintf(`
   408  
   409  resource "aws_db_option_group" "bar" {
   410  	name = "option-group-test-terraform"
   411  	option_group_description = "Test option group for terraform"
   412  	engine_name = "mysql"
   413  	major_engine_version = "5.6"
   414  }
   415  
   416  resource "aws_db_instance" "bar" {
   417  	identifier = "foobarbaz-test-terraform-%d"
   418  
   419  	allocated_storage = 10
   420  	engine = "MySQL"
   421  	instance_class = "db.m1.small"
   422  	name = "baz"
   423  	password = "barbarbarbar"
   424  	username = "foo"
   425  
   426  	backup_retention_period = 0
   427  
   428  	parameter_group_name = "default.mysql5.6"
   429  	option_group_name = "${aws_db_option_group.bar.name}"
   430  }`, acctest.RandInt())
   431  
   432  func testAccReplicaInstanceConfig(val int) string {
   433  	return fmt.Sprintf(`
   434  	resource "aws_db_instance" "bar" {
   435  		identifier = "foobarbaz-test-terraform-%d"
   436  
   437  		allocated_storage = 5
   438  		engine = "mysql"
   439  		engine_version = "5.6.21"
   440  		instance_class = "db.t1.micro"
   441  		name = "baz"
   442  		password = "barbarbarbar"
   443  		username = "foo"
   444  
   445  		backup_retention_period = 1
   446  
   447  		parameter_group_name = "default.mysql5.6"
   448  	}
   449  	
   450  	resource "aws_db_instance" "replica" {
   451  		identifier = "tf-replica-db-%d"
   452  		backup_retention_period = 0
   453  		replicate_source_db = "${aws_db_instance.bar.identifier}"
   454  		allocated_storage = "${aws_db_instance.bar.allocated_storage}"
   455  		engine = "${aws_db_instance.bar.engine}"
   456  		engine_version = "${aws_db_instance.bar.engine_version}"
   457  		instance_class = "${aws_db_instance.bar.instance_class}"
   458  		password = "${aws_db_instance.bar.password}"
   459  		username = "${aws_db_instance.bar.username}"
   460  		tags {
   461  			Name = "tf-replica-db"
   462  		}
   463  	}
   464  	`, val, val)
   465  }
   466  
   467  func testAccSnapshotInstanceConfig() string {
   468  	return fmt.Sprintf(`
   469  provider "aws" {
   470    region = "us-east-1"
   471  }
   472  resource "aws_db_instance" "snapshot" {
   473  	identifier = "tf-snapshot-%d"
   474  
   475  	allocated_storage = 5
   476  	engine = "mysql"
   477  	engine_version = "5.6.21"
   478  	instance_class = "db.t1.micro"
   479  	name = "baz"
   480  	password = "barbarbarbar"
   481  	username = "foo"
   482  	security_group_names = ["default"]
   483  	backup_retention_period = 1
   484  
   485  	parameter_group_name = "default.mysql5.6"
   486  
   487  	skip_final_snapshot = false
   488  	copy_tags_to_snapshot = true
   489  	final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-1"
   490  	tags {
   491  		Name = "tf-tags-db"
   492  	}
   493  }`, acctest.RandInt())
   494  }
   495  
   496  func testAccNoSnapshotInstanceConfig() string {
   497  	return fmt.Sprintf(`
   498  provider "aws" {
   499    region = "us-east-1"
   500  }
   501  resource "aws_db_instance" "no_snapshot" {
   502  	identifier = "tf-test-%s"
   503  
   504  	allocated_storage = 5
   505  	engine = "mysql"
   506  	engine_version = "5.6.21"
   507  	instance_class = "db.t1.micro"
   508  	name = "baz"
   509  	password = "barbarbarbar"
   510  	username = "foo"
   511      security_group_names = ["default"]
   512  	backup_retention_period = 1
   513  
   514  	parameter_group_name = "default.mysql5.6"
   515  
   516  	skip_final_snapshot = true
   517  	final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-2"
   518  }
   519  `, acctest.RandString(5))
   520  }
   521  
   522  var testAccSnapshotInstanceConfig_enhancedMonitoring = `
   523  resource "aws_iam_role" "enhanced_policy_role" {
   524      name = "enhanced-monitoring-role"
   525      assume_role_policy = <<EOF
   526  {
   527    "Version": "2012-10-17",
   528    "Statement": [
   529      {
   530        "Sid": "",
   531        "Effect": "Allow",
   532        "Principal": {
   533          "Service": "monitoring.rds.amazonaws.com"
   534        },
   535        "Action": "sts:AssumeRole"
   536      }
   537    ]
   538  }
   539  EOF
   540  
   541  }
   542  
   543  resource "aws_iam_policy_attachment" "test-attach" {
   544      name = "enhanced-monitoring-attachment"
   545      roles = [
   546          "${aws_iam_role.enhanced_policy_role.name}",
   547      ]
   548  
   549      policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
   550  }
   551  
   552  resource "aws_db_instance" "enhanced_monitoring" {
   553  	identifier = "foobarbaz-test-terraform-enhanced-monitoring"
   554  	depends_on = ["aws_iam_policy_attachment.test-attach"]
   555  
   556  	allocated_storage = 5
   557  	engine = "mysql"
   558  	engine_version = "5.6.21"
   559  	instance_class = "db.m3.medium"
   560  	name = "baz"
   561  	password = "barbarbarbar"
   562  	username = "foo"
   563  	backup_retention_period = 1
   564  
   565  	parameter_group_name = "default.mysql5.6"
   566  
   567  	monitoring_role_arn = "${aws_iam_role.enhanced_policy_role.arn}"
   568  	monitoring_interval = "5"
   569  
   570  	skip_final_snapshot = true
   571  }
   572  `