github.com/peterbale/terraform@v0.9.0-beta2.0.20170315142748-5723acd55547/builtin/providers/aws/resource_aws_db_instance_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"math/rand"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/hashicorp/terraform/helper/acctest"
    14  	"github.com/hashicorp/terraform/helper/resource"
    15  	"github.com/hashicorp/terraform/terraform"
    16  
    17  	"github.com/aws/aws-sdk-go/aws"
    18  	"github.com/aws/aws-sdk-go/aws/awserr"
    19  	"github.com/aws/aws-sdk-go/service/rds"
    20  )
    21  
    22  func TestAccAWSDBInstance_basic(t *testing.T) {
    23  	var v rds.DBInstance
    24  
    25  	resource.Test(t, resource.TestCase{
    26  		PreCheck:     func() { testAccPreCheck(t) },
    27  		Providers:    testAccProviders,
    28  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
    29  		Steps: []resource.TestStep{
    30  			{
    31  				Config: testAccAWSDBInstanceConfig,
    32  				Check: resource.ComposeTestCheckFunc(
    33  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
    34  					testAccCheckAWSDBInstanceAttributes(&v),
    35  					resource.TestCheckResourceAttr(
    36  						"aws_db_instance.bar", "allocated_storage", "10"),
    37  					resource.TestCheckResourceAttr(
    38  						"aws_db_instance.bar", "engine", "mysql"),
    39  					resource.TestCheckResourceAttr(
    40  						"aws_db_instance.bar", "license_model", "general-public-license"),
    41  					resource.TestCheckResourceAttr(
    42  						"aws_db_instance.bar", "instance_class", "db.t1.micro"),
    43  					resource.TestCheckResourceAttr(
    44  						"aws_db_instance.bar", "name", "baz"),
    45  					resource.TestCheckResourceAttr(
    46  						"aws_db_instance.bar", "username", "foo"),
    47  					resource.TestCheckResourceAttr(
    48  						"aws_db_instance.bar", "parameter_group_name", "default.mysql5.6"),
    49  					resource.TestCheckResourceAttrSet("aws_db_instance.bar", "hosted_zone_id"),
    50  				),
    51  			},
    52  		},
    53  	})
    54  }
    55  
    56  func TestAccAWSDBInstance_kmsKey(t *testing.T) {
    57  	var v rds.DBInstance
    58  	keyRegex := regexp.MustCompile("^arn:aws:kms:")
    59  
    60  	ri := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
    61  	config := fmt.Sprintf(testAccAWSDBInstanceConfigKmsKeyId, ri)
    62  
    63  	resource.Test(t, resource.TestCase{
    64  		PreCheck:     func() { testAccPreCheck(t) },
    65  		Providers:    testAccProviders,
    66  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
    67  		Steps: []resource.TestStep{
    68  			{
    69  				Config: config,
    70  				Check: resource.ComposeTestCheckFunc(
    71  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
    72  					testAccCheckAWSDBInstanceAttributes(&v),
    73  					resource.TestMatchResourceAttr(
    74  						"aws_db_instance.bar", "kms_key_id", keyRegex),
    75  				),
    76  			},
    77  		},
    78  	})
    79  }
    80  
    81  func TestAccAWSDBInstance_subnetGroup(t *testing.T) {
    82  	var v rds.DBInstance
    83  	rName := acctest.RandString(10)
    84  
    85  	resource.Test(t, resource.TestCase{
    86  		PreCheck:     func() { testAccPreCheck(t) },
    87  		Providers:    testAccProviders,
    88  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
    89  		Steps: []resource.TestStep{
    90  			{
    91  				Config: testAccAWSDBInstanceConfigWithSubnetGroup(rName),
    92  				Check: resource.ComposeTestCheckFunc(
    93  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
    94  					resource.TestCheckResourceAttr(
    95  						"aws_db_instance.bar", "db_subnet_group_name", "foo-"+rName),
    96  				),
    97  			},
    98  			{
    99  				Config: testAccAWSDBInstanceConfigWithSubnetGroupUpdated(rName),
   100  				Check: resource.ComposeTestCheckFunc(
   101  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   102  					resource.TestCheckResourceAttr(
   103  						"aws_db_instance.bar", "db_subnet_group_name", "bar-"+rName),
   104  				),
   105  			},
   106  		},
   107  	})
   108  }
   109  
   110  func TestAccAWSDBInstance_optionGroup(t *testing.T) {
   111  	var v rds.DBInstance
   112  
   113  	rName := fmt.Sprintf("tf-option-test-%d", acctest.RandInt())
   114  
   115  	resource.Test(t, resource.TestCase{
   116  		PreCheck:     func() { testAccPreCheck(t) },
   117  		Providers:    testAccProviders,
   118  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   119  		Steps: []resource.TestStep{
   120  			{
   121  				Config: testAccAWSDBInstanceConfigWithOptionGroup(rName),
   122  				Check: resource.ComposeTestCheckFunc(
   123  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   124  					testAccCheckAWSDBInstanceAttributes(&v),
   125  					resource.TestCheckResourceAttr(
   126  						"aws_db_instance.bar", "option_group_name", rName),
   127  				),
   128  			},
   129  		},
   130  	})
   131  }
   132  
   133  func TestAccAWSDBInstanceReplica(t *testing.T) {
   134  	var s, r rds.DBInstance
   135  
   136  	resource.Test(t, resource.TestCase{
   137  		PreCheck:     func() { testAccPreCheck(t) },
   138  		Providers:    testAccProviders,
   139  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   140  		Steps: []resource.TestStep{
   141  			{
   142  				Config: testAccReplicaInstanceConfig(rand.New(rand.NewSource(time.Now().UnixNano())).Int()),
   143  				Check: resource.ComposeTestCheckFunc(
   144  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &s),
   145  					testAccCheckAWSDBInstanceExists("aws_db_instance.replica", &r),
   146  					testAccCheckAWSDBInstanceReplicaAttributes(&s, &r),
   147  				),
   148  			},
   149  		},
   150  	})
   151  }
   152  
   153  func TestAccAWSDBInstanceNoSnapshot(t *testing.T) {
   154  	var snap rds.DBInstance
   155  
   156  	resource.Test(t, resource.TestCase{
   157  		PreCheck:     func() { testAccPreCheck(t) },
   158  		Providers:    testAccProviders,
   159  		CheckDestroy: testAccCheckAWSDBInstanceNoSnapshot,
   160  		Steps: []resource.TestStep{
   161  			{
   162  				Config: testAccSnapshotInstanceConfig(),
   163  				Check: resource.ComposeTestCheckFunc(
   164  					testAccCheckAWSDBInstanceExists("aws_db_instance.snapshot", &snap),
   165  				),
   166  			},
   167  		},
   168  	})
   169  }
   170  
   171  func TestAccAWSDBInstanceSnapshot(t *testing.T) {
   172  	var snap rds.DBInstance
   173  	rInt := acctest.RandInt()
   174  
   175  	resource.Test(t, resource.TestCase{
   176  		PreCheck:  func() { testAccPreCheck(t) },
   177  		Providers: testAccProviders,
   178  		// testAccCheckAWSDBInstanceSnapshot verifies a database snapshot is
   179  		// created, and subequently deletes it
   180  		CheckDestroy: testAccCheckAWSDBInstanceSnapshot(rInt),
   181  		Steps: []resource.TestStep{
   182  			{
   183  				Config: testAccSnapshotInstanceConfigWithSnapshot(rInt),
   184  				Check: resource.ComposeTestCheckFunc(
   185  					testAccCheckAWSDBInstanceExists("aws_db_instance.snapshot", &snap),
   186  				),
   187  			},
   188  		},
   189  	})
   190  }
   191  
   192  func TestAccAWSDBInstance_enhancedMonitoring(t *testing.T) {
   193  	var dbInstance rds.DBInstance
   194  	rName := acctest.RandString(5)
   195  
   196  	resource.Test(t, resource.TestCase{
   197  		PreCheck:     func() { testAccPreCheck(t) },
   198  		Providers:    testAccProviders,
   199  		CheckDestroy: testAccCheckAWSDBInstanceNoSnapshot,
   200  		Steps: []resource.TestStep{
   201  			{
   202  				Config: testAccSnapshotInstanceConfig_enhancedMonitoring(rName),
   203  				Check: resource.ComposeTestCheckFunc(
   204  					testAccCheckAWSDBInstanceExists("aws_db_instance.enhanced_monitoring", &dbInstance),
   205  					resource.TestCheckResourceAttr(
   206  						"aws_db_instance.enhanced_monitoring", "monitoring_interval", "5"),
   207  				),
   208  			},
   209  		},
   210  	})
   211  }
   212  
   213  // Regression test for https://github.com/hashicorp/terraform/issues/3760 .
   214  // We apply a plan, then change just the iops. If the apply succeeds, we
   215  // consider this a pass, as before in 3760 the request would fail
   216  func TestAccAWS_separate_DBInstance_iops_update(t *testing.T) {
   217  	var v rds.DBInstance
   218  
   219  	rName := acctest.RandString(5)
   220  
   221  	resource.Test(t, resource.TestCase{
   222  		PreCheck:     func() { testAccPreCheck(t) },
   223  		Providers:    testAccProviders,
   224  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   225  		Steps: []resource.TestStep{
   226  			{
   227  				Config: testAccSnapshotInstanceConfig_iopsUpdate(rName, 1000),
   228  				Check: resource.ComposeTestCheckFunc(
   229  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   230  					testAccCheckAWSDBInstanceAttributes(&v),
   231  				),
   232  			},
   233  
   234  			{
   235  				Config: testAccSnapshotInstanceConfig_iopsUpdate(rName, 2000),
   236  				Check: resource.ComposeTestCheckFunc(
   237  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   238  					testAccCheckAWSDBInstanceAttributes(&v),
   239  				),
   240  			},
   241  		},
   242  	})
   243  }
   244  
   245  func TestAccAWSDBInstance_portUpdate(t *testing.T) {
   246  	var v rds.DBInstance
   247  
   248  	rName := acctest.RandString(5)
   249  
   250  	resource.Test(t, resource.TestCase{
   251  		PreCheck:     func() { testAccPreCheck(t) },
   252  		Providers:    testAccProviders,
   253  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   254  		Steps: []resource.TestStep{
   255  			{
   256  				Config: testAccSnapshotInstanceConfig_mysqlPort(rName),
   257  				Check: resource.ComposeTestCheckFunc(
   258  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   259  					resource.TestCheckResourceAttr(
   260  						"aws_db_instance.bar", "port", "3306"),
   261  				),
   262  			},
   263  
   264  			{
   265  				Config: testAccSnapshotInstanceConfig_updateMysqlPort(rName),
   266  				Check: resource.ComposeTestCheckFunc(
   267  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   268  					resource.TestCheckResourceAttr(
   269  						"aws_db_instance.bar", "port", "3305"),
   270  				),
   271  			},
   272  		},
   273  	})
   274  }
   275  
   276  func TestAccAWSDBInstance_MSSQL_TZ(t *testing.T) {
   277  	var v rds.DBInstance
   278  
   279  	resource.Test(t, resource.TestCase{
   280  		PreCheck:     func() { testAccPreCheck(t) },
   281  		Providers:    testAccProviders,
   282  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   283  		Steps: []resource.TestStep{
   284  			{
   285  				Config: testAccAWSDBMSSQL_timezone,
   286  				Check: resource.ComposeTestCheckFunc(
   287  					testAccCheckAWSDBInstanceExists("aws_db_instance.mssql", &v),
   288  					testAccCheckAWSDBInstanceAttributes_MSSQL(&v, ""),
   289  					resource.TestCheckResourceAttr(
   290  						"aws_db_instance.mssql", "allocated_storage", "20"),
   291  					resource.TestCheckResourceAttr(
   292  						"aws_db_instance.mssql", "engine", "sqlserver-ex"),
   293  				),
   294  			},
   295  
   296  			{
   297  				Config: testAccAWSDBMSSQL_timezone_AKST,
   298  				Check: resource.ComposeTestCheckFunc(
   299  					testAccCheckAWSDBInstanceExists("aws_db_instance.mssql", &v),
   300  					testAccCheckAWSDBInstanceAttributes_MSSQL(&v, "Alaskan Standard Time"),
   301  					resource.TestCheckResourceAttr(
   302  						"aws_db_instance.mssql", "allocated_storage", "20"),
   303  					resource.TestCheckResourceAttr(
   304  						"aws_db_instance.mssql", "engine", "sqlserver-ex"),
   305  				),
   306  			},
   307  		},
   308  	})
   309  }
   310  
   311  func TestAccAWSDBInstance_MinorVersion(t *testing.T) {
   312  	var v rds.DBInstance
   313  
   314  	resource.Test(t, resource.TestCase{
   315  		PreCheck:     func() { testAccPreCheck(t) },
   316  		Providers:    testAccProviders,
   317  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   318  		Steps: []resource.TestStep{
   319  			{
   320  				Config: testAccAWSDBInstanceConfigAutoMinorVersion,
   321  				Check: resource.ComposeTestCheckFunc(
   322  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   323  				),
   324  			},
   325  		},
   326  	})
   327  }
   328  
   329  // See https://github.com/hashicorp/terraform/issues/11881
   330  func TestAccAWSDBInstance_diffSuppressInitialState(t *testing.T) {
   331  	var v rds.DBInstance
   332  	rInt := acctest.RandInt()
   333  
   334  	resource.Test(t, resource.TestCase{
   335  		PreCheck:     func() { testAccPreCheck(t) },
   336  		Providers:    testAccProviders,
   337  		CheckDestroy: testAccCheckAWSDBInstanceDestroy,
   338  		Steps: []resource.TestStep{
   339  			{
   340  				Config: testAccAWSDBInstanceConfigSuppressInitialState(rInt),
   341  				Check: resource.ComposeTestCheckFunc(
   342  					testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
   343  				),
   344  			},
   345  		},
   346  	})
   347  }
   348  
   349  func testAccCheckAWSDBInstanceDestroy(s *terraform.State) error {
   350  	conn := testAccProvider.Meta().(*AWSClient).rdsconn
   351  
   352  	for _, rs := range s.RootModule().Resources {
   353  		if rs.Type != "aws_db_instance" {
   354  			continue
   355  		}
   356  
   357  		// Try to find the Group
   358  		var err error
   359  		resp, err := conn.DescribeDBInstances(
   360  			&rds.DescribeDBInstancesInput{
   361  				DBInstanceIdentifier: aws.String(rs.Primary.ID),
   362  			})
   363  
   364  		if ae, ok := err.(awserr.Error); ok && ae.Code() == "DBInstanceNotFound" {
   365  			continue
   366  		}
   367  
   368  		if err == nil {
   369  			if len(resp.DBInstances) != 0 &&
   370  				*resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID {
   371  				return fmt.Errorf("DB Instance still exists")
   372  			}
   373  		}
   374  
   375  		// Verify the error
   376  		newerr, ok := err.(awserr.Error)
   377  		if !ok {
   378  			return err
   379  		}
   380  		if newerr.Code() != "DBInstanceNotFound" {
   381  			return err
   382  		}
   383  	}
   384  
   385  	return nil
   386  }
   387  
   388  func testAccCheckAWSDBInstanceAttributes(v *rds.DBInstance) resource.TestCheckFunc {
   389  	return func(s *terraform.State) error {
   390  
   391  		if *v.Engine != "mysql" {
   392  			return fmt.Errorf("bad engine: %#v", *v.Engine)
   393  		}
   394  
   395  		if *v.EngineVersion == "" {
   396  			return fmt.Errorf("bad engine_version: %#v", *v.EngineVersion)
   397  		}
   398  
   399  		if *v.BackupRetentionPeriod != 0 {
   400  			return fmt.Errorf("bad backup_retention_period: %#v", *v.BackupRetentionPeriod)
   401  		}
   402  
   403  		return nil
   404  	}
   405  }
   406  
   407  func testAccCheckAWSDBInstanceAttributes_MSSQL(v *rds.DBInstance, tz string) resource.TestCheckFunc {
   408  	return func(s *terraform.State) error {
   409  
   410  		if *v.Engine != "sqlserver-ex" {
   411  			return fmt.Errorf("bad engine: %#v", *v.Engine)
   412  		}
   413  
   414  		rtz := ""
   415  		if v.Timezone != nil {
   416  			rtz = *v.Timezone
   417  		}
   418  
   419  		if tz != rtz {
   420  			return fmt.Errorf("Expected (%s) Timezone for MSSQL test, got (%s)", tz, rtz)
   421  		}
   422  
   423  		return nil
   424  	}
   425  }
   426  
   427  func testAccCheckAWSDBInstanceReplicaAttributes(source, replica *rds.DBInstance) resource.TestCheckFunc {
   428  	return func(s *terraform.State) error {
   429  
   430  		if replica.ReadReplicaSourceDBInstanceIdentifier != nil && *replica.ReadReplicaSourceDBInstanceIdentifier != *source.DBInstanceIdentifier {
   431  			return fmt.Errorf("bad source identifier for replica, expected: '%s', got: '%s'", *source.DBInstanceIdentifier, *replica.ReadReplicaSourceDBInstanceIdentifier)
   432  		}
   433  
   434  		return nil
   435  	}
   436  }
   437  
   438  func testAccCheckAWSDBInstanceSnapshot(rInt int) resource.TestCheckFunc {
   439  	return func(s *terraform.State) error {
   440  		for _, rs := range s.RootModule().Resources {
   441  			if rs.Type != "aws_db_instance" {
   442  				continue
   443  			}
   444  
   445  			awsClient := testAccProvider.Meta().(*AWSClient)
   446  			conn := awsClient.rdsconn
   447  
   448  			var err error
   449  			log.Printf("[INFO] Trying to locate the DBInstance Final Snapshot")
   450  			snapshot_identifier := fmt.Sprintf("foobarbaz-test-terraform-final-snapshot-%d", rInt)
   451  			_, snapErr := conn.DescribeDBSnapshots(
   452  				&rds.DescribeDBSnapshotsInput{
   453  					DBSnapshotIdentifier: aws.String(snapshot_identifier),
   454  				})
   455  
   456  			if snapErr != nil {
   457  				newerr, _ := snapErr.(awserr.Error)
   458  				if newerr.Code() == "DBSnapshotNotFound" {
   459  					return fmt.Errorf("Snapshot %s not found", snapshot_identifier)
   460  				}
   461  			} else { // snapshot was found,
   462  				// verify we have the tags copied to the snapshot
   463  				instanceARN, err := buildRDSARN(snapshot_identifier, testAccProvider.Meta().(*AWSClient).partition, testAccProvider.Meta().(*AWSClient).accountid, testAccProvider.Meta().(*AWSClient).region)
   464  				// tags have a different ARN, just swapping :db: for :snapshot:
   465  				tagsARN := strings.Replace(instanceARN, ":db:", ":snapshot:", 1)
   466  				if err != nil {
   467  					return fmt.Errorf("Error building ARN for tags check with ARN (%s): %s", tagsARN, err)
   468  				}
   469  				resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{
   470  					ResourceName: aws.String(tagsARN),
   471  				})
   472  				if err != nil {
   473  					return fmt.Errorf("Error retrieving tags for ARN (%s): %s", tagsARN, err)
   474  				}
   475  
   476  				if resp.TagList == nil || len(resp.TagList) == 0 {
   477  					return fmt.Errorf("Tag list is nil or zero: %s", resp.TagList)
   478  				}
   479  
   480  				var found bool
   481  				for _, t := range resp.TagList {
   482  					if *t.Key == "Name" && *t.Value == "tf-tags-db" {
   483  						found = true
   484  					}
   485  				}
   486  				if !found {
   487  					return fmt.Errorf("Expected to find tag Name (%s), but wasn't found. Tags: %s", "tf-tags-db", resp.TagList)
   488  				}
   489  				// end tag search
   490  
   491  				log.Printf("[INFO] Deleting the Snapshot %s", snapshot_identifier)
   492  				_, snapDeleteErr := conn.DeleteDBSnapshot(
   493  					&rds.DeleteDBSnapshotInput{
   494  						DBSnapshotIdentifier: aws.String(snapshot_identifier),
   495  					})
   496  				if snapDeleteErr != nil {
   497  					return err
   498  				}
   499  			} // end snapshot was found
   500  
   501  			resp, err := conn.DescribeDBInstances(
   502  				&rds.DescribeDBInstancesInput{
   503  					DBInstanceIdentifier: aws.String(rs.Primary.ID),
   504  				})
   505  
   506  			if err != nil {
   507  				newerr, _ := err.(awserr.Error)
   508  				if newerr.Code() != "DBInstanceNotFound" {
   509  					return err
   510  				}
   511  
   512  			} else {
   513  				if len(resp.DBInstances) != 0 &&
   514  					*resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID {
   515  					return fmt.Errorf("DB Instance still exists")
   516  				}
   517  			}
   518  		}
   519  
   520  		return nil
   521  	}
   522  }
   523  
   524  func testAccCheckAWSDBInstanceNoSnapshot(s *terraform.State) error {
   525  	conn := testAccProvider.Meta().(*AWSClient).rdsconn
   526  
   527  	for _, rs := range s.RootModule().Resources {
   528  		if rs.Type != "aws_db_instance" {
   529  			continue
   530  		}
   531  
   532  		var err error
   533  		resp, err := conn.DescribeDBInstances(
   534  			&rds.DescribeDBInstancesInput{
   535  				DBInstanceIdentifier: aws.String(rs.Primary.ID),
   536  			})
   537  
   538  		if err != nil {
   539  			newerr, _ := err.(awserr.Error)
   540  			if newerr.Code() != "DBInstanceNotFound" {
   541  				return err
   542  			}
   543  
   544  		} else {
   545  			if len(resp.DBInstances) != 0 &&
   546  				*resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID {
   547  				return fmt.Errorf("DB Instance still exists")
   548  			}
   549  		}
   550  
   551  		snapshot_identifier := "foobarbaz-test-terraform-final-snapshot-2"
   552  		_, snapErr := conn.DescribeDBSnapshots(
   553  			&rds.DescribeDBSnapshotsInput{
   554  				DBSnapshotIdentifier: aws.String(snapshot_identifier),
   555  			})
   556  
   557  		if snapErr != nil {
   558  			newerr, _ := snapErr.(awserr.Error)
   559  			if newerr.Code() != "DBSnapshotNotFound" {
   560  				return fmt.Errorf("Snapshot %s found and it shouldn't have been", snapshot_identifier)
   561  			}
   562  		}
   563  	}
   564  
   565  	return nil
   566  }
   567  
   568  func testAccCheckAWSDBInstanceExists(n string, v *rds.DBInstance) resource.TestCheckFunc {
   569  	return func(s *terraform.State) error {
   570  		rs, ok := s.RootModule().Resources[n]
   571  		if !ok {
   572  			return fmt.Errorf("Not found: %s", n)
   573  		}
   574  
   575  		if rs.Primary.ID == "" {
   576  			return fmt.Errorf("No DB Instance ID is set")
   577  		}
   578  
   579  		conn := testAccProvider.Meta().(*AWSClient).rdsconn
   580  
   581  		opts := rds.DescribeDBInstancesInput{
   582  			DBInstanceIdentifier: aws.String(rs.Primary.ID),
   583  		}
   584  
   585  		resp, err := conn.DescribeDBInstances(&opts)
   586  
   587  		if err != nil {
   588  			return err
   589  		}
   590  
   591  		if len(resp.DBInstances) != 1 ||
   592  			*resp.DBInstances[0].DBInstanceIdentifier != rs.Primary.ID {
   593  			return fmt.Errorf("DB Instance not found")
   594  		}
   595  
   596  		*v = *resp.DBInstances[0]
   597  
   598  		return nil
   599  	}
   600  }
   601  
   602  // Database names cannot collide, and deletion takes so long, that making the
   603  // name a bit random helps so able we can kill a test that's just waiting for a
   604  // delete and not be blocked on kicking off another one.
   605  var testAccAWSDBInstanceConfig = `
   606  resource "aws_db_instance" "bar" {
   607  	allocated_storage = 10
   608  	engine = "MySQL"
   609  	engine_version = "5.6.21"
   610  	instance_class = "db.t1.micro"
   611  	name = "baz"
   612  	password = "barbarbarbar"
   613  	username = "foo"
   614  
   615  
   616  	# Maintenance Window is stored in lower case in the API, though not strictly 
   617  	# documented. Terraform will downcase this to match (as opposed to throw a 
   618  	# validation error).
   619  	maintenance_window = "Fri:09:00-Fri:09:30"
   620  	skip_final_snapshot = true
   621  
   622  	backup_retention_period = 0
   623  
   624  	parameter_group_name = "default.mysql5.6"
   625  
   626  	timeouts {
   627  		create = "30m"
   628  	}
   629  }`
   630  
   631  var testAccAWSDBInstanceConfigKmsKeyId = `
   632  resource "aws_kms_key" "foo" {
   633      description = "Terraform acc test %s"
   634      policy = <<POLICY
   635  {
   636    "Version": "2012-10-17",
   637    "Id": "kms-tf-1",
   638    "Statement": [
   639      {
   640        "Sid": "Enable IAM User Permissions",
   641        "Effect": "Allow",
   642        "Principal": {
   643          "AWS": "*"
   644        },
   645        "Action": "kms:*",
   646        "Resource": "*"
   647      }
   648    ]
   649  }
   650  POLICY
   651  }
   652  
   653  resource "aws_db_instance" "bar" {
   654  	allocated_storage = 10
   655  	engine = "MySQL"
   656  	engine_version = "5.6.21"
   657  	instance_class = "db.m3.medium"
   658  	name = "baz"
   659  	password = "barbarbarbar"
   660  	username = "foo"
   661  
   662  
   663  	# Maintenance Window is stored in lower case in the API, though not strictly
   664  	# documented. Terraform will downcase this to match (as opposed to throw a
   665  	# validation error).
   666  	maintenance_window = "Fri:09:00-Fri:09:30"
   667  
   668  	backup_retention_period = 0
   669  	storage_encrypted = true
   670  	kms_key_id = "${aws_kms_key.foo.arn}"
   671  
   672  	skip_final_snapshot = true
   673  
   674  	parameter_group_name = "default.mysql5.6"
   675  }
   676  `
   677  
   678  func testAccAWSDBInstanceConfigWithOptionGroup(rName string) string {
   679  	return fmt.Sprintf(`
   680  resource "aws_db_option_group" "bar" {
   681  	name = "%s"
   682  	option_group_description = "Test option group for terraform"
   683  	engine_name = "mysql"
   684  	major_engine_version = "5.6"
   685  }
   686  
   687  resource "aws_db_instance" "bar" {
   688  	identifier = "foobarbaz-test-terraform-%d"
   689  
   690  	allocated_storage = 10
   691  	engine = "MySQL"
   692  	instance_class = "db.m1.small"
   693  	name = "baz"
   694  	password = "barbarbarbar"
   695  	username = "foo"
   696  
   697  	backup_retention_period = 0
   698  	skip_final_snapshot = true
   699  
   700  	parameter_group_name = "default.mysql5.6"
   701  	option_group_name = "${aws_db_option_group.bar.name}"
   702  }`, rName, acctest.RandInt())
   703  }
   704  
   705  func testAccReplicaInstanceConfig(val int) string {
   706  	return fmt.Sprintf(`
   707  	resource "aws_db_instance" "bar" {
   708  		identifier = "foobarbaz-test-terraform-%d"
   709  
   710  		allocated_storage = 5
   711  		engine = "mysql"
   712  		engine_version = "5.6.21"
   713  		instance_class = "db.t1.micro"
   714  		name = "baz"
   715  		password = "barbarbarbar"
   716  		username = "foo"
   717  
   718  		backup_retention_period = 1
   719  		skip_final_snapshot = true
   720  
   721  		parameter_group_name = "default.mysql5.6"
   722  	}
   723  	
   724  	resource "aws_db_instance" "replica" {
   725  		identifier = "tf-replica-db-%d"
   726  		backup_retention_period = 0
   727  		replicate_source_db = "${aws_db_instance.bar.identifier}"
   728  		allocated_storage = "${aws_db_instance.bar.allocated_storage}"
   729  		engine = "${aws_db_instance.bar.engine}"
   730  		engine_version = "${aws_db_instance.bar.engine_version}"
   731  		instance_class = "${aws_db_instance.bar.instance_class}"
   732  		password = "${aws_db_instance.bar.password}"
   733  		username = "${aws_db_instance.bar.username}"
   734  		skip_final_snapshot = true
   735  		tags {
   736  			Name = "tf-replica-db"
   737  		}
   738  	}
   739  	`, val, val)
   740  }
   741  
   742  func testAccSnapshotInstanceConfig() string {
   743  	return fmt.Sprintf(`
   744  provider "aws" {
   745    region = "us-east-1"
   746  }
   747  resource "aws_db_instance" "snapshot" {
   748  	identifier = "tf-test-%d"
   749  
   750  	allocated_storage = 5
   751  	engine = "mysql"
   752  	engine_version = "5.6.21"
   753  	instance_class = "db.t1.micro"
   754  	name = "baz"
   755  	password = "barbarbarbar"
   756  	username = "foo"
   757  	security_group_names = ["default"]
   758  	backup_retention_period = 1
   759  
   760  	publicly_accessible = true
   761  
   762  	parameter_group_name = "default.mysql5.6"
   763  
   764  	skip_final_snapshot = true
   765  	final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-1"
   766  }`, acctest.RandInt())
   767  }
   768  
   769  func testAccSnapshotInstanceConfigWithSnapshot(rInt int) string {
   770  	return fmt.Sprintf(`
   771  provider "aws" {
   772    region = "us-east-1"
   773  }
   774  resource "aws_db_instance" "snapshot" {
   775  	identifier = "tf-snapshot-%d"
   776  
   777  	allocated_storage = 5
   778  	engine = "mysql"
   779  	engine_version = "5.6.21"
   780  	instance_class = "db.t1.micro"
   781  	name = "baz"
   782  	password = "barbarbarbar"
   783  	publicly_accessible = true
   784  	username = "foo"
   785      	security_group_names = ["default"]
   786  	backup_retention_period = 1
   787  
   788  	parameter_group_name = "default.mysql5.6"
   789  
   790  	copy_tags_to_snapshot = true
   791  	final_snapshot_identifier = "foobarbaz-test-terraform-final-snapshot-%d"
   792  	tags {
   793  		Name = "tf-tags-db"
   794  	}
   795  }
   796  `, rInt, rInt)
   797  }
   798  
   799  func testAccSnapshotInstanceConfig_enhancedMonitoring(rName string) string {
   800  	return fmt.Sprintf(`
   801  resource "aws_iam_role" "enhanced_policy_role" {
   802      name = "enhanced-monitoring-role-%s"
   803      assume_role_policy = <<EOF
   804  {
   805    "Version": "2012-10-17",
   806    "Statement": [
   807      {
   808        "Sid": "",
   809        "Effect": "Allow",
   810        "Principal": {
   811          "Service": "monitoring.rds.amazonaws.com"
   812        },
   813        "Action": "sts:AssumeRole"
   814      }
   815    ]
   816  }
   817  EOF
   818  
   819  }
   820  
   821  resource "aws_iam_policy_attachment" "test-attach" {
   822      name = "enhanced-monitoring-attachment"
   823      roles = [
   824          "${aws_iam_role.enhanced_policy_role.name}",
   825      ]
   826  
   827      policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
   828  }
   829  
   830  resource "aws_db_instance" "enhanced_monitoring" {
   831  	identifier = "foobarbaz-enhanced-monitoring-%s"
   832  	depends_on = ["aws_iam_policy_attachment.test-attach"]
   833  
   834  	allocated_storage = 5
   835  	engine = "mysql"
   836  	engine_version = "5.6.21"
   837  	instance_class = "db.m3.medium"
   838  	name = "baz"
   839  	password = "barbarbarbar"
   840  	username = "foo"
   841  	backup_retention_period = 1
   842  
   843  	parameter_group_name = "default.mysql5.6"
   844  
   845  	monitoring_role_arn = "${aws_iam_role.enhanced_policy_role.arn}"
   846  	monitoring_interval = "5"
   847  
   848  	skip_final_snapshot = true
   849  }`, rName, rName)
   850  }
   851  
   852  func testAccSnapshotInstanceConfig_iopsUpdate(rName string, iops int) string {
   853  	return fmt.Sprintf(`
   854  resource "aws_db_instance" "bar" {
   855    identifier           = "mydb-rds-%s"
   856    engine               = "mysql"
   857    engine_version       = "5.6.23"
   858    instance_class       = "db.t2.micro"
   859    name                 = "mydb"
   860    username             = "foo"
   861    password             = "barbarbar"
   862    parameter_group_name = "default.mysql5.6"
   863    skip_final_snapshot = true
   864  
   865    apply_immediately = true
   866  
   867    storage_type      = "io1"
   868    allocated_storage = 200
   869    iops              = %d
   870  }`, rName, iops)
   871  }
   872  
   873  func testAccSnapshotInstanceConfig_mysqlPort(rName string) string {
   874  	return fmt.Sprintf(`
   875  resource "aws_db_instance" "bar" {
   876    identifier           = "mydb-rds-%s"
   877    engine               = "mysql"
   878    engine_version       = "5.6.23"
   879    instance_class       = "db.t2.micro"
   880    name                 = "mydb"
   881    username             = "foo"
   882    password             = "barbarbar"
   883    parameter_group_name = "default.mysql5.6"
   884    port = 3306
   885    allocated_storage = 10
   886    skip_final_snapshot = true
   887  
   888    apply_immediately = true
   889  }`, rName)
   890  }
   891  
   892  func testAccSnapshotInstanceConfig_updateMysqlPort(rName string) string {
   893  	return fmt.Sprintf(`
   894  resource "aws_db_instance" "bar" {
   895    identifier           = "mydb-rds-%s"
   896    engine               = "mysql"
   897    engine_version       = "5.6.23"
   898    instance_class       = "db.t2.micro"
   899    name                 = "mydb"
   900    username             = "foo"
   901    password             = "barbarbar"
   902    parameter_group_name = "default.mysql5.6"
   903    port = 3305
   904    allocated_storage = 10
   905    skip_final_snapshot = true
   906  
   907    apply_immediately = true
   908  }`, rName)
   909  }
   910  
   911  func testAccAWSDBInstanceConfigWithSubnetGroup(rName string) string {
   912  	return fmt.Sprintf(`
   913  resource "aws_vpc" "foo" {
   914  	cidr_block = "10.1.0.0/16"
   915  }
   916  
   917  resource "aws_subnet" "foo" {
   918  	cidr_block = "10.1.1.0/24"
   919  	availability_zone = "us-west-2a"
   920  	vpc_id = "${aws_vpc.foo.id}"
   921  	tags {
   922  		Name = "tf-dbsubnet-test-1"
   923  	}
   924  }
   925  
   926  resource "aws_subnet" "bar" {
   927  	cidr_block = "10.1.2.0/24"
   928  	availability_zone = "us-west-2b"
   929  	vpc_id = "${aws_vpc.foo.id}"
   930  	tags {
   931  		Name = "tf-dbsubnet-test-2"
   932  	}
   933  }
   934  
   935  resource "aws_db_subnet_group" "foo" {
   936  	name = "foo-%s"
   937  	subnet_ids = ["${aws_subnet.foo.id}", "${aws_subnet.bar.id}"]
   938  	tags {
   939  		Name = "tf-dbsubnet-group-test"
   940  	}
   941  }
   942  
   943  resource "aws_db_instance" "bar" {
   944    identifier           = "mydb-rds-%s"
   945    engine               = "mysql"
   946    engine_version       = "5.6.23"
   947    instance_class       = "db.t2.micro"
   948    name                 = "mydb"
   949    username             = "foo"
   950    password             = "barbarbar"
   951    parameter_group_name = "default.mysql5.6"
   952    db_subnet_group_name = "${aws_db_subnet_group.foo.name}"
   953    port = 3305
   954    allocated_storage = 10
   955    skip_final_snapshot = true
   956  
   957  	backup_retention_period = 0
   958    apply_immediately = true
   959  }`, rName, rName)
   960  }
   961  
   962  func testAccAWSDBInstanceConfigWithSubnetGroupUpdated(rName string) string {
   963  	return fmt.Sprintf(`
   964  resource "aws_vpc" "foo" {
   965  	cidr_block = "10.1.0.0/16"
   966  }
   967  
   968  resource "aws_vpc" "bar" {
   969  	cidr_block = "10.10.0.0/16"
   970  }
   971  
   972  resource "aws_subnet" "foo" {
   973  	cidr_block = "10.1.1.0/24"
   974  	availability_zone = "us-west-2a"
   975  	vpc_id = "${aws_vpc.foo.id}"
   976  	tags {
   977  		Name = "tf-dbsubnet-test-1"
   978  	}
   979  }
   980  
   981  resource "aws_subnet" "bar" {
   982  	cidr_block = "10.1.2.0/24"
   983  	availability_zone = "us-west-2b"
   984  	vpc_id = "${aws_vpc.foo.id}"
   985  	tags {
   986  		Name = "tf-dbsubnet-test-2"
   987  	}
   988  }
   989  
   990  resource "aws_subnet" "test" {
   991  	cidr_block = "10.10.3.0/24"
   992  	availability_zone = "us-west-2b"
   993  	vpc_id = "${aws_vpc.bar.id}"
   994  	tags {
   995  		Name = "tf-dbsubnet-test-3"
   996  	}
   997  }
   998  
   999  resource "aws_subnet" "another_test" {
  1000  	cidr_block = "10.10.4.0/24"
  1001  	availability_zone = "us-west-2a"
  1002  	vpc_id = "${aws_vpc.bar.id}"
  1003  	tags {
  1004  		Name = "tf-dbsubnet-test-4"
  1005  	}
  1006  }
  1007  
  1008  resource "aws_db_subnet_group" "foo" {
  1009  	name = "foo-%s"
  1010  	subnet_ids = ["${aws_subnet.foo.id}", "${aws_subnet.bar.id}"]
  1011  	tags {
  1012  		Name = "tf-dbsubnet-group-test"
  1013  	}
  1014  }
  1015  
  1016  resource "aws_db_subnet_group" "bar" {
  1017  	name = "bar-%s"
  1018  	subnet_ids = ["${aws_subnet.test.id}", "${aws_subnet.another_test.id}"]
  1019  	tags {
  1020  		Name = "tf-dbsubnet-group-test-updated"
  1021  	}
  1022  }
  1023  
  1024  resource "aws_db_instance" "bar" {
  1025    identifier           = "mydb-rds-%s"
  1026    engine               = "mysql"
  1027    engine_version       = "5.6.23"
  1028    instance_class       = "db.t2.micro"
  1029    name                 = "mydb"
  1030    username             = "foo"
  1031    password             = "barbarbar"
  1032    parameter_group_name = "default.mysql5.6"
  1033    db_subnet_group_name = "${aws_db_subnet_group.bar.name}"
  1034    port = 3305
  1035    allocated_storage = 10
  1036    skip_final_snapshot = true
  1037  
  1038  	backup_retention_period = 0
  1039  
  1040    apply_immediately = true
  1041  }`, rName, rName, rName)
  1042  }
  1043  
  1044  const testAccAWSDBMSSQL_timezone = `
  1045  provider "aws" {
  1046    region = "us-west-2"
  1047  }
  1048  
  1049  resource "aws_vpc" "foo" {
  1050    cidr_block           = "10.1.0.0/16"
  1051    enable_dns_hostnames = true
  1052  	tags {
  1053  		Name = "tf-rds-mssql-timezone-test"
  1054  	}
  1055  }
  1056  
  1057  resource "aws_db_subnet_group" "rds_one" {
  1058    name        = "rds_one_db"
  1059    description = "db subnets for rds_one"
  1060  
  1061    subnet_ids = ["${aws_subnet.main.id}", "${aws_subnet.other.id}"]
  1062  }
  1063  
  1064  resource "aws_subnet" "main" {
  1065    vpc_id            = "${aws_vpc.foo.id}"
  1066    availability_zone = "us-west-2a"
  1067    cidr_block        = "10.1.1.0/24"
  1068  }
  1069  
  1070  resource "aws_subnet" "other" {
  1071    vpc_id            = "${aws_vpc.foo.id}"
  1072    availability_zone = "us-west-2b"
  1073    cidr_block        = "10.1.2.0/24"
  1074  }
  1075  
  1076  resource "aws_db_instance" "mssql" {
  1077    #identifier = "tf-test-mssql"
  1078  
  1079    db_subnet_group_name = "${aws_db_subnet_group.rds_one.name}"
  1080  
  1081    instance_class          = "db.t2.micro"
  1082    allocated_storage       = 20
  1083    username                = "somecrazyusername"
  1084    password                = "somecrazypassword"
  1085    engine                  = "sqlserver-ex"
  1086    backup_retention_period = 0
  1087    skip_final_snapshot = true
  1088  
  1089    #publicly_accessible = true
  1090  
  1091    vpc_security_group_ids = ["${aws_security_group.rds-mssql.id}"]
  1092  }
  1093  
  1094  resource "aws_security_group" "rds-mssql" {
  1095    name = "tf-rds-mssql-test"
  1096  
  1097    description = "TF Testing"
  1098    vpc_id      = "${aws_vpc.foo.id}"
  1099  }
  1100  
  1101  resource "aws_security_group_rule" "rds-mssql-1" {
  1102    type        = "egress"
  1103    from_port   = 0
  1104    to_port     = 0
  1105    protocol    = "-1"
  1106    cidr_blocks = ["0.0.0.0/0"]
  1107  
  1108    security_group_id = "${aws_security_group.rds-mssql.id}"
  1109  }
  1110  `
  1111  
  1112  const testAccAWSDBMSSQL_timezone_AKST = `
  1113  provider "aws" {
  1114    region = "us-west-2"
  1115  }
  1116  
  1117  resource "aws_vpc" "foo" {
  1118    cidr_block           = "10.1.0.0/16"
  1119    enable_dns_hostnames = true
  1120  	tags {
  1121  		Name = "tf-rds-mssql-timezone-test"
  1122  	}
  1123  }
  1124  
  1125  resource "aws_db_subnet_group" "rds_one" {
  1126    name        = "rds_one_db"
  1127    description = "db subnets for rds_one"
  1128  
  1129    subnet_ids = ["${aws_subnet.main.id}", "${aws_subnet.other.id}"]
  1130  }
  1131  
  1132  resource "aws_subnet" "main" {
  1133    vpc_id            = "${aws_vpc.foo.id}"
  1134    availability_zone = "us-west-2a"
  1135    cidr_block        = "10.1.1.0/24"
  1136  }
  1137  
  1138  resource "aws_subnet" "other" {
  1139    vpc_id            = "${aws_vpc.foo.id}"
  1140    availability_zone = "us-west-2b"
  1141    cidr_block        = "10.1.2.0/24"
  1142  }
  1143  
  1144  resource "aws_db_instance" "mssql" {
  1145    #identifier = "tf-test-mssql"
  1146  
  1147    db_subnet_group_name = "${aws_db_subnet_group.rds_one.name}"
  1148  
  1149    instance_class          = "db.t2.micro"
  1150    allocated_storage       = 20
  1151    username                = "somecrazyusername"
  1152    password                = "somecrazypassword"
  1153    engine                  = "sqlserver-ex"
  1154    backup_retention_period = 0
  1155    skip_final_snapshot = true
  1156  
  1157    #publicly_accessible = true
  1158  
  1159    vpc_security_group_ids = ["${aws_security_group.rds-mssql.id}"]
  1160    timezone               = "Alaskan Standard Time"
  1161  }
  1162  
  1163  resource "aws_security_group" "rds-mssql" {
  1164    name = "tf-rds-mssql-test"
  1165  
  1166    description = "TF Testing"
  1167    vpc_id      = "${aws_vpc.foo.id}"
  1168  }
  1169  
  1170  resource "aws_security_group_rule" "rds-mssql-1" {
  1171    type        = "egress"
  1172    from_port   = 0
  1173    to_port     = 0
  1174    protocol    = "-1"
  1175    cidr_blocks = ["0.0.0.0/0"]
  1176  
  1177    security_group_id = "${aws_security_group.rds-mssql.id}"
  1178  }
  1179  `
  1180  
  1181  var testAccAWSDBInstanceConfigAutoMinorVersion = fmt.Sprintf(`
  1182  resource "aws_db_instance" "bar" {
  1183    identifier = "foobarbaz-test-terraform-%d"
  1184  	allocated_storage = 10
  1185  	engine = "MySQL"
  1186  	engine_version = "5.6"
  1187  	instance_class = "db.t1.micro"
  1188  	name = "baz"
  1189  	password = "barbarbarbar"
  1190  	username = "foo"
  1191  	skip_final_snapshot = true
  1192  }
  1193  `, acctest.RandInt())
  1194  
  1195  func testAccAWSDBInstanceConfigSuppressInitialState(rInt int) string {
  1196  	return fmt.Sprintf(`
  1197  resource "aws_db_instance" "bar" {
  1198    identifier = "foobarbaz-test-terraform-%d"
  1199  	allocated_storage = 10
  1200  	engine = "MySQL"
  1201  	instance_class = "db.t1.micro"
  1202  	name = "baz"
  1203  	password = "barbarbarbar"
  1204  	username = "foo"
  1205  	skip_final_snapshot = true
  1206  }
  1207  
  1208  data "template_file" "test" {
  1209    template = ""
  1210    vars = {
  1211      test_var = "${aws_db_instance.bar.engine_version}"
  1212    }
  1213  }
  1214  `, rInt)
  1215  }