package aws import ( "fmt" "log" "reflect" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/emr" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" ) func TestAccAWSEMRCluster_basic(t *testing.T) { var cluster emr.Cluster r := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ { Config: testAccAWSEmrClusterConfig(r), Check: testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), }, }, }) } func TestAccAWSEMRCluster_security_config(t *testing.T) { var cluster emr.Cluster r := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ { Config: testAccAWSEmrClusterConfig_SecurityConfiguration(r), Check: testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), }, }, }) } func TestAccAWSEMRCluster_bootstrap_ordering(t *testing.T) { var cluster emr.Cluster rName := acctest.RandomWithPrefix("tf-emr-bootstrap") argsInts := []string{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", } argsStrings := []string{ "instance.isMaster=true", "echo running on master node", } resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ { Config: testAccAWSEmrClusterConfig_bootstrap(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.test", &cluster), testAccCheck_bootstrap_order(&cluster, argsInts, argsStrings), ), }, }, }) } func TestAccAWSEMRCluster_terminationProtected(t *testing.T) { var cluster emr.Cluster r := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ { Config: testAccAWSEmrClusterConfig(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "termination_protection", "false"), ), }, { Config: testAccAWSEmrClusterConfigTerminationPolicyUpdated(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "termination_protection", "true"), ), }, { //Need to turn off termination_protection to allow the job to be deleted Config: testAccAWSEmrClusterConfig(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), ), }, }, }) } func TestAccAWSEMRCluster_visibleToAllUsers(t *testing.T) { var cluster emr.Cluster r := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ { Config: testAccAWSEmrClusterConfig(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "visible_to_all_users", "true"), ), }, { Config: testAccAWSEmrClusterConfigVisibleToAllUsersUpdated(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "visible_to_all_users", "false"), ), }, }, }) } func TestAccAWSEMRCluster_tags(t *testing.T) { var cluster emr.Cluster r := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ { Config: testAccAWSEmrClusterConfig(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), resource.TestCheckResourceAttr("aws_emr_cluster.tf-test-cluster", "tags.%", "4"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.role", "rolename"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.dns_zone", "env_zone"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.env", "env"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.name", "name-env")), }, { Config: testAccAWSEmrClusterConfigUpdatedTags(r), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &cluster), resource.TestCheckResourceAttr("aws_emr_cluster.tf-test-cluster", "tags.%", "3"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.dns_zone", "new_zone"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.Env", "production"), resource.TestCheckResourceAttr( "aws_emr_cluster.tf-test-cluster", "tags.name", "name-env"), ), }, }, }) } func testAccCheck_bootstrap_order(cluster *emr.Cluster, argsInts, argsStrings []string) resource.TestCheckFunc { return func(s *terraform.State) error { emrconn := testAccProvider.Meta().(*AWSClient).emrconn req := emr.ListBootstrapActionsInput{ ClusterId: cluster.Id, } resp, err := emrconn.ListBootstrapActions(&req) if err != nil { return fmt.Errorf("[ERR] Error listing boostrap actions in test: %s", err) } // make sure we actually checked something var ran bool for _, ba := range resp.BootstrapActions { // assume name matches the config rArgs := aws.StringValueSlice(ba.Args) if *ba.Name == "test" { ran = true if !reflect.DeepEqual(argsInts, rArgs) { return fmt.Errorf("Error matching Bootstrap args:\n\texpected: %#v\n\tgot: %#v", argsInts, rArgs) } } else if *ba.Name == "runif" { ran = true if !reflect.DeepEqual(argsStrings, rArgs) { return fmt.Errorf("Error matching Bootstrap args:\n\texpected: %#v\n\tgot: %#v", argsStrings, rArgs) } } } if !ran { return fmt.Errorf("Expected to compare bootstrap actions, but no checks were ran") } return nil } } func testAccCheckAWSEmrDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).emrconn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_emr_cluster" { continue } params := &emr.DescribeClusterInput{ ClusterId: aws.String(rs.Primary.ID), } describe, err := conn.DescribeCluster(params) if err == nil { if describe.Cluster != nil && *describe.Cluster.Status.State == "WAITING" { return fmt.Errorf("EMR Cluster still exists") } } providerErr, ok := err.(awserr.Error) if !ok { return err } log.Printf("[ERROR] %v", providerErr) } return nil } func testAccCheckAWSEmrClusterExists(n string, v *emr.Cluster) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { return fmt.Errorf("No cluster id set") } conn := testAccProvider.Meta().(*AWSClient).emrconn describe, err := conn.DescribeCluster(&emr.DescribeClusterInput{ ClusterId: aws.String(rs.Primary.ID), }) if err != nil { return fmt.Errorf("EMR error: %v", err) } if describe.Cluster != nil && *describe.Cluster.Id != rs.Primary.ID { return fmt.Errorf("EMR cluser not found") } *v = *describe.Cluster if describe.Cluster != nil && *describe.Cluster.Status.State != "WAITING" { return fmt.Errorf("EMR cluser is not up yet") } return nil } } func testAccAWSEmrClusterConfig_bootstrap(r string) string { return fmt.Sprintf(` resource "aws_emr_cluster" "test" { count = 1 name = "%s" release_label = "emr-5.0.0" applications = ["Hadoop", "Hive"] log_uri = "s3n://terraform/testlog/" master_instance_type = "m4.large" core_instance_type = "m1.small" core_instance_count = 1 service_role = "${aws_iam_role.iam_emr_default_role.arn}" depends_on = ["aws_main_route_table_association.a"] ec2_attributes { subnet_id = "${aws_subnet.main.id}" emr_managed_master_security_group = "${aws_security_group.allow_all.id}" emr_managed_slave_security_group = "${aws_security_group.allow_all.id}" instance_profile = "${aws_iam_instance_profile.emr_profile.arn}" } bootstrap_action { path = "s3://elasticmapreduce/bootstrap-actions/run-if" name = "runif" args = ["instance.isMaster=true", "echo running on master node"] } bootstrap_action = [ { path = "s3://${aws_s3_bucket.tester.bucket}/testscript.sh" name = "test" args = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", ] }, ] } resource "aws_iam_instance_profile" "emr_profile" { name = "%s_profile" role = "${aws_iam_role.iam_emr_profile_role.name}" } resource "aws_iam_role" "iam_emr_default_role" { name = "%s_default_role" assume_role_policy = <