diff --git a/aws/internal/service/glue/waiter/status.go b/aws/internal/service/glue/waiter/status.go index bd43baa2492..e7093e36246 100644 --- a/aws/internal/service/glue/waiter/status.go +++ b/aws/internal/service/glue/waiter/status.go @@ -8,9 +8,10 @@ import ( const ( MLTransformStatusUnknown = "Unknown" + TriggerStatusUnknown = "Unknown" ) -// MLTransformStatus fetches the Operation and its Status +// MLTransformStatus fetches the MLTransform and its Status func MLTransformStatus(conn *glue.Glue, transformId string) resource.StateRefreshFunc { return func() (interface{}, string, error) { input := &glue.GetMLTransformInput{ @@ -30,3 +31,24 @@ func MLTransformStatus(conn *glue.Glue, transformId string) resource.StateRefres return output, aws.StringValue(output.Status), nil } } + +// TriggerStatus fetches the Trigger and its Status +func TriggerStatus(conn *glue.Glue, triggerName string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + input := &glue.GetTriggerInput{ + Name: aws.String(triggerName), + } + + output, err := conn.GetTrigger(input) + + if err != nil { + return nil, TriggerStatusUnknown, err + } + + if output == nil { + return output, TriggerStatusUnknown, nil + } + + return output, aws.StringValue(output.Trigger.State), nil + } +} diff --git a/aws/internal/service/glue/waiter/waiter.go b/aws/internal/service/glue/waiter/waiter.go index d13f1fb205e..bc0f6f4ab86 100644 --- a/aws/internal/service/glue/waiter/waiter.go +++ b/aws/internal/service/glue/waiter/waiter.go @@ -1,18 +1,20 @@ package waiter import ( - "github.com/aws/aws-sdk-go/service/glue" "time" + "github.com/aws/aws-sdk-go/service/glue" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) const ( - // Maximum amount of time to wait for an Operation to return Success + // Maximum amount of time to wait for an Operation to return Deleted MLTransformDeleteTimeout = 2 * time.Minute + TriggerCreateTimeout = 2 * time.Minute + TriggerDeleteTimeout = 2 * time.Minute ) -// MLTransformDeleted waits for an Operation to return Success +// MLTransformDeleted waits for an MLTransform to return Deleted func MLTransformDeleted(conn *glue.Glue, transformId string) (*glue.GetMLTransformOutput, error) { stateConf := &resource.StateChangeConf{ Pending: []string{glue.TransformStatusTypeNotReady, glue.TransformStatusTypeReady, glue.TransformStatusTypeDeleting}, @@ -29,3 +31,45 @@ func MLTransformDeleted(conn *glue.Glue, transformId string) (*glue.GetMLTransfo return nil, err } + +// TriggerCreated waits for a Trigger to return Created +func TriggerCreated(conn *glue.Glue, triggerName string) (*glue.GetTriggerOutput, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{ + glue.TriggerStateActivating, + glue.TriggerStateCreating, + }, + Target: []string{ + glue.TriggerStateActivated, + glue.TriggerStateCreated, + }, + Refresh: TriggerStatus(conn, triggerName), + Timeout: TriggerCreateTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*glue.GetTriggerOutput); ok { + return output, err + } + + return nil, err +} + +// TriggerDeleted waits for a Trigger to return Deleted +func TriggerDeleted(conn *glue.Glue, triggerName string) (*glue.GetTriggerOutput, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{glue.TriggerStateDeleting}, + Target: []string{}, + Refresh: TriggerStatus(conn, triggerName), + Timeout: TriggerDeleteTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*glue.GetTriggerOutput); ok { + return output, err + } + + return nil, err +} diff --git a/aws/resource_aws_glue_trigger.go b/aws/resource_aws_glue_trigger.go index b36ea66fff5..af349540138 100644 --- a/aws/resource_aws_glue_trigger.go +++ b/aws/resource_aws_glue_trigger.go @@ -8,10 +8,10 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/glue" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/glue/waiter" ) func resourceAwsGlueTrigger() *schema.Resource { @@ -52,6 +52,24 @@ func resourceAwsGlueTrigger() *schema.Resource { Type: schema.TypeInt, Optional: true, }, + "security_configuration": { + Type: schema.TypeString, + Optional: true, + }, + "notification_property": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "notify_delay_after": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), + }, + }, + }, + }, }, }, }, @@ -72,7 +90,7 @@ func resourceAwsGlueTrigger() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.NoZeroValues, + ValidateFunc: validation.StringLenBetween(1, 255), }, "predicate": { Type: schema.TypeList, @@ -95,44 +113,29 @@ func resourceAwsGlueTrigger() *schema.Resource { Optional: true, }, "logical_operator": { - Type: schema.TypeString, - Optional: true, - Default: glue.LogicalOperatorEquals, - ValidateFunc: validation.StringInSlice([]string{ - glue.LogicalOperatorEquals, - }, false), + Type: schema.TypeString, + Optional: true, + Default: glue.LogicalOperatorEquals, + ValidateFunc: validation.StringInSlice(glue.LogicalOperator_Values(), false), }, "state": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - glue.JobRunStateFailed, - glue.JobRunStateStopped, - glue.JobRunStateSucceeded, - glue.JobRunStateTimeout, - }, false), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(glue.JobRunState_Values(), false), }, "crawl_state": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - glue.CrawlStateRunning, - glue.CrawlStateSucceeded, - glue.CrawlStateCancelled, - glue.CrawlStateFailed, - }, false), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(glue.CrawlState_Values(), false), }, }, }, }, "logical": { - Type: schema.TypeString, - Optional: true, - Default: glue.LogicalAnd, - ValidateFunc: validation.StringInSlice([]string{ - glue.LogicalAnd, - glue.LogicalAny, - }, false), + Type: schema.TypeString, + Optional: true, + Default: glue.LogicalAnd, + ValidateFunc: validation.StringInSlice(glue.Logical_Values(), false), }, }, }, @@ -143,14 +146,10 @@ func resourceAwsGlueTrigger() *schema.Resource { }, "tags": tagsSchema(), "type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - glue.TriggerTypeConditional, - glue.TriggerTypeOnDemand, - glue.TriggerTypeScheduled, - }, false), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(glue.TriggerType_Values(), false), }, "workflow_name": { Type: schema.TypeString, @@ -200,27 +199,17 @@ func resourceAwsGlueTriggerCreate(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] Creating Glue Trigger: %s", input) _, err := conn.CreateTrigger(input) if err != nil { - return fmt.Errorf("error creating Glue Trigger (%s): %s", name, err) + return fmt.Errorf("error creating Glue Trigger (%s): %w", name, err) } d.SetId(name) log.Printf("[DEBUG] Waiting for Glue Trigger (%s) to create", d.Id()) - stateConf := &resource.StateChangeConf{ - Pending: []string{ - glue.TriggerStateActivating, - glue.TriggerStateCreating, - }, - Target: []string{ - glue.TriggerStateActivated, - glue.TriggerStateCreated, - }, - Refresh: resourceAwsGlueTriggerRefreshFunc(conn, d.Id()), - Timeout: d.Timeout(schema.TimeoutCreate), - } - _, err = stateConf.WaitForState() - if err != nil { - return fmt.Errorf("error waiting for Glue Trigger (%s) to create", d.Id()) + if _, err := waiter.TriggerCreated(conn, d.Id()); err != nil { + if isAWSErr(err, glue.ErrCodeEntityNotFoundException, "") { + return nil + } + return fmt.Errorf("error waiting for Glue Trigger (%s) to be Created: %w", d.Id(), err) } return resourceAwsGlueTriggerRead(d, meta) @@ -242,7 +231,7 @@ func resourceAwsGlueTriggerRead(d *schema.ResourceData, meta interface{}) error d.SetId("") return nil } - return fmt.Errorf("error reading Glue Trigger (%s): %s", d.Id(), err) + return fmt.Errorf("error reading Glue Trigger (%s): %w", d.Id(), err) } trigger := output.Trigger @@ -253,7 +242,7 @@ func resourceAwsGlueTriggerRead(d *schema.ResourceData, meta interface{}) error } if err := d.Set("actions", flattenGlueActions(trigger.Actions)); err != nil { - return fmt.Errorf("error setting actions: %s", err) + return fmt.Errorf("error setting actions: %w", err) } triggerARN := arn.ARN{ @@ -278,7 +267,7 @@ func resourceAwsGlueTriggerRead(d *schema.ResourceData, meta interface{}) error d.Set("enabled", enabled) if err := d.Set("predicate", flattenGluePredicate(trigger.Predicate)); err != nil { - return fmt.Errorf("error setting predicate: %s", err) + return fmt.Errorf("error setting predicate: %w", err) } d.Set("name", trigger.Name) @@ -287,11 +276,11 @@ func resourceAwsGlueTriggerRead(d *schema.ResourceData, meta interface{}) error tags, err := keyvaluetags.GlueListTags(conn, triggerARN) if err != nil { - return fmt.Errorf("error listing tags for Glue Trigger (%s): %s", triggerARN, err) + return fmt.Errorf("error listing tags for Glue Trigger (%s): %w", triggerARN, err) } if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + return fmt.Errorf("error setting tags: %w", err) } d.Set("type", trigger.Type) @@ -327,7 +316,7 @@ func resourceAwsGlueTriggerUpdate(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] Updating Glue Trigger: %s", input) _, err := conn.UpdateTrigger(input) if err != nil { - return fmt.Errorf("error updating Glue Trigger (%s): %s", d.Id(), err) + return fmt.Errorf("error updating Glue Trigger (%s): %w", d.Id(), err) } } @@ -340,7 +329,7 @@ func resourceAwsGlueTriggerUpdate(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] Starting Glue Trigger: %s", input) _, err := conn.StartTrigger(input) if err != nil { - return fmt.Errorf("error starting Glue Trigger (%s): %s", d.Id(), err) + return fmt.Errorf("error starting Glue Trigger (%s): %w", d.Id(), err) } } else { input := &glue.StopTriggerInput{ @@ -350,7 +339,7 @@ func resourceAwsGlueTriggerUpdate(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] Stopping Glue Trigger: %s", input) _, err := conn.StopTrigger(input) if err != nil { - return fmt.Errorf("error stopping Glue Trigger (%s): %s", d.Id(), err) + return fmt.Errorf("error stopping Glue Trigger (%s): %w", d.Id(), err) } } } @@ -358,7 +347,7 @@ func resourceAwsGlueTriggerUpdate(d *schema.ResourceData, meta interface{}) erro if d.HasChange("tags") { o, n := d.GetChange("tags") if err := keyvaluetags.GlueUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { - return fmt.Errorf("error updating tags: %s", err) + return fmt.Errorf("error updating tags: %w", err) } } @@ -371,44 +360,20 @@ func resourceAwsGlueTriggerDelete(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] Deleting Glue Trigger: %s", d.Id()) err := deleteGlueTrigger(conn, d.Id()) if err != nil { - return fmt.Errorf("error deleting Glue Trigger (%s): %s", d.Id(), err) + return fmt.Errorf("error deleting Glue Trigger (%s): %w", d.Id(), err) } log.Printf("[DEBUG] Waiting for Glue Trigger (%s) to delete", d.Id()) - stateConf := &resource.StateChangeConf{ - Pending: []string{glue.TriggerStateDeleting}, - Target: []string{""}, - Refresh: resourceAwsGlueTriggerRefreshFunc(conn, d.Id()), - Timeout: d.Timeout(schema.TimeoutDelete), - } - _, err = stateConf.WaitForState() - if err != nil { + if _, err := waiter.TriggerDeleted(conn, d.Id()); err != nil { if isAWSErr(err, glue.ErrCodeEntityNotFoundException, "") { return nil } - return fmt.Errorf("error waiting for Glue Trigger (%s) to delete", d.Id()) + return fmt.Errorf("error waiting for Glue Trigger (%s) to be Deleted: %w", d.Id(), err) } return nil } -func resourceAwsGlueTriggerRefreshFunc(conn *glue.Glue, name string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - output, err := conn.GetTrigger(&glue.GetTriggerInput{ - Name: aws.String(name), - }) - if err != nil { - return output, "", err - } - - if output.Trigger == nil { - return output, "", nil - } - - return output, aws.StringValue(output.Trigger.State), nil - } -} - func deleteGlueTrigger(conn *glue.Glue, Name string) error { input := &glue.DeleteTriggerInput{ Name: aws.String(Name), @@ -451,12 +416,32 @@ func expandGlueActions(l []interface{}) []*glue.Action { action.Timeout = aws.Int64(int64(v.(int))) } + if v, ok := m["security_configuration"].(string); ok && v != "" { + action.SecurityConfiguration = aws.String(v) + } + + if v, ok := m["notification_property"].([]interface{}); ok && len(v) > 0 { + action.NotificationProperty = expandGlueTriggerNotificationProperty(v) + } + actions = append(actions, action) } return actions } +func expandGlueTriggerNotificationProperty(l []interface{}) *glue.NotificationProperty { + m := l[0].(map[string]interface{}) + + property := &glue.NotificationProperty{} + + if v, ok := m["notify_delay_after"]; ok && v.(int) > 0 { + property.NotifyDelayAfter = aws.Int64(int64(v.(int))) + } + + return property +} + func expandGlueConditions(l []interface{}) []*glue.Condition { conditions := []*glue.Condition{} @@ -520,6 +505,14 @@ func flattenGlueActions(actions []*glue.Action) []interface{} { m["job_name"] = v } + if v := aws.StringValue(action.SecurityConfiguration); v != "" { + m["security_configuration"] = v + } + + if v := action.NotificationProperty; v != nil { + m["notification_property"] = flattenGlueTriggerNotificationProperty(v) + } + l = append(l, m) } @@ -568,3 +561,15 @@ func flattenGluePredicate(predicate *glue.Predicate) []map[string]interface{} { return []map[string]interface{}{m} } + +func flattenGlueTriggerNotificationProperty(property *glue.NotificationProperty) []map[string]interface{} { + if property == nil { + return []map[string]interface{}{} + } + + m := map[string]interface{}{ + "notify_delay_after": aws.Int64Value(property.NotifyDelayAfter), + } + + return []map[string]interface{}{m} +} diff --git a/aws/resource_aws_glue_trigger_test.go b/aws/resource_aws_glue_trigger_test.go index 9672592744d..0a620118cf7 100644 --- a/aws/resource_aws_glue_trigger_test.go +++ b/aws/resource_aws_glue_trigger_test.go @@ -57,7 +57,7 @@ func testSweepGlueTriggers(region string) error { func TestAccAWSGlueTrigger_basic(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -71,6 +71,7 @@ func TestAccAWSGlueTrigger_basic(t *testing.T) { testAccCheckAWSGlueTriggerExists(resourceName, &trigger), resource.TestCheckResourceAttr(resourceName, "actions.#", "1"), resource.TestCheckResourceAttr(resourceName, "actions.0.job_name", rName), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.#", "0"), testAccCheckResourceAttrRegionalARN(resourceName, "arn", "glue", fmt.Sprintf("trigger/%s", rName)), resource.TestCheckResourceAttr(resourceName, "description", ""), resource.TestCheckResourceAttr(resourceName, "enabled", "true"), @@ -94,7 +95,7 @@ func TestAccAWSGlueTrigger_basic(t *testing.T) { func TestAccAWSGlueTrigger_Crawler(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test_trigger" resource.ParallelTest(t, resource.TestCase{ @@ -140,7 +141,7 @@ func TestAccAWSGlueTrigger_Crawler(t *testing.T) { func TestAccAWSGlueTrigger_Description(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -174,7 +175,7 @@ func TestAccAWSGlueTrigger_Description(t *testing.T) { func TestAccAWSGlueTrigger_Enabled(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -215,7 +216,7 @@ func TestAccAWSGlueTrigger_Enabled(t *testing.T) { func TestAccAWSGlueTrigger_Predicate(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -257,7 +258,7 @@ func TestAccAWSGlueTrigger_Predicate(t *testing.T) { func TestAccAWSGlueTrigger_Schedule(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -291,7 +292,7 @@ func TestAccAWSGlueTrigger_Schedule(t *testing.T) { func TestAccAWSGlueTrigger_Tags(t *testing.T) { var trigger1, trigger2, trigger3 glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -336,7 +337,7 @@ func TestAccAWSGlueTrigger_Tags(t *testing.T) { func TestAccAWSGlueTrigger_WorkflowName(t *testing.T) { var trigger glue.Trigger - rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5)) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_trigger.test" resource.ParallelTest(t, resource.TestCase{ @@ -360,6 +361,108 @@ func TestAccAWSGlueTrigger_WorkflowName(t *testing.T) { }) } +func TestAccAWSGlueTrigger_actions_notify(t *testing.T) { + var trigger glue.Trigger + + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_glue_trigger.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSGlueTriggerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSGlueTriggerConfigActionsNotification(rName, 1), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSGlueTriggerExists(resourceName, &trigger), + resource.TestCheckResourceAttr(resourceName, "actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.job_name", rName), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.0.notify_delay_after", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSGlueTriggerConfigActionsNotification(rName, 2), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSGlueTriggerExists(resourceName, &trigger), + resource.TestCheckResourceAttr(resourceName, "actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.job_name", rName), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.0.notify_delay_after", "2"), + ), + }, + { + Config: testAccAWSGlueTriggerConfigActionsNotification(rName, 1), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSGlueTriggerExists(resourceName, &trigger), + resource.TestCheckResourceAttr(resourceName, "actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.job_name", rName), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.notification_property.0.notify_delay_after", "1"), + ), + }, + }, + }) +} + +func TestAccAWSGlueTrigger_actions_securityConfig(t *testing.T) { + var trigger glue.Trigger + + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_glue_trigger.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSGlueTriggerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSGlueTriggerConfigActionsSecurityConfiguration(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSGlueTriggerExists(resourceName, &trigger), + resource.TestCheckResourceAttr(resourceName, "actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "actions.0.job_name", rName), + resource.TestCheckResourceAttr(resourceName, "actions.0.security_configuration", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSGlueTrigger_disappears(t *testing.T) { + var trigger glue.Trigger + + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_glue_trigger.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSGlueTriggerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSGlueTriggerConfig_OnDemand(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSGlueTriggerExists(resourceName, &trigger), + testAccCheckResourceDisappears(testAccProvider, resourceAwsGlueTrigger(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckAWSGlueTriggerExists(resourceName string, trigger *glue.Trigger) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -424,28 +527,24 @@ func testAccCheckAWSGlueTriggerDestroy(s *terraform.State) error { } func testAccAWSGlueTriggerConfig_Description(rName, description string) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_trigger" "test" { - description = "%s" - name = "%s" + description = %[1]q + name = %[2]q type = "ON_DEMAND" actions { job_name = aws_glue_job.test.name } } -`, testAccAWSGlueJobConfig_Required(rName), description, rName) +`, description, rName)) } func testAccAWSGlueTriggerConfig_Enabled(rName string, enabled bool) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_trigger" "test" { - enabled = %t - name = "%s" + enabled = %[1]t + name = %[2]q schedule = "cron(15 12 * * ? *)" type = "SCHEDULED" @@ -453,30 +552,26 @@ resource "aws_glue_trigger" "test" { job_name = aws_glue_job.test.name } } -`, testAccAWSGlueJobConfig_Required(rName), enabled, rName) +`, enabled, rName)) } func testAccAWSGlueTriggerConfig_OnDemand(rName string) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_trigger" "test" { - name = "%s" + name = %[1]q type = "ON_DEMAND" actions { job_name = aws_glue_job.test.name } } -`, testAccAWSGlueJobConfig_Required(rName), rName) +`, rName)) } func testAccAWSGlueTriggerConfig_Predicate(rName, state string) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_job" "test2" { - name = "%s2" + name = "%[1]s2" role_arn = aws_iam_role.test.arn command { @@ -487,7 +582,7 @@ resource "aws_glue_job" "test2" { } resource "aws_glue_trigger" "test" { - name = "%s" + name = %[1]q type = "CONDITIONAL" actions { @@ -497,22 +592,20 @@ resource "aws_glue_trigger" "test" { predicate { conditions { job_name = aws_glue_job.test.name - state = "%s" + state = %[2]q } } } -`, testAccAWSGlueJobConfig_Required(rName), rName, rName, state) +`, rName, state)) } func testAccAWSGlueTriggerConfig_Crawler(rName, state string) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccGlueCrawlerConfig_S3Target(rName, "s3://test_bucket"), fmt.Sprintf(` resource "aws_glue_crawler" "test2" { depends_on = [aws_iam_role_policy_attachment.test-AWSGlueServiceRole] database_name = aws_glue_catalog_database.test.name - name = "%scrawl2" + name = "%[1]scrawl2" role = aws_iam_role.test.name s3_target { @@ -521,7 +614,7 @@ resource "aws_glue_crawler" "test2" { } resource "aws_glue_trigger" "test_trigger" { - name = "%strigger" + name = %[1]q type = "CONDITIONAL" actions { @@ -531,31 +624,29 @@ resource "aws_glue_trigger" "test_trigger" { predicate { conditions { crawler_name = aws_glue_crawler.test2.name - crawl_state = "%s" + crawl_state = %[2]q } } } -`, testAccGlueCrawlerConfig_S3Target(rName, "s3://test_bucket"), rName, rName, state) +`, rName, state)) } func testAccAWSGlueTriggerConfig_Schedule(rName, schedule string) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_trigger" "test" { - name = "%s" - schedule = "%s" + name = %[1]q + schedule = %[2]q type = "SCHEDULED" actions { job_name = aws_glue_job.test.name } } -`, testAccAWSGlueJobConfig_Required(rName), rName, schedule) +`, rName, schedule)) } func testAccAWSGlueTriggerConfigTags1(rName, tagKey1, tagValue1 string) string { - return testAccAWSGlueJobConfig_Required(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_trigger" "test" { name = %[1]q type = "ON_DEMAND" @@ -568,11 +659,11 @@ resource "aws_glue_trigger" "test" { %[2]q = %[3]q } } -`, rName, tagKey1, tagValue1) +`, rName, tagKey1, tagValue1)) } func testAccAWSGlueTriggerConfigTags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return testAccAWSGlueJobConfig_Required(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_trigger" "test" { name = %[1]q type = "ON_DEMAND" @@ -586,19 +677,17 @@ resource "aws_glue_trigger" "test" { %[4]q = %[5]q } } -`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) } func testAccAWSGlueTriggerConfig_WorkflowName(rName string) string { - return fmt.Sprintf(` -%s - + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` resource "aws_glue_workflow" test { - name = "%s" + name = %[1]q } resource "aws_glue_trigger" "test" { - name = "%s" + name = %[1]q type = "ON_DEMAND" workflow_name = aws_glue_workflow.test.name @@ -606,5 +695,54 @@ resource "aws_glue_trigger" "test" { job_name = aws_glue_job.test.name } } -`, testAccAWSGlueJobConfig_Required(rName), rName, rName) +`, rName)) +} + +func testAccAWSGlueTriggerConfigActionsNotification(rName string, delay int) string { + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` +resource "aws_glue_trigger" "test" { + name = %[1]q + type = "ON_DEMAND" + + actions { + job_name = aws_glue_job.test.name + + notification_property { + notify_delay_after = %[2]d + } + } +} +`, rName, delay)) +} + +func testAccAWSGlueTriggerConfigActionsSecurityConfiguration(rName string) string { + return composeConfig(testAccAWSGlueJobConfig_Required(rName), fmt.Sprintf(` +resource "aws_glue_security_configuration" "test" { + name = %[1]q + + encryption_configuration { + cloudwatch_encryption { + cloudwatch_encryption_mode = "DISABLED" + } + + job_bookmarks_encryption { + job_bookmarks_encryption_mode = "DISABLED" + } + + s3_encryption { + s3_encryption_mode = "DISABLED" + } + } +} + +resource "aws_glue_trigger" "test" { + name = %[1]q + type = "ON_DEMAND" + + actions { + job_name = aws_glue_job.test.name + security_configuration = aws_glue_security_configuration.test.name + } +} +`, rName)) } diff --git a/website/docs/r/glue_trigger.html.markdown b/website/docs/r/glue_trigger.html.markdown index 37981adc0fb..f6e4cad4092 100644 --- a/website/docs/r/glue_trigger.html.markdown +++ b/website/docs/r/glue_trigger.html.markdown @@ -123,6 +123,12 @@ The following arguments are supported: * `crawler_name` - (Optional) The name of the crawler to be executed. Conflicts with `job_name`. * `job_name` - (Optional) The name of a job to be executed. Conflicts with `crawler_name`. * `timeout` - (Optional) The job run timeout in minutes. It overrides the timeout value of the job. +* `security_configuration` - (Optional) The name of the Security Configuration structure to be used with this action. +* `notification_property` - (Optional) Specifies configuration properties of a job run notification. see [Notification Property](#notification-property) details below. + +#### Notification Property + +* `notify_delay_after` - (Optional) After a job run starts, the number of minutes to wait before sending a job run delay notification. ### predicate Argument Reference