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