diff --git a/.changelog/26188.txt b/.changelog/26188.txt new file mode 100644 index 000000000000..4dd8abe3d8db --- /dev/null +++ b/.changelog/26188.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_glue_job: Add `execution_class` argument +``` \ No newline at end of file diff --git a/internal/service/glue/dev_endpoint_test.go b/internal/service/glue/dev_endpoint_test.go index 40e7ffc0311c..5775858cb557 100644 --- a/internal/service/glue/dev_endpoint_test.go +++ b/internal/service/glue/dev_endpoint_test.go @@ -561,15 +561,15 @@ func TestAccGlueDevEndpoint_disappears(t *testing.T) { }) } -func testAccCheckDevEndpointExists(resourceName string, v *glue.DevEndpoint) resource.TestCheckFunc { +func testAccCheckDevEndpointExists(n string, v *glue.DevEndpoint) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { - return fmt.Errorf("no Glue Dev Endpoint ID is set") + return fmt.Errorf("No Glue Dev Endpoint ID is set") } conn := acctest.Provider.Meta().(*conns.AWSClient).GlueConn @@ -638,16 +638,16 @@ data "aws_partition" "current" {} } func testAccDevEndpointConfig_basic(rName string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { - name = %q + name = %[1]q role_arn = aws_iam_role.test.arn } -`, rName) +`, rName)) } func testAccDevEndpointConfig_arguments(rName, argKey, argValue string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn @@ -655,11 +655,11 @@ resource "aws_glue_dev_endpoint" "test" { %[2]q = %[3]q } } -`, rName, argKey, argValue) +`, rName, argKey, argValue)) } func testAccDevEndpointConfig_arguments2(rName, argKey1, argValue1, argKey2, argValue2 string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn @@ -668,102 +668,102 @@ resource "aws_glue_dev_endpoint" "test" { %[4]q = %[5]q } } -`, rName, argKey1, argValue1, argKey2, argValue2) +`, rName, argKey1, argValue1, argKey2, argValue2)) } func testAccDevEndpointConfig_extraJarsS3Path(rName string, extraJarsS3Path string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { - name = %q + name = %[1]q role_arn = aws_iam_role.test.arn - extra_jars_s3_path = %q + extra_jars_s3_path = %[2]q } -`, rName, extraJarsS3Path) +`, rName, extraJarsS3Path)) } func testAccDevEndpointConfig_extraPythonLibsS3Path(rName string, extraPythonLibsS3Path string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { - name = %q + name = %[1]q role_arn = aws_iam_role.test.arn - extra_python_libs_s3_path = %q + extra_python_libs_s3_path = %[2]q } -`, rName, extraPythonLibsS3Path) +`, rName, extraPythonLibsS3Path)) } func testAccDevEndpointConfig_version(rName string, glueVersion string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn glue_version = %[2]q } -`, rName, glueVersion) +`, rName, glueVersion)) } func testAccDevEndpointConfig_numberOfNodes(rName string, numberOfNodes int) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { - name = %q + name = %[1]q role_arn = aws_iam_role.test.arn - number_of_nodes = %d + number_of_nodes = %[2]d } -`, rName, numberOfNodes) +`, rName, numberOfNodes)) } func testAccDevEndpointConfig_numberOfWorkers(rName string, numberOfWorkers int) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { - name = %q + name = %[1]q role_arn = aws_iam_role.test.arn worker_type = "G.1X" - number_of_workers = %d + number_of_workers = %[2]d } -`, rName, numberOfWorkers) +`, rName, numberOfWorkers)) } func testAccDevEndpointConfig_publicKey(rName string, publicKey string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { - name = %q + name = %[1]q role_arn = aws_iam_role.test.arn - public_key = "%s" + public_key = %[2]q } -`, rName, publicKey) +`, rName, publicKey)) } func testAccDevEndpointConfig_publicKeys2(rName string, publicKey1 string, publicKey2 string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn public_keys = [%[2]q, %[3]q] } -`, rName, publicKey1, publicKey2) +`, rName, publicKey1, publicKey2)) } func testAccDevEndpointConfig_publicKeys3(rName string, publicKey1 string, publicKey2 string, publicKey3 string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn public_keys = [%[2]q, %[3]q, %[4]q] } -`, rName, publicKey1, publicKey2, publicKey3) +`, rName, publicKey1, publicKey2, publicKey3)) } func testAccDevEndpointConfig_publicKeys4(rName string, publicKey1 string, publicKey2 string, publicKey3 string, publicKey4 string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn public_keys = [%[2]q, %[3]q, %[4]q, %[5]q] } -`, rName, publicKey1, publicKey2, publicKey3, publicKey4) +`, rName, publicKey1, publicKey2, publicKey3, publicKey4)) } func testAccDevEndpointConfig_securityConfiguration(rName string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn @@ -787,7 +787,7 @@ resource "aws_glue_security_configuration" "test" { } } } -`, rName) +`, rName)) } func testAccDevEndpointConfig_subnetIDSecurityGroupIDs(rName string) string { @@ -843,6 +843,10 @@ resource "aws_security_group" "test" { name = %[1]q vpc_id = aws_vpc.test.id + tags = { + Name = %[1]q + } + ingress { from_port = 0 to_port = 0 @@ -866,7 +870,7 @@ resource "aws_security_group" "test" { } func testAccDevEndpointConfig_tags1(rName, tagKey1, tagValue1 string) string { - return testAccJobConfig_Base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn @@ -875,11 +879,11 @@ resource "aws_glue_dev_endpoint" "test" { %[2]q = %[3]q } } -`, rName, tagKey1, tagValue1) +`, rName, tagKey1, tagValue1)) } func testAccDevEndpointConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return testAccJobConfig_Base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn @@ -889,27 +893,27 @@ resource "aws_glue_dev_endpoint" "test" { %[4]q = %[5]q } } -`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) } func testAccDevEndpointConfig_workerType(rName, workerType string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn worker_type = %[2]q number_of_workers = 2 } -`, rName, workerType) +`, rName, workerType)) } func testAccDevEndpointConfig_workerTypeStandard(rName string) string { - return testAccDevEndpointConfig_base(rName) + fmt.Sprintf(` + return acctest.ConfigCompose(testAccDevEndpointConfig_base(rName), fmt.Sprintf(` resource "aws_glue_dev_endpoint" "test" { name = %[1]q role_arn = aws_iam_role.test.arn worker_type = "Standard" number_of_workers = 2 } -`, rName) +`, rName)) } diff --git a/internal/service/glue/find.go b/internal/service/glue/find.go index 3cd89049695b..d570a454f24b 100644 --- a/internal/service/glue/find.go +++ b/internal/service/glue/find.go @@ -27,13 +27,35 @@ func FindDevEndpointByName(conn *glue.Glue, name string) (*glue.DevEndpoint, err } if output == nil || output.DevEndpoint == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.DevEndpoint, nil +} + +func FindJobByName(conn *glue.Glue, name string) (*glue.Job, error) { + input := &glue.GetJobInput{ + JobName: aws.String(name), + } + + output, err := conn.GetJob(input) + + if tfawserr.ErrCodeEquals(err, glue.ErrCodeEntityNotFoundException) { return nil, &resource.NotFoundError{ - Message: "Empty result", + LastError: err, LastRequest: input, } } - return output.DevEndpoint, nil + if err != nil { + return nil, err + } + + if output == nil || output.Job == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.Job, nil } // FindTableByName returns the Table corresponding to the specified name. diff --git a/internal/service/glue/job.go b/internal/service/glue/job.go index 465364e137cc..4db137fd8eab 100644 --- a/internal/service/glue/job.go +++ b/internal/service/glue/job.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) @@ -76,6 +77,11 @@ func ResourceJob() *schema.Resource { Optional: true, Computed: true, }, + "execution_class": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(glue.ExecutionClass_Values(), true), + }, "execution_property": { Type: schema.TypeList, Optional: true, @@ -109,6 +115,11 @@ func ResourceJob() *schema.Resource { ForceNew: true, ValidateFunc: validation.NoZeroValues, }, + "non_overridable_arguments": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, "notification_property": { Type: schema.TypeList, Optional: true, @@ -124,6 +135,12 @@ func ResourceJob() *schema.Resource { }, }, }, + "number_of_workers": { + Type: schema.TypeInt, + Optional: true, + ConflictsWith: []string{"max_capacity"}, + ValidateFunc: validation.IntAtLeast(2), + }, "role_arn": { Type: schema.TypeString, Required: true, @@ -147,17 +164,6 @@ func ResourceJob() *schema.Resource { ConflictsWith: []string{"max_capacity"}, ValidateFunc: validation.StringInSlice(glue.WorkerType_Values(), false), }, - "number_of_workers": { - Type: schema.TypeInt, - Optional: true, - ConflictsWith: []string{"max_capacity"}, - ValidateFunc: validation.IntAtLeast(2), - }, - "non_overridable_arguments": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, }, } } @@ -166,8 +172,8 @@ func resourceJobCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).GlueConn defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) - name := d.Get("name").(string) + name := d.Get("name").(string) input := &glue.CreateJobInput{ Command: expandJobCommand(d.Get("command").([]interface{})), Name: aws.String(name), @@ -175,67 +181,72 @@ func resourceJobCreate(d *schema.ResourceData, meta interface{}) error { Tags: Tags(tags.IgnoreAWS()), } - if v, ok := d.GetOk("timeout"); ok { - input.Timeout = aws.Int64(int64(v.(int))) - } - - if v, ok := d.GetOk("max_capacity"); ok { - input.MaxCapacity = aws.Float64(v.(float64)) - } - if v, ok := d.GetOk("connections"); ok { input.Connections = &glue.ConnectionsList{ Connections: flex.ExpandStringList(v.([]interface{})), } } - if kv, ok := d.GetOk("default_arguments"); ok { - input.DefaultArguments = flex.ExpandStringMap(kv.(map[string]interface{})) - } - - if kv, ok := d.GetOk("non_overridable_arguments"); ok { - input.NonOverridableArguments = flex.ExpandStringMap(kv.(map[string]interface{})) + if v, ok := d.GetOk("default_arguments"); ok { + input.DefaultArguments = flex.ExpandStringMap(v.(map[string]interface{})) } if v, ok := d.GetOk("description"); ok { input.Description = aws.String(v.(string)) } - if v, ok := d.GetOk("glue_version"); ok { - input.GlueVersion = aws.String(v.(string)) + if v, ok := d.GetOk("execution_class"); ok { + input.ExecutionClass = aws.String(v.(string)) } if v, ok := d.GetOk("execution_property"); ok { input.ExecutionProperty = expandExecutionProperty(v.([]interface{})) } + if v, ok := d.GetOk("glue_version"); ok { + input.GlueVersion = aws.String(v.(string)) + } + + if v, ok := d.GetOk("max_capacity"); ok { + input.MaxCapacity = aws.Float64(v.(float64)) + } + if v, ok := d.GetOk("max_retries"); ok { input.MaxRetries = aws.Int64(int64(v.(int))) } + if v, ok := d.GetOk("non_overridable_arguments"); ok { + input.NonOverridableArguments = flex.ExpandStringMap(v.(map[string]interface{})) + } + if v, ok := d.GetOk("notification_property"); ok { input.NotificationProperty = expandNotificationProperty(v.([]interface{})) } + if v, ok := d.GetOk("number_of_workers"); ok { + input.NumberOfWorkers = aws.Int64(int64(v.(int))) + } + if v, ok := d.GetOk("security_configuration"); ok { input.SecurityConfiguration = aws.String(v.(string)) } - if v, ok := d.GetOk("worker_type"); ok { - input.WorkerType = aws.String(v.(string)) + if v, ok := d.GetOk("timeout"); ok { + input.Timeout = aws.Int64(int64(v.(int))) } - if v, ok := d.GetOk("number_of_workers"); ok { - input.NumberOfWorkers = aws.Int64(int64(v.(int))) + if v, ok := d.GetOk("worker_type"); ok { + input.WorkerType = aws.String(v.(string)) } log.Printf("[DEBUG] Creating Glue Job: %s", input) - _, err := conn.CreateJob(input) + output, err := conn.CreateJob(input) + if err != nil { - return fmt.Errorf("error creating Glue Job (%s): %s", name, err) + return fmt.Errorf("creating Glue Job (%s): %w", name, err) } - d.SetId(name) + d.SetId(aws.StringValue(output.Name)) return resourceJobRead(d, meta) } @@ -245,28 +256,18 @@ func resourceJobRead(d *schema.ResourceData, meta interface{}) error { defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig - input := &glue.GetJobInput{ - JobName: aws.String(d.Id()), - } - - log.Printf("[DEBUG] Reading Glue Job: %s", input) - output, err := conn.GetJob(input) - if err != nil { - if tfawserr.ErrCodeEquals(err, glue.ErrCodeEntityNotFoundException) { - log.Printf("[WARN] Glue Job (%s) not found, removing from state", d.Id()) - d.SetId("") - return nil - } - return fmt.Errorf("error reading Glue Job (%s): %s", d.Id(), err) - } + job, err := FindJobByName(conn, d.Id()) - job := output.Job - if job == nil { + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Glue Job (%s) not found, removing from state", d.Id()) d.SetId("") return nil } + if err != nil { + return fmt.Errorf("reading Glue Job (%s): %w", d.Id(), err) + } + jobARN := arn.ARN{ Partition: meta.(*conns.AWSClient).Partition, Service: "glue", @@ -275,83 +276,61 @@ func resourceJobRead(d *schema.ResourceData, meta interface{}) error { Resource: fmt.Sprintf("job/%s", d.Id()), }.String() d.Set("arn", jobARN) - if err := d.Set("command", flattenJobCommand(job.Command)); err != nil { - return fmt.Errorf("error setting command: %s", err) + return fmt.Errorf("setting command: %w", err) } if err := d.Set("connections", flattenConnectionsList(job.Connections)); err != nil { - return fmt.Errorf("error setting connections: %s", err) - } - if err := d.Set("default_arguments", aws.StringValueMap(job.DefaultArguments)); err != nil { - return fmt.Errorf("error setting default_arguments: %s", err) - } - if err := d.Set("non_overridable_arguments", aws.StringValueMap(job.NonOverridableArguments)); err != nil { - return fmt.Errorf("error setting non_overridable_arguments: %w", err) + return fmt.Errorf("setting connections: %w", err) } + d.Set("default_arguments", aws.StringValueMap(job.DefaultArguments)) d.Set("description", job.Description) - d.Set("glue_version", job.GlueVersion) + d.Set("execution_class", job.ExecutionClass) if err := d.Set("execution_property", flattenExecutionProperty(job.ExecutionProperty)); err != nil { - return fmt.Errorf("error setting execution_property: %s", err) + return fmt.Errorf("setting execution_property: %w", err) } + d.Set("glue_version", job.GlueVersion) d.Set("max_capacity", job.MaxCapacity) d.Set("max_retries", job.MaxRetries) + d.Set("name", job.Name) + d.Set("non_overridable_arguments", aws.StringValueMap(job.NonOverridableArguments)) if err := d.Set("notification_property", flattenNotificationProperty(job.NotificationProperty)); err != nil { - return fmt.Errorf("error setting notification_property: #{err}") + return fmt.Errorf("setting notification_property: %w", err) } - d.Set("name", job.Name) + d.Set("number_of_workers", job.NumberOfWorkers) d.Set("role_arn", job.Role) + d.Set("security_configuration", job.SecurityConfiguration) + d.Set("timeout", job.Timeout) + d.Set("worker_type", job.WorkerType) tags, err := ListTags(conn, jobARN) if err != nil { - return fmt.Errorf("error listing tags for Glue Job (%s): %s", jobARN, err) + return fmt.Errorf("listing tags for Glue Job (%s): %w", jobARN, err) } tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig) //lintignore:AWSR002 if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %w", err) + return fmt.Errorf("setting tags: %w", err) } if err := d.Set("tags_all", tags.Map()); err != nil { - return fmt.Errorf("error setting tags_all: %w", err) - } - - d.Set("timeout", job.Timeout) - if err := d.Set("security_configuration", job.SecurityConfiguration); err != nil { - return fmt.Errorf("error setting security_configuration: %s", err) + return fmt.Errorf("setting tags_all: %w", err) } - d.Set("worker_type", job.WorkerType) - d.Set("number_of_workers", job.NumberOfWorkers) - return nil } func resourceJobUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).GlueConn - if d.HasChanges("command", "connections", "default_arguments", "description", - "execution_property", "glue_version", "max_capacity", "max_retries", "notification_property", "number_of_workers", - "role_arn", "security_configuration", "timeout", "worker_type", "non_overridable_arguments") { + if d.HasChangesExcept("tags", "tags_all") { jobUpdate := &glue.JobUpdate{ Command: expandJobCommand(d.Get("command").([]interface{})), Role: aws.String(d.Get("role_arn").(string)), } - if v, ok := d.GetOk("timeout"); ok { - jobUpdate.Timeout = aws.Int64(int64(v.(int))) - } - - if v, ok := d.GetOk("number_of_workers"); ok { - jobUpdate.NumberOfWorkers = aws.Int64(int64(v.(int))) - } else { - if v, ok := d.GetOk("max_capacity"); ok { - jobUpdate.MaxCapacity = aws.Float64(v.(float64)) - } - } - if v, ok := d.GetOk("connections"); ok { jobUpdate.Connections = &glue.ConnectionsList{ Connections: flex.ExpandStringList(v.([]interface{})), @@ -362,34 +341,50 @@ func resourceJobUpdate(d *schema.ResourceData, meta interface{}) error { jobUpdate.DefaultArguments = flex.ExpandStringMap(kv.(map[string]interface{})) } - if kv, ok := d.GetOk("non_overridable_arguments"); ok { - jobUpdate.NonOverridableArguments = flex.ExpandStringMap(kv.(map[string]interface{})) - } - if v, ok := d.GetOk("description"); ok { jobUpdate.Description = aws.String(v.(string)) } - if v, ok := d.GetOk("glue_version"); ok { - jobUpdate.GlueVersion = aws.String(v.(string)) + if v, ok := d.GetOk("execution_class"); ok { + jobUpdate.ExecutionClass = aws.String(v.(string)) } if v, ok := d.GetOk("execution_property"); ok { jobUpdate.ExecutionProperty = expandExecutionProperty(v.([]interface{})) } + if v, ok := d.GetOk("glue_version"); ok { + jobUpdate.GlueVersion = aws.String(v.(string)) + } + if v, ok := d.GetOk("max_retries"); ok { jobUpdate.MaxRetries = aws.Int64(int64(v.(int))) } + if kv, ok := d.GetOk("non_overridable_arguments"); ok { + jobUpdate.NonOverridableArguments = flex.ExpandStringMap(kv.(map[string]interface{})) + } + if v, ok := d.GetOk("notification_property"); ok { jobUpdate.NotificationProperty = expandNotificationProperty(v.([]interface{})) } + if v, ok := d.GetOk("number_of_workers"); ok { + jobUpdate.NumberOfWorkers = aws.Int64(int64(v.(int))) + } else { + if v, ok := d.GetOk("max_capacity"); ok { + jobUpdate.MaxCapacity = aws.Float64(v.(float64)) + } + } + if v, ok := d.GetOk("security_configuration"); ok { jobUpdate.SecurityConfiguration = aws.String(v.(string)) } + if v, ok := d.GetOk("timeout"); ok { + jobUpdate.Timeout = aws.Int64(int64(v.(int))) + } + if v, ok := d.GetOk("worker_type"); ok { jobUpdate.WorkerType = aws.String(v.(string)) } @@ -401,15 +396,16 @@ func resourceJobUpdate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] Updating Glue Job: %s", input) _, err := conn.UpdateJob(input) + if err != nil { - return fmt.Errorf("error updating Glue Job (%s): %s", d.Id(), err) + return fmt.Errorf("updating Glue Job (%s): %w", d.Id(), err) } } if d.HasChange("tags_all") { o, n := d.GetChange("tags_all") if err := UpdateTags(conn, d.Get("arn").(string), o, n); err != nil { - return fmt.Errorf("error updating tags: %s", err) + return fmt.Errorf("updating tags: %w", err) } } @@ -420,25 +416,16 @@ func resourceJobDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).GlueConn log.Printf("[DEBUG] Deleting Glue Job: %s", d.Id()) - err := DeleteJob(conn, d.Id()) - if err != nil { - return fmt.Errorf("error deleting Glue Job (%s): %s", d.Id(), err) - } - - return nil -} + _, err := conn.DeleteJob(&glue.DeleteJobInput{ + JobName: aws.String(d.Id()), + }) -func DeleteJob(conn *glue.Glue, jobName string) error { - input := &glue.DeleteJobInput{ - JobName: aws.String(jobName), + if tfawserr.ErrCodeEquals(err, glue.ErrCodeEntityNotFoundException) { + return nil } - _, err := conn.DeleteJob(input) if err != nil { - if tfawserr.ErrCodeEquals(err, glue.ErrCodeEntityNotFoundException) { - return nil - } - return err + return fmt.Errorf("deleting Glue Job (%s): %w", d.Id(), err) } return nil diff --git a/internal/service/glue/job_test.go b/internal/service/glue/job_test.go index 4eef24bcf5d1..6254365f3173 100644 --- a/internal/service/glue/job_test.go +++ b/internal/service/glue/job_test.go @@ -5,21 +5,19 @@ import ( "regexp" "testing" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/glue" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfglue "github.com/hashicorp/terraform-provider-aws/internal/service/glue" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func TestAccGlueJob_basic(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" roleResourceName := "aws_iam_role.test" @@ -37,8 +35,9 @@ func TestAccGlueJob_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "command.#", "1"), resource.TestCheckResourceAttr(resourceName, "command.0.script_location", "testscriptlocation"), resource.TestCheckResourceAttr(resourceName, "default_arguments.%", "0"), - resource.TestCheckResourceAttr(resourceName, "non_overridable_arguments.%", "0"), + resource.TestCheckResourceAttr(resourceName, "execution_class", ""), resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "non_overridable_arguments.%", "0"), resource.TestCheckResourceAttrPair(resourceName, "role_arn", roleResourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttr(resourceName, "timeout", "2880"), @@ -53,10 +52,32 @@ func TestAccGlueJob_basic(t *testing.T) { }) } -func TestAccGlueJob_basicStreaming(t *testing.T) { +func TestAccGlueJob_disappears(t *testing.T) { var job glue.Job + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_glue_job.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, glue.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccJobConfig_required(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckJobExists(resourceName, &job), + acctest.CheckResourceDisappears(acctest.Provider, tfglue.ResourceJob(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) +func TestAccGlueJob_basicStreaming(t *testing.T) { + var job glue.Job + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" roleResourceName := "aws_iam_role.test" @@ -92,8 +113,7 @@ func TestAccGlueJob_basicStreaming(t *testing.T) { } func TestAccGlueJob_command(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -129,8 +149,7 @@ func TestAccGlueJob_command(t *testing.T) { func TestAccGlueJob_defaultArguments(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -168,8 +187,7 @@ func TestAccGlueJob_defaultArguments(t *testing.T) { func TestAccGlueJob_nonOverridableArguments(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -207,8 +225,7 @@ func TestAccGlueJob_nonOverridableArguments(t *testing.T) { func TestAccGlueJob_description(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -242,8 +259,7 @@ func TestAccGlueJob_description(t *testing.T) { func TestAccGlueJob_glueVersion(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -282,10 +298,42 @@ func TestAccGlueJob_glueVersion(t *testing.T) { }) } -func TestAccGlueJob_executionProperty(t *testing.T) { +func TestAccGlueJob_executionClass(t *testing.T) { var job glue.Job + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_glue_job.test" - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, glue.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccJobConfig_executionClass(rName, "FLEX"), + Check: resource.ComposeTestCheckFunc( + testAccCheckJobExists(resourceName, &job), + resource.TestCheckResourceAttr(resourceName, "execution_class", "FLEX"), + ), + }, + { + Config: testAccJobConfig_executionClass(rName, "STANDARD"), + Check: resource.ComposeTestCheckFunc( + testAccCheckJobExists(resourceName, &job), + resource.TestCheckResourceAttr(resourceName, "execution_class", "STANDARD"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +func TestAccGlueJob_executionProperty(t *testing.T) { + var job glue.Job + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -325,8 +373,7 @@ func TestAccGlueJob_executionProperty(t *testing.T) { func TestAccGlueJob_maxRetries(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -364,8 +411,7 @@ func TestAccGlueJob_maxRetries(t *testing.T) { func TestAccGlueJob_notificationProperty(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -404,9 +450,8 @@ func TestAccGlueJob_notificationProperty(t *testing.T) { } func TestAccGlueJob_tags(t *testing.T) { - var job1, job2, job3 glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + var job glue.Job + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -418,7 +463,7 @@ func TestAccGlueJob_tags(t *testing.T) { { Config: testAccJobConfig_tags1(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccCheckJobExists(resourceName, &job1), + testAccCheckJobExists(resourceName, &job), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), @@ -431,7 +476,7 @@ func TestAccGlueJob_tags(t *testing.T) { { Config: testAccJobConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckJobExists(resourceName, &job2), + testAccCheckJobExists(resourceName, &job), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), @@ -440,7 +485,7 @@ func TestAccGlueJob_tags(t *testing.T) { { Config: testAccJobConfig_tags1(rName, "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckJobExists(resourceName, &job3), + testAccCheckJobExists(resourceName, &job), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), @@ -451,8 +496,7 @@ func TestAccGlueJob_tags(t *testing.T) { func TestAccGlueJob_streamingTimeout(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -485,8 +529,7 @@ func TestAccGlueJob_streamingTimeout(t *testing.T) { } func TestAccGlueJob_timeout(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -520,8 +563,7 @@ func TestAccGlueJob_timeout(t *testing.T) { func TestAccGlueJob_security(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -555,8 +597,7 @@ func TestAccGlueJob_security(t *testing.T) { func TestAccGlueJob_workerType(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -597,8 +638,7 @@ func TestAccGlueJob_workerType(t *testing.T) { func TestAccGlueJob_pythonShell(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -653,8 +693,7 @@ func TestAccGlueJob_pythonShell(t *testing.T) { func TestAccGlueJob_maxCapacity(t *testing.T) { var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_glue_job.test" resource.ParallelTest(t, resource.TestCase{ @@ -689,35 +728,11 @@ func TestAccGlueJob_maxCapacity(t *testing.T) { }) } -func TestAccGlueJob_disappears(t *testing.T) { - var job glue.Job - - rName := fmt.Sprintf("tf-acc-test-%s", sdkacctest.RandString(5)) - resourceName := "aws_glue_job.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, glue.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckJobDestroy, - Steps: []resource.TestStep{ - { - Config: testAccJobConfig_required(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckJobExists(resourceName, &job), - acctest.CheckResourceDisappears(acctest.Provider, tfglue.ResourceJob(), resourceName), - ), - ExpectNonEmptyPlan: true, - }, - }, - }) -} - -func testAccCheckJobExists(resourceName string, job *glue.Job) resource.TestCheckFunc { +func testAccCheckJobExists(n string, v *glue.Job) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { @@ -726,23 +741,15 @@ func testAccCheckJobExists(resourceName string, job *glue.Job) resource.TestChec conn := acctest.Provider.Meta().(*conns.AWSClient).GlueConn - output, err := conn.GetJob(&glue.GetJobInput{ - JobName: aws.String(rs.Primary.ID), - }) + output, err := tfglue.FindJobByName(conn, rs.Primary.ID) + if err != nil { return err } - if output.Job == nil { - return fmt.Errorf("Glue Job (%s) not found", rs.Primary.ID) - } + *v = *output - if aws.StringValue(output.Job.Name) == rs.Primary.ID { - *job = *output.Job - return nil - } - - return fmt.Errorf("Glue Job (%s) not found", rs.Primary.ID) + return nil } } @@ -754,29 +761,23 @@ func testAccCheckJobDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GlueConn - output, err := conn.GetJob(&glue.GetJobInput{ - JobName: aws.String(rs.Primary.ID), - }) - - if err != nil { - if tfawserr.ErrCodeEquals(err, glue.ErrCodeEntityNotFoundException) { - return nil - } + _, err := tfglue.FindJobByName(conn, rs.Primary.ID) + if tfresource.NotFound(err) { + continue } - job := output.Job - if job != nil && aws.StringValue(job.Name) == rs.Primary.ID { - return fmt.Errorf("Glue Job %s still exists", rs.Primary.ID) + if err != nil { + return err } - return err + return fmt.Errorf("Glue Job %s still exists", rs.Primary.ID) } return nil } -func testAccJobConfig_Base(rName string) string { +func testAccJobConfig_base(rName string) string { return fmt.Sprintf(` data "aws_partition" "current" {} @@ -785,7 +786,7 @@ data "aws_iam_policy" "AWSGlueServiceRole" { } resource "aws_iam_role" "test" { - name = "%s" + name = %[1]q assume_role_policy = <