From 8ff44d0056b8a6dbc26a0b21fa36f29373b715c2 Mon Sep 17 00:00:00 2001 From: Paul Stack Date: Tue, 3 Jan 2017 22:15:44 +0000 Subject: [PATCH] provider:aws: Add support for updating aws_emr_cluster parameters (#11008) * provider:aws: Add support for updating aws_emr_cluster parameters Fixes #10962 We now support the update of `visibile_to_add_users` and `termination_protected` parameters ``` make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSEMRCluster_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/01/03 18:45:20 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSEMRCluster_ -timeout 120m === RUN TestAccAWSEMRCluster_basic --- PASS: TestAccAWSEMRCluster_basic (551.98s) === RUN TestAccAWSEMRCluster_terminationProtected --- PASS: TestAccAWSEMRCluster_terminationProtected (545.52s) === RUN TestAccAWSEMRCluster_visibleToAllUsers --- PASS: TestAccAWSEMRCluster_visibleToAllUsers (552.09s) === RUN TestAccAWSEMRCluster_tags --- PASS: TestAccAWSEMRCluster_tags (598.91s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 2248.537s ``` * Update resource_aws_emr_cluster_test.go --- .../providers/aws/resource_aws_emr_cluster.go | 88 ++- .../aws/resource_aws_emr_cluster_test.go | 631 +++++++++++++++++- 2 files changed, 685 insertions(+), 34 deletions(-) diff --git a/builtin/providers/aws/resource_aws_emr_cluster.go b/builtin/providers/aws/resource_aws_emr_cluster.go index 6464f12ed..3017e1087 100644 --- a/builtin/providers/aws/resource_aws_emr_cluster.go +++ b/builtin/providers/aws/resource_aws_emr_cluster.go @@ -24,121 +24,120 @@ func resourceAwsEMRCluster() *schema.Resource { Update: resourceAwsEMRClusterUpdate, Delete: resourceAwsEMRClusterDelete, Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, ForceNew: true, Required: true, }, - "release_label": &schema.Schema{ + "release_label": { Type: schema.TypeString, ForceNew: true, Required: true, }, - "master_instance_type": &schema.Schema{ + "master_instance_type": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "core_instance_type": &schema.Schema{ + "core_instance_type": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: true, }, - "core_instance_count": &schema.Schema{ + "core_instance_count": { Type: schema.TypeInt, Optional: true, Default: 1, }, - "cluster_state": &schema.Schema{ + "cluster_state": { Type: schema.TypeString, Computed: true, }, - "log_uri": &schema.Schema{ + "log_uri": { Type: schema.TypeString, ForceNew: true, Optional: true, }, - "master_public_dns": &schema.Schema{ + "master_public_dns": { Type: schema.TypeString, Computed: true, }, - "applications": &schema.Schema{ + "applications": { Type: schema.TypeSet, Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "termination_protection": &schema.Schema{ + "termination_protection": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "keep_job_flow_alive_when_no_steps": { Type: schema.TypeBool, ForceNew: true, Optional: true, Computed: true, }, - "keep_job_flow_alive_when_no_steps": &schema.Schema{ - Type: schema.TypeBool, - ForceNew: true, - Optional: true, - Computed: true, - }, - "ec2_attributes": &schema.Schema{ + "ec2_attributes": { Type: schema.TypeList, MaxItems: 1, Optional: true, ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "key_name": &schema.Schema{ + "key_name": { Type: schema.TypeString, Optional: true, }, - "subnet_id": &schema.Schema{ + "subnet_id": { Type: schema.TypeString, Optional: true, }, - "additional_master_security_groups": &schema.Schema{ + "additional_master_security_groups": { Type: schema.TypeString, Optional: true, }, - "additional_slave_security_groups": &schema.Schema{ + "additional_slave_security_groups": { Type: schema.TypeString, Optional: true, }, - "emr_managed_master_security_group": &schema.Schema{ + "emr_managed_master_security_group": { Type: schema.TypeString, Optional: true, }, - "emr_managed_slave_security_group": &schema.Schema{ + "emr_managed_slave_security_group": { Type: schema.TypeString, Optional: true, }, - "instance_profile": &schema.Schema{ + "instance_profile": { Type: schema.TypeString, Required: true, }, - "service_access_security_group": &schema.Schema{ + "service_access_security_group": { Type: schema.TypeString, Optional: true, }, }, }, }, - "bootstrap_action": &schema.Schema{ + "bootstrap_action": { Type: schema.TypeSet, Optional: true, ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, }, - "path": &schema.Schema{ + "path": { Type: schema.TypeString, Required: true, }, - "args": &schema.Schema{ + "args": { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -148,20 +147,19 @@ func resourceAwsEMRCluster() *schema.Resource { }, }, "tags": tagsSchema(), - "configurations": &schema.Schema{ + "configurations": { Type: schema.TypeString, ForceNew: true, Optional: true, }, - "service_role": &schema.Schema{ + "service_role": { Type: schema.TypeString, ForceNew: true, Required: true, }, - "visible_to_all_users": &schema.Schema{ + "visible_to_all_users": { Type: schema.TypeBool, Optional: true, - ForceNew: true, Default: true, }, }, @@ -430,6 +428,30 @@ func resourceAwsEMRClusterUpdate(d *schema.ResourceData, meta interface{}) error } } + if d.HasChange("visible_to_all_users") { + d.SetPartial("visible_to_all_users") + _, errModify := conn.SetVisibleToAllUsers(&emr.SetVisibleToAllUsersInput{ + JobFlowIds: []*string{aws.String(d.Id())}, + VisibleToAllUsers: aws.Bool(d.Get("visible_to_all_users").(bool)), + }) + if errModify != nil { + log.Printf("[ERROR] %s", errModify) + return errModify + } + } + + if d.HasChange("termination_protection") { + d.SetPartial("termination_protection") + _, errModify := conn.SetTerminationProtection(&emr.SetTerminationProtectionInput{ + JobFlowIds: []*string{aws.String(d.Id())}, + TerminationProtected: aws.Bool(d.Get("termination_protection").(bool)), + }) + if errModify != nil { + log.Printf("[ERROR] %s", errModify) + return errModify + } + } + if err := setTagsEMR(conn, d); err != nil { return err } else { diff --git a/builtin/providers/aws/resource_aws_emr_cluster_test.go b/builtin/providers/aws/resource_aws_emr_cluster_test.go index 0521bf1de..ad8b16a1f 100644 --- a/builtin/providers/aws/resource_aws_emr_cluster_test.go +++ b/builtin/providers/aws/resource_aws_emr_cluster_test.go @@ -21,7 +21,7 @@ func TestAccAWSEMRCluster_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSEmrDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSEmrClusterConfig(r), Check: testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &jobFlow), }, @@ -29,6 +29,69 @@ func TestAccAWSEMRCluster_basic(t *testing.T) { }) } +func TestAccAWSEMRCluster_terminationProtected(t *testing.T) { + var jobFlow emr.RunJobFlowOutput + 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", &jobFlow), + resource.TestCheckResourceAttr( + "aws_emr_cluster.tf-test-cluster", "termination_protection", "false"), + ), + }, + { + Config: testAccAWSEmrClusterConfigTerminationPolicyUpdated(r), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEmrClusterExists("aws_emr_cluster.tf-test-cluster", &jobFlow), + 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", &jobFlow), + ), + }, + }, + }) +} + +func TestAccAWSEMRCluster_visibleToAllUsers(t *testing.T) { + var jobFlow emr.RunJobFlowOutput + 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", &jobFlow), + 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", &jobFlow), + resource.TestCheckResourceAttr( + "aws_emr_cluster.tf-test-cluster", "visible_to_all_users", "false"), + ), + }, + }, + }) +} + func TestAccAWSEMRCluster_tags(t *testing.T) { var jobFlow emr.RunJobFlowOutput r := acctest.RandInt() @@ -414,6 +477,572 @@ EOT `, r, r, r, r, r, r) } +func testAccAWSEmrClusterConfigTerminationPolicyUpdated(r int) string { + return fmt.Sprintf(` +provider "aws" { + region = "us-west-2" +} + +resource "aws_emr_cluster" "tf-test-cluster" { + name = "emr-test-%d" + release_label = "emr-4.6.0" + applications = ["Spark"] + + 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}" + } + + master_instance_type = "m3.xlarge" + core_instance_type = "m3.xlarge" + core_instance_count = 1 + + tags { + role = "rolename" + dns_zone = "env_zone" + env = "env" + name = "name-env" + } + + keep_job_flow_alive_when_no_steps = true + termination_protection = true + + bootstrap_action { + path = "s3://elasticmapreduce/bootstrap-actions/run-if" + name = "runif" + args = ["instance.isMaster=true", "echo running on master node"] + } + + configurations = "test-fixtures/emr_configurations.json" + + depends_on = ["aws_main_route_table_association.a"] + + service_role = "${aws_iam_role.iam_emr_default_role.arn}" +} + +resource "aws_security_group" "allow_all" { + name = "allow_all" + description = "Allow all inbound traffic" + vpc_id = "${aws_vpc.main.id}" + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + depends_on = ["aws_subnet.main"] + + lifecycle { + ignore_changes = ["ingress", "egress"] + } + + tags { + name = "emr_test" + } +} + +resource "aws_vpc" "main" { + cidr_block = "168.31.0.0/16" + enable_dns_hostnames = true + + tags { + name = "emr_test" + } +} + +resource "aws_subnet" "main" { + vpc_id = "${aws_vpc.main.id}" + cidr_block = "168.31.0.0/20" + + tags { + name = "emr_test" + } +} + +resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.main.id}" +} + +resource "aws_route_table" "r" { + vpc_id = "${aws_vpc.main.id}" + + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.gw.id}" + } +} + +resource "aws_main_route_table_association" "a" { + vpc_id = "${aws_vpc.main.id}" + route_table_id = "${aws_route_table.r.id}" +} + +### + +# IAM things + +### + +# IAM role for EMR Service +resource "aws_iam_role" "iam_emr_default_role" { + name = "iam_emr_default_role_%d" + + assume_role_policy = <