From 4acf84a13242e8e9972df66811b0f6d996bed521 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 26 Mar 2020 10:09:26 +0200 Subject: [PATCH 01/23] create udf resource --- aws/provider.go | 1 + ...resource_aws_glue_user_defined_function.go | 244 ++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 aws/resource_aws_glue_user_defined_function.go diff --git a/aws/provider.go b/aws/provider.go index 8bc6f07a5b48..8988be2beb4e 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -627,6 +627,7 @@ func Provider() *schema.Provider { "aws_glue_job": resourceAwsGlueJob(), "aws_glue_security_configuration": resourceAwsGlueSecurityConfiguration(), "aws_glue_trigger": resourceAwsGlueTrigger(), + "aws_glue_user_defined_function": resourceAwsGlueUserDefinedFunction(), "aws_glue_workflow": resourceAwsGlueWorkflow(), "aws_guardduty_detector": resourceAwsGuardDutyDetector(), "aws_guardduty_publishing_destination": resourceAwsGuardDutyPublishingDestination(), diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go new file mode 100644 index 000000000000..f906668bdc51 --- /dev/null +++ b/aws/resource_aws_glue_user_defined_function.go @@ -0,0 +1,244 @@ +package aws + +import ( + "fmt" + "log" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/glue" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceAwsGlueUserDefinedFunction() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsGlueUserDefinedFunctionCreate, + Read: resourceAwsGlueUserDefinedFunctionRead, + Update: resourceAwsGlueUserDefinedFunctionUpdate, + Delete: resourceAwsGlueUserDefinedFunctionDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "catalog_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "database_name": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "name": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "class_name": { + Type: schema.TypeList, + Required: true, + }, + "owner_name": { + Type: schema.TypeList, + Required: true, + }, + "owner_type": { + Type: schema.TypeList, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + glue.PrincipalTypeGroup, + glue.PrincipalTypeRole, + glue.PrincipalTypeUser, + }, false), + }, + "resource_uris": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + glue.ResourceTypeArchive, + glue.ResourceTypeFile, + glue.ResourceTypeJar, + }, false), + }, + "uri": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "create_time": { + Type: schema.TypeList, + Computed: true, + }, + }, + } +} + +func resourceAwsGlueUserDefinedFunctionCreate(d *schema.ResourceData, meta interface{}) error { + glueconn := meta.(*AWSClient).glueconn + catalogID := createAwsGlueCatalogID(d, meta.(*AWSClient).accountid) + dbName := d.Get("database_name").(string) + funcName := d.Get("name").(string) + + input := &glue.CreateUserDefinedFunctionInput{ + CatalogId: aws.String(catalogID), + DatabaseName: aws.String(dbName), + FunctionInput: expandAwsGlueUserDefinedFunctionInput(d), + } + + _, err := glueconn.CreateUserDefinedFunction(input) + if err != nil { + return fmt.Errorf("error creating Glue User Defined Function: %s", err) + } + + d.SetId(fmt.Sprintf("%s:%s:%s", catalogID, dbName, funcName)) + + return resourceAwsGlueUserDefinedFunctionUpdate(d, meta) +} + +func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta interface{}) error { + glueconn := meta.(*AWSClient).glueconn + + catalogID, dbName, funcName, err := readAwsGlueUDFID(d.Id()) + if err != nil { + return err + } + + input := &glue.UpdateUserDefinedFunctionInput{ + CatalogId: aws.String(catalogID), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + FunctionInput: expandAwsGlueUserDefinedFunctionInput(d), + } + + if d.HasChange("owner_name") || d.HasChange("owner_type") || + d.HasChange("class_name") || d.HasChange("resource_uris") { + if _, err := glueconn.UpdateUserDefinedFunction(input); err != nil { + return err + } + } + + return resourceAwsGlueUserDefinedFunctionRead(d, meta) +} + +func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interface{}) error { + glueconn := meta.(*AWSClient).glueconn + + catalogID, dbName, funcName, err := readAwsGlueUDFID(d.Id()) + if err != nil { + return err + } + + input := &glue.GetUserDefinedFunctionInput{ + CatalogId: aws.String(catalogID), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + } + + out, err := glueconn.GetUserDefinedFunction(input) + if err != nil { + + if isAWSErr(err, glue.ErrCodeEntityNotFoundException, "") { + log.Printf("[WARN] Glue User Defined Function (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + return fmt.Errorf("error reading Glue User Defined Function: %s", err.Error()) + } + + udf := out.UserDefinedFunction + d.Set("name", udf.FunctionName) + d.Set("catalog_id", catalogID) + d.Set("owner_type", udf.OwnerType) + d.Set("owner_name", udf.OwnerName) + d.Set("class_name", udf.ClassName) + if udf.CreateTime != nil { + d.Set("create_time", udf.CreateTime.Format(time.RFC3339)) + } + if err := d.Set("resource_uris", flattenAwsGlueUserDefinedFunctionResourceUri(udf.ResourceUris)); err != nil { + return err + } + + return nil +} + +func resourceAwsGlueUserDefinedFunctionDelete(d *schema.ResourceData, meta interface{}) error { + glueconn := meta.(*AWSClient).glueconn + catalogID, dbName, funcName, err := readAwsGlueUDFID(d.Id()) + if err != nil { + return err + } + + log.Printf("[DEBUG] Glue User Defined Function: %s", d.Id()) + _, err = glueconn.DeleteUserDefinedFunction(&glue.DeleteUserDefinedFunctionInput{ + CatalogId: aws.String(catalogID), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + }) + if err != nil { + return fmt.Errorf("error deleting Glue User Defined Function: %s", err.Error()) + } + return nil +} + +func readAwsGlueUDFID(id string) (catalogID string, dbName string, funcName string, err error) { + idParts := strings.Split(id, ":") + if len(idParts) != 3 { + return "", "", "", fmt.Errorf("unexpected format of ID (%q), expected CATALOG-ID:DATABASE-NAME:FUNCTION-NAME", id) + } + return idParts[0], idParts[1], idParts[2], nil +} + +func expandAwsGlueUserDefinedFunctionInput(d *schema.ResourceData) *glue.UserDefinedFunctionInput { + + udf := &glue.UserDefinedFunctionInput{ + ClassName: aws.String(d.Get("class_name").(string)), + FunctionName: aws.String(d.Get("name").(string)), + OwnerName: aws.String(d.Get("owner_name").(string)), + OwnerType: aws.String(d.Get("owner_type").(string)), + ResourceUris: expandAwsGlueUserDefinedFunctionResourceUri(d.Get("resource_uris").(*schema.Set)), + } + + return udf +} + +func expandAwsGlueUserDefinedFunctionResourceUri(conf *schema.Set) []*glue.ResourceUri { + result := make([]*glue.ResourceUri, 0, conf.Len()) + + for _, r := range conf.List() { + uriRaw := r.(map[string]interface{}) + uri := &glue.ResourceUri{ + ResourceType: aws.String(uriRaw["resource_type"].(string)), + Uri: aws.String(uriRaw["uri"].(string)), + } + + result = append(result, uri) + } + + return result +} + +func flattenAwsGlueUserDefinedFunctionResourceUri(uris []*glue.ResourceUri) []map[string]interface{} { + result := make([]map[string]interface{}, 0, len(uris)) + + for _, i := range uris { + l := map[string]interface{}{ + "resource_type": aws.StringValue(i.ResourceType), + "uri": aws.StringValue(i.Uri), + } + + result = append(result, l) + } + return result +} From f02d4a5cab248a11c91a02b1e449bc923eb53b1d Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 26 Mar 2020 13:37:40 +0200 Subject: [PATCH 02/23] add tests + changes to schema --- ...resource_aws_glue_user_defined_function.go | 37 +++-- ...rce_aws_glue_user_defined_function_test.go | 151 ++++++++++++++++++ 2 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 aws/resource_aws_glue_user_defined_function_test.go diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index f906668bdc51..176a785e8db2 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -34,20 +34,23 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { Required: true, }, "name": { - Type: schema.TypeString, - ForceNew: true, - Required: true, + Type: schema.TypeString, + ForceNew: true, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), }, "class_name": { - Type: schema.TypeList, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), }, "owner_name": { - Type: schema.TypeList, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), }, "owner_type": { - Type: schema.TypeList, + Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ glue.PrincipalTypeGroup, @@ -57,7 +60,8 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { }, "resource_uris": { Type: schema.TypeSet, - Required: true, + Optional: true, + MaxItems: 1000, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "resource_type": { @@ -70,14 +74,15 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { }, false), }, "uri": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 1024), }, }, }, }, "create_time": { - Type: schema.TypeList, + Type: schema.TypeString, Computed: true, }, }, @@ -103,7 +108,7 @@ func resourceAwsGlueUserDefinedFunctionCreate(d *schema.ResourceData, meta inter d.SetId(fmt.Sprintf("%s:%s:%s", catalogID, dbName, funcName)) - return resourceAwsGlueUserDefinedFunctionUpdate(d, meta) + return resourceAwsGlueUserDefinedFunctionRead(d, meta) } func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta interface{}) error { @@ -160,6 +165,7 @@ func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interfa udf := out.UserDefinedFunction d.Set("name", udf.FunctionName) d.Set("catalog_id", catalogID) + d.Set("database_name", dbName) d.Set("owner_type", udf.OwnerType) d.Set("owner_name", udf.OwnerName) d.Set("class_name", udf.ClassName) @@ -207,7 +213,10 @@ func expandAwsGlueUserDefinedFunctionInput(d *schema.ResourceData) *glue.UserDef FunctionName: aws.String(d.Get("name").(string)), OwnerName: aws.String(d.Get("owner_name").(string)), OwnerType: aws.String(d.Get("owner_type").(string)), - ResourceUris: expandAwsGlueUserDefinedFunctionResourceUri(d.Get("resource_uris").(*schema.Set)), + } + + if v, ok := d.GetOk("resource_uris"); ok && v.(*schema.Set).Len() > 0 { + udf.ResourceUris = expandAwsGlueUserDefinedFunctionResourceUri(d.Get("resource_uris").(*schema.Set)) } return udf diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go new file mode 100644 index 000000000000..1de25fc1c40c --- /dev/null +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -0,0 +1,151 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/glue" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { + var udf glue.UserDefinedFunction + rName := acctest.RandomWithPrefix("tf-acc-test") + updated := "test" + resourceName := "aws_glue_user_defined_function.test" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGlueUDFDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), + Destroy: false, + Check: resource.ComposeTestCheckFunc( + testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "class_name", rName), + resource.TestCheckResourceAttr(resourceName, "owner_name", rName), + resource.TestCheckResourceAttr(resourceName, "owner_type", "GROUP"), + resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGlueUserDefinedFunctionBasicConfig(rName, updated), + Destroy: false, + Check: resource.ComposeTestCheckFunc( + testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "class_name", updated), + resource.TestCheckResourceAttr(resourceName, "owner_name", updated), + resource.TestCheckResourceAttr(resourceName, "owner_type", "GROUP"), + resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), + ), + }, + }, + }) +} + +func testAccCheckGlueUDFDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).glueconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_glue_user_defined_function" { + continue + } + + catalogId, dbName, funcName, err := readAwsGlueUDFID(rs.Primary.ID) + if err != nil { + return err + } + + input := &glue.GetUserDefinedFunctionInput{ + CatalogId: aws.String(catalogId), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + } + if _, err := conn.GetUserDefinedFunction(input); err != nil { + //Verify the error is what we want + if isAWSErr(err, glue.ErrCodeEntityNotFoundException, "") { + continue + } + + return err + } + return fmt.Errorf("still exists") + } + return nil +} + +func testAccGlueUserDefinedFunctionBasicConfig(rName string, name string) string { + return fmt.Sprintf(` +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_user_defined_function" "test" { + name = %[1]q + catalog_id = "${aws_glue_catalog_database.test.catalog_id}" + database_name = "${aws_glue_catalog_database.test.name}" + class_name = %[2]q + owner_name = %[2]q + owner_type = "GROUP" + + resource_uris { + resource_type = "ARCHIVE" + uri = %[2]q + } +} +`, rName, name) +} + +func testAccCheckGlueUserDefinedFunctionExists(name string, udf *glue.UserDefinedFunction) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + catalogId, dbName, funcName, err := readAwsGlueUDFID(rs.Primary.ID) + if err != nil { + return err + } + + glueconn := testAccProvider.Meta().(*AWSClient).glueconn + out, err := glueconn.GetUserDefinedFunction(&glue.GetUserDefinedFunctionInput{ + CatalogId: aws.String(catalogId), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + }) + + if err != nil { + return err + } + + if out.UserDefinedFunction == nil { + return fmt.Errorf("No Glue Database Found") + } + + if *out.UserDefinedFunction.FunctionName != funcName { + return fmt.Errorf("Glue UDF Mismatch - existing: %q, state: %q", + *out.UserDefinedFunction.FunctionName, funcName) + } + + *udf = *out.UserDefinedFunction + + return nil + } +} From 6f2cfdbdcec3a6774776c18c360a36ab34cddacc Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 26 Mar 2020 13:54:19 +0200 Subject: [PATCH 03/23] add test for resource uri --- ...rce_aws_glue_user_defined_function_test.go | 94 ++++++++++++++++++- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 1de25fc1c40c..e941ce469e14 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -17,6 +17,7 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") updated := "test" resourceName := "aws_glue_user_defined_function.test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -31,7 +32,6 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "class_name", rName), resource.TestCheckResourceAttr(resourceName, "owner_name", rName), resource.TestCheckResourceAttr(resourceName, "owner_type", "GROUP"), - resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), ), }, { @@ -48,6 +48,48 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "class_name", updated), resource.TestCheckResourceAttr(resourceName, "owner_name", updated), resource.TestCheckResourceAttr(resourceName, "owner_type", "GROUP"), + ), + }, + }, + }) +} + +func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { + var udf glue.UserDefinedFunction + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_glue_user_defined_function.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGlueUDFDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), + Destroy: false, + Check: resource.ComposeTestCheckFunc( + testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGlueUserDefinedFunctionResourceURIConfig2(rName), + Destroy: false, + Check: resource.ComposeTestCheckFunc( + testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "2"), + ), + }, + { + Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), + Destroy: false, + Check: resource.ComposeTestCheckFunc( + testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), ), }, @@ -99,13 +141,57 @@ resource "aws_glue_user_defined_function" "test" { class_name = %[2]q owner_name = %[2]q owner_type = "GROUP" +} +`, rName, name) +} + +func testAccGlueUserDefinedFunctionResourceURIConfig1(rName string) string { + return fmt.Sprintf(` +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_user_defined_function" "test" { + name = %[1]q + catalog_id = "${aws_glue_catalog_database.test.catalog_id}" + database_name = "${aws_glue_catalog_database.test.name}" + class_name = %[1]q + owner_name = %[1]q + owner_type = "GROUP" resource_uris { - resource_type = "ARCHIVE" - uri = %[2]q + resource_type = "ARCHIVE" + uri = %[1]q } } -`, rName, name) +`, rName) +} + +func testAccGlueUserDefinedFunctionResourceURIConfig2(rName string) string { + return fmt.Sprintf(` +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_user_defined_function" "test" { + name = %[1]q + catalog_id = "${aws_glue_catalog_database.test.catalog_id}" + database_name = "${aws_glue_catalog_database.test.name}" + class_name = %[1]q + owner_name = %[1]q + owner_type = "GROUP" + + resource_uris { + resource_type = "ARCHIVE" + uri = %[1]q + } + + resource_uris { + resource_type = "JAR" + uri = %[1]q + } +} +`, rName) } func testAccCheckGlueUserDefinedFunctionExists(name string, udf *glue.UserDefinedFunction) resource.TestCheckFunc { From 7353d0a6b60172c6f0ae0a4487d07a52e7606d19 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 26 Mar 2020 14:53:52 +0200 Subject: [PATCH 04/23] add docs and make catalog id optional --- ...resource_aws_glue_user_defined_function.go | 2 +- .../glue_user_defined_function.html.markdown | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 website/docs/r/glue_user_defined_function.html.markdown diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index 176a785e8db2..325497b3c072 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -26,7 +26,7 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { "catalog_id": { Type: schema.TypeString, ForceNew: true, - Required: true, + Optional: true, }, "database_name": { Type: schema.TypeString, diff --git a/website/docs/r/glue_user_defined_function.html.markdown b/website/docs/r/glue_user_defined_function.html.markdown new file mode 100644 index 000000000000..af864a58176e --- /dev/null +++ b/website/docs/r/glue_user_defined_function.html.markdown @@ -0,0 +1,64 @@ +--- +subcategory: "Glue" +layout: "aws" +page_title: "AWS: aws_glue_user_defined_function" +description: |- + Provides a Glue User Defined Function. +--- + +# Resource: aws_glue_user_defined_function + +Provides a Glue User Defined Function Resource. + +## Example Usage + +```hcl +resource "aws_glue_catalog_database" "example" { + name = "my_database" +} + +resource "aws_glue_user_defined_function" "example" { + name = "my_func" + catalog_id = "${aws_glue_catalog_database.example.catalog_id}" + database_name = "${aws_glue_catalog_database.example.name}" + class_name = "class" + owner_name = "owner" + owner_type = "GROUP" + + resource_uris { + resource_type = "ARCHIVE" + uri = "uri" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the function. +* `catalog_id` - (Optional) ID of the Glue Catalog to create the function in. If omitted, this defaults to the AWS Account ID. +* `database_name` - (Required) The name of the Database to create the Function. +* `class_name` - (Required) The Java class that contains the function code. +* `owner_name` - (Required) The owner of the function. +* `owner_type` - (Required) The owner type. can be one of `USER`, `ROLE`, and `GROUP`. +* `resource_uris` - (Optional) The configuration block for Resource URIs. See [resource uris](#resource-uris) below for more details. + +### Resource URIs + +* `resource_type` - (Required) The type of the resource. can be one of `JAR`, `FILE`, and `ARCHIVE`. +* `uri` - (Required) The URI for accessing the resource. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `create_date`- The time at which the function was created. + +## Import + +Glue User Defined Functions can be imported using the `catalog_id:database_name:function_name`. If you have not set a Catalog ID specify the AWS Account ID that the database is in, e.g. + +``` +$ terraform import aws_glue_user_defined_function.func 123456789012:my_database:my_func +``` From 5748b9073d89dfc8efd78bc52d7359136135e711 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 26 Mar 2020 16:37:56 +0200 Subject: [PATCH 05/23] spacing --- website/docs/r/glue_user_defined_function.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/glue_user_defined_function.html.markdown b/website/docs/r/glue_user_defined_function.html.markdown index af864a58176e..426ed6b1ae38 100644 --- a/website/docs/r/glue_user_defined_function.html.markdown +++ b/website/docs/r/glue_user_defined_function.html.markdown @@ -26,8 +26,8 @@ resource "aws_glue_user_defined_function" "example" { owner_type = "GROUP" resource_uris { - resource_type = "ARCHIVE" - uri = "uri" + resource_type = "ARCHIVE" + uri = "uri" } } ``` From 2148a4f0b8683e8865c077a6d8647e5ac0b418f1 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 30 Apr 2020 12:36:10 +0300 Subject: [PATCH 06/23] add disappears test case --- ...resource_aws_glue_user_defined_function.go | 16 ++--- ...rce_aws_glue_user_defined_function_test.go | 69 +++++++++++++++---- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index 325497b3c072..394fe4e14622 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -90,7 +90,7 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { } func resourceAwsGlueUserDefinedFunctionCreate(d *schema.ResourceData, meta interface{}) error { - glueconn := meta.(*AWSClient).glueconn + conn := meta.(*AWSClient).glueconn catalogID := createAwsGlueCatalogID(d, meta.(*AWSClient).accountid) dbName := d.Get("database_name").(string) funcName := d.Get("name").(string) @@ -101,7 +101,7 @@ func resourceAwsGlueUserDefinedFunctionCreate(d *schema.ResourceData, meta inter FunctionInput: expandAwsGlueUserDefinedFunctionInput(d), } - _, err := glueconn.CreateUserDefinedFunction(input) + _, err := conn.CreateUserDefinedFunction(input) if err != nil { return fmt.Errorf("error creating Glue User Defined Function: %s", err) } @@ -112,7 +112,7 @@ func resourceAwsGlueUserDefinedFunctionCreate(d *schema.ResourceData, meta inter } func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta interface{}) error { - glueconn := meta.(*AWSClient).glueconn + conn := meta.(*AWSClient).glueconn catalogID, dbName, funcName, err := readAwsGlueUDFID(d.Id()) if err != nil { @@ -128,7 +128,7 @@ func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta inter if d.HasChange("owner_name") || d.HasChange("owner_type") || d.HasChange("class_name") || d.HasChange("resource_uris") { - if _, err := glueconn.UpdateUserDefinedFunction(input); err != nil { + if _, err := conn.UpdateUserDefinedFunction(input); err != nil { return err } } @@ -137,7 +137,7 @@ func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta inter } func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interface{}) error { - glueconn := meta.(*AWSClient).glueconn + conn := meta.(*AWSClient).glueconn catalogID, dbName, funcName, err := readAwsGlueUDFID(d.Id()) if err != nil { @@ -150,7 +150,7 @@ func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interfa FunctionName: aws.String(funcName), } - out, err := glueconn.GetUserDefinedFunction(input) + out, err := conn.GetUserDefinedFunction(input) if err != nil { if isAWSErr(err, glue.ErrCodeEntityNotFoundException, "") { @@ -180,14 +180,14 @@ func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interfa } func resourceAwsGlueUserDefinedFunctionDelete(d *schema.ResourceData, meta interface{}) error { - glueconn := meta.(*AWSClient).glueconn + conn := meta.(*AWSClient).glueconn catalogID, dbName, funcName, err := readAwsGlueUDFID(d.Id()) if err != nil { return err } log.Printf("[DEBUG] Glue User Defined Function: %s", d.Id()) - _, err = glueconn.DeleteUserDefinedFunction(&glue.DeleteUserDefinedFunctionInput{ + _, err = conn.DeleteUserDefinedFunction(&glue.DeleteUserDefinedFunctionInput{ CatalogId: aws.String(catalogID), DatabaseName: aws.String(dbName), FunctionName: aws.String(funcName), diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index e941ce469e14..2fc4dcec14c6 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -13,7 +13,6 @@ import ( ) func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { - var udf glue.UserDefinedFunction rName := acctest.RandomWithPrefix("tf-acc-test") updated := "test" resourceName := "aws_glue_user_defined_function.test" @@ -27,7 +26,7 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), Destroy: false, Check: resource.ComposeTestCheckFunc( - testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "class_name", rName), resource.TestCheckResourceAttr(resourceName, "owner_name", rName), @@ -43,7 +42,7 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { Config: testAccGlueUserDefinedFunctionBasicConfig(rName, updated), Destroy: false, Check: resource.ComposeTestCheckFunc( - testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "class_name", updated), resource.TestCheckResourceAttr(resourceName, "owner_name", updated), @@ -55,7 +54,6 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { } func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { - var udf glue.UserDefinedFunction rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_glue_user_defined_function.test" @@ -68,7 +66,7 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), Destroy: false, Check: resource.ComposeTestCheckFunc( - testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), ), }, @@ -81,7 +79,7 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { Config: testAccGlueUserDefinedFunctionResourceURIConfig2(rName), Destroy: false, Check: resource.ComposeTestCheckFunc( - testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "2"), ), }, @@ -89,7 +87,7 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), Destroy: false, Check: resource.ComposeTestCheckFunc( - testAccCheckGlueUserDefinedFunctionExists(resourceName, &udf), + testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), ), }, @@ -97,6 +95,28 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { }) } +func TestAccAWSGlueUserDefinedFunction_disappears(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_glue_user_defined_function.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckGlueUDFDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), + Destroy: false, + Check: resource.ComposeTestCheckFunc( + testAccCheckGlueUserDefinedFunctionExists(resourceName), + testAccCheckGlueUserDefinedFunctionDisappears(resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckGlueUDFDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).glueconn @@ -194,7 +214,7 @@ resource "aws_glue_user_defined_function" "test" { `, rName) } -func testAccCheckGlueUserDefinedFunctionExists(name string, udf *glue.UserDefinedFunction) resource.TestCheckFunc { +func testAccCheckGlueUserDefinedFunctionExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] if !ok { @@ -210,8 +230,8 @@ func testAccCheckGlueUserDefinedFunctionExists(name string, udf *glue.UserDefine return err } - glueconn := testAccProvider.Meta().(*AWSClient).glueconn - out, err := glueconn.GetUserDefinedFunction(&glue.GetUserDefinedFunctionInput{ + conn := testAccProvider.Meta().(*AWSClient).glueconn + out, err := conn.GetUserDefinedFunction(&glue.GetUserDefinedFunctionInput{ CatalogId: aws.String(catalogId), DatabaseName: aws.String(dbName), FunctionName: aws.String(funcName), @@ -230,8 +250,33 @@ func testAccCheckGlueUserDefinedFunctionExists(name string, udf *glue.UserDefine *out.UserDefinedFunction.FunctionName, funcName) } - *udf = *out.UserDefinedFunction - return nil } } + +func testAccCheckGlueUserDefinedFunctionDisappears(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + catalogId, dbName, funcName, err := readAwsGlueUDFID(rs.Primary.ID) + if err != nil { + return err + } + + conn := testAccProvider.Meta().(*AWSClient).glueconn + _, err = conn.DeleteUserDefinedFunction(&glue.DeleteUserDefinedFunctionInput{ + CatalogId: aws.String(catalogId), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + }) + + return err + } +} From ddb96dd898f5dfd18064a4cf278286a1f39b555a Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Thu, 30 Apr 2020 12:38:59 +0300 Subject: [PATCH 07/23] use HasChanges --- aws/resource_aws_glue_user_defined_function.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index 394fe4e14622..fd63d05fa7e6 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -126,8 +126,7 @@ func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta inter FunctionInput: expandAwsGlueUserDefinedFunctionInput(d), } - if d.HasChange("owner_name") || d.HasChange("owner_type") || - d.HasChange("class_name") || d.HasChange("resource_uris") { + if d.HasChanges("owner_name", "owner_type", "class_name", "resource_uris") { if _, err := conn.UpdateUserDefinedFunction(input); err != nil { return err } From f8a0d6bf9e15b6769c259808a4e0fcdbbd465d68 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Tue, 19 May 2020 22:40:00 +0300 Subject: [PATCH 08/23] disappears --- ...rce_aws_glue_user_defined_function_test.go | 109 +++++++----------- 1 file changed, 41 insertions(+), 68 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 2fc4dcec14c6..eb0c2cb7f077 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -109,7 +109,7 @@ func TestAccAWSGlueUserDefinedFunction_disappears(t *testing.T) { Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), - testAccCheckGlueUserDefinedFunctionDisappears(resourceName), + testAccCheckResourceDisappears(testAccProvider, resourceAwsGlueUserDefinedFunction(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -148,6 +148,46 @@ func testAccCheckGlueUDFDestroy(s *terraform.State) error { return nil } +func testAccCheckGlueUserDefinedFunctionExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + catalogId, dbName, funcName, err := readAwsGlueUDFID(rs.Primary.ID) + if err != nil { + return err + } + + conn := testAccProvider.Meta().(*AWSClient).glueconn + out, err := conn.GetUserDefinedFunction(&glue.GetUserDefinedFunctionInput{ + CatalogId: aws.String(catalogId), + DatabaseName: aws.String(dbName), + FunctionName: aws.String(funcName), + }) + + if err != nil { + return err + } + + if out.UserDefinedFunction == nil { + return fmt.Errorf("No Glue Database Found") + } + + if *out.UserDefinedFunction.FunctionName != funcName { + return fmt.Errorf("Glue UDF Mismatch - existing: %q, state: %q", + *out.UserDefinedFunction.FunctionName, funcName) + } + + return nil + } +} + func testAccGlueUserDefinedFunctionBasicConfig(rName string, name string) string { return fmt.Sprintf(` resource "aws_glue_catalog_database" "test" { @@ -213,70 +253,3 @@ resource "aws_glue_user_defined_function" "test" { } `, rName) } - -func testAccCheckGlueUserDefinedFunctionExists(name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s", name) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - catalogId, dbName, funcName, err := readAwsGlueUDFID(rs.Primary.ID) - if err != nil { - return err - } - - conn := testAccProvider.Meta().(*AWSClient).glueconn - out, err := conn.GetUserDefinedFunction(&glue.GetUserDefinedFunctionInput{ - CatalogId: aws.String(catalogId), - DatabaseName: aws.String(dbName), - FunctionName: aws.String(funcName), - }) - - if err != nil { - return err - } - - if out.UserDefinedFunction == nil { - return fmt.Errorf("No Glue Database Found") - } - - if *out.UserDefinedFunction.FunctionName != funcName { - return fmt.Errorf("Glue UDF Mismatch - existing: %q, state: %q", - *out.UserDefinedFunction.FunctionName, funcName) - } - - return nil - } -} - -func testAccCheckGlueUserDefinedFunctionDisappears(name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s", name) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - catalogId, dbName, funcName, err := readAwsGlueUDFID(rs.Primary.ID) - if err != nil { - return err - } - - conn := testAccProvider.Meta().(*AWSClient).glueconn - _, err = conn.DeleteUserDefinedFunction(&glue.DeleteUserDefinedFunctionInput{ - CatalogId: aws.String(catalogId), - DatabaseName: aws.String(dbName), - FunctionName: aws.String(funcName), - }) - - return err - } -} From 0bd38be603011c6d6a6244925dc15ed794c7a1c2 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Tue, 19 May 2020 23:55:12 +0300 Subject: [PATCH 09/23] arn --- aws/resource_aws_glue_user_defined_function.go | 15 +++++++++++++++ ...esource_aws_glue_user_defined_function_test.go | 1 + .../r/glue_user_defined_function.html.markdown | 2 ++ 3 files changed, 18 insertions(+) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index fd63d05fa7e6..3f2673e0a21c 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -7,6 +7,7 @@ import ( "time" "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/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" @@ -23,6 +24,10 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, "catalog_id": { Type: schema.TypeString, ForceNew: true, @@ -162,6 +167,16 @@ func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interfa } udf := out.UserDefinedFunction + + udfArn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "glue", + Region: meta.(*AWSClient).region, + AccountID: meta.(*AWSClient).accountid, + Resource: fmt.Sprintf("userDefinedFunction/%s/%s", dbName, aws.StringValue(udf.FunctionName)), + }.String() + + d.Set("arn", udfArn) d.Set("name", udf.FunctionName) d.Set("catalog_id", catalogID) d.Set("database_name", dbName) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index eb0c2cb7f077..67fa782064ce 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -27,6 +27,7 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "glue", fmt.Sprintf("userDefinedFunction/%s/%s", rName, rName)), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "class_name", rName), resource.TestCheckResourceAttr(resourceName, "owner_name", rName), diff --git a/website/docs/r/glue_user_defined_function.html.markdown b/website/docs/r/glue_user_defined_function.html.markdown index 426ed6b1ae38..6aa5535ae5aa 100644 --- a/website/docs/r/glue_user_defined_function.html.markdown +++ b/website/docs/r/glue_user_defined_function.html.markdown @@ -53,6 +53,8 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: +* `id`- The id of the Glue User Defined Function. +* `arn`- The ARN of the Glue User Defined Function. * `create_date`- The time at which the function was created. ## Import From 68a47568510aa156328a17b2aaf1e9730fc8b18e Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sun, 23 Aug 2020 19:41:37 +0300 Subject: [PATCH 10/23] sdk v2 --- aws/resource_aws_glue_user_defined_function.go | 4 ++-- aws/resource_aws_glue_user_defined_function_test.go | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index 3f2673e0a21c..2157ca390026 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -9,8 +9,8 @@ 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/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func resourceAwsGlueUserDefinedFunction() *schema.Resource { diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 67fa782064ce..ce6e10d7a575 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -6,10 +6,9 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/glue" - - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/terraform" + "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" ) func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { From 7c55f2280e90c87f2cb29e21a79e73da46552638 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sun, 23 Aug 2020 19:43:03 +0300 Subject: [PATCH 11/23] tf 12 syntax for tests and docs --- aws/resource_aws_glue_user_defined_function_test.go | 12 ++++++------ .../docs/r/glue_user_defined_function.html.markdown | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index ce6e10d7a575..b88d10dd460e 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -196,8 +196,8 @@ resource "aws_glue_catalog_database" "test" { resource "aws_glue_user_defined_function" "test" { name = %[1]q - catalog_id = "${aws_glue_catalog_database.test.catalog_id}" - database_name = "${aws_glue_catalog_database.test.name}" + catalog_id = aws_glue_catalog_database.test.catalog_id + database_name = aws_glue_catalog_database.test.name class_name = %[2]q owner_name = %[2]q owner_type = "GROUP" @@ -213,8 +213,8 @@ resource "aws_glue_catalog_database" "test" { resource "aws_glue_user_defined_function" "test" { name = %[1]q - catalog_id = "${aws_glue_catalog_database.test.catalog_id}" - database_name = "${aws_glue_catalog_database.test.name}" + catalog_id = aws_glue_catalog_database.test.catalog_id + database_name = aws_glue_catalog_database.test.name class_name = %[1]q owner_name = %[1]q owner_type = "GROUP" @@ -235,8 +235,8 @@ resource "aws_glue_catalog_database" "test" { resource "aws_glue_user_defined_function" "test" { name = %[1]q - catalog_id = "${aws_glue_catalog_database.test.catalog_id}" - database_name = "${aws_glue_catalog_database.test.name}" + catalog_id = aws_glue_catalog_database.test.catalog_id + database_name = aws_glue_catalog_database.test.name class_name = %[1]q owner_name = %[1]q owner_type = "GROUP" diff --git a/website/docs/r/glue_user_defined_function.html.markdown b/website/docs/r/glue_user_defined_function.html.markdown index 6aa5535ae5aa..bd50721482f1 100644 --- a/website/docs/r/glue_user_defined_function.html.markdown +++ b/website/docs/r/glue_user_defined_function.html.markdown @@ -19,8 +19,8 @@ resource "aws_glue_catalog_database" "example" { resource "aws_glue_user_defined_function" "example" { name = "my_func" - catalog_id = "${aws_glue_catalog_database.example.catalog_id}" - database_name = "${aws_glue_catalog_database.example.name}" + catalog_id = aws_glue_catalog_database.example.catalog_id + database_name = aws_glue_catalog_database.example.name class_name = "class" owner_name = "owner" owner_type = "GROUP" From 05be47a08ff6ee8743b6a683b1dd1d0d8564605c Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sun, 23 Aug 2020 19:44:47 +0300 Subject: [PATCH 12/23] use %w for errors --- ...resource_aws_glue_user_defined_function.go | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index 2157ca390026..8d5e5f1d5d36 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -55,13 +55,9 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { ValidateFunc: validation.StringLenBetween(1, 255), }, "owner_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - glue.PrincipalTypeGroup, - glue.PrincipalTypeRole, - glue.PrincipalTypeUser, - }, false), + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(glue.PrincipalType_Values(), false), }, "resource_uris": { Type: schema.TypeSet, @@ -70,13 +66,9 @@ func resourceAwsGlueUserDefinedFunction() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "resource_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - glue.ResourceTypeArchive, - glue.ResourceTypeFile, - glue.ResourceTypeJar, - }, false), + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(glue.ResourceType_Values(), false), }, "uri": { Type: schema.TypeString, @@ -108,7 +100,7 @@ func resourceAwsGlueUserDefinedFunctionCreate(d *schema.ResourceData, meta inter _, err := conn.CreateUserDefinedFunction(input) if err != nil { - return fmt.Errorf("error creating Glue User Defined Function: %s", err) + return fmt.Errorf("error creating Glue User Defined Function: %w", err) } d.SetId(fmt.Sprintf("%s:%s:%s", catalogID, dbName, funcName)) @@ -163,7 +155,7 @@ func resourceAwsGlueUserDefinedFunctionRead(d *schema.ResourceData, meta interfa return nil } - return fmt.Errorf("error reading Glue User Defined Function: %s", err.Error()) + return fmt.Errorf("error reading Glue User Defined Function: %w", err) } udf := out.UserDefinedFunction @@ -207,7 +199,7 @@ func resourceAwsGlueUserDefinedFunctionDelete(d *schema.ResourceData, meta inter FunctionName: aws.String(funcName), }) if err != nil { - return fmt.Errorf("error deleting Glue User Defined Function: %s", err.Error()) + return fmt.Errorf("error deleting Glue User Defined Function: %w", err) } return nil } From 4dba876c814d2ca1cb81424b09926184f88b2295 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sun, 23 Aug 2020 19:54:04 +0300 Subject: [PATCH 13/23] add docs for arn --- website/docs/index.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index e37cb2664f2a..2942f93fc200 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -265,6 +265,7 @@ for more information about connecting to alternate AWS endpoints or AWS compatib - [`aws_glue_crawler` resource](/docs/providers/aws/r/glue_crawler.html) - [`aws_glue_job` resource](/docs/providers/aws/r/glue_job.html) - [`aws_glue_trigger` resource](/docs/providers/aws/r/glue_trigger.html) + - [`aws_glue_user_defined_function` resource](/docs/providers/aws/r/glue_user_defined_function.html) - [`aws_guardduty_detector` resource](/docs/providers/aws/r/guardduty_detector.html) - [`aws_guardduty_ipset` resource](/docs/providers/aws/r/guardduty_ipset.html) - [`aws_guardduty_threatintelset` resource](/docs/providers/aws/r/guardduty_threatintelset.html) From d345a8c6808780ae9b03340c1c7b082ab8ba382f Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sat, 29 Aug 2020 11:51:47 +0300 Subject: [PATCH 14/23] remove hadchanges --- aws/resource_aws_glue_user_defined_function.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index 8d5e5f1d5d36..e244da3ead86 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -123,10 +123,8 @@ func resourceAwsGlueUserDefinedFunctionUpdate(d *schema.ResourceData, meta inter FunctionInput: expandAwsGlueUserDefinedFunctionInput(d), } - if d.HasChanges("owner_name", "owner_type", "class_name", "resource_uris") { - if _, err := conn.UpdateUserDefinedFunction(input); err != nil { - return err - } + if _, err := conn.UpdateUserDefinedFunction(input); err != nil { + return fmt.Errorf("error updating Glue User Defined Function (%s): %w", d.Id(), err) } return resourceAwsGlueUserDefinedFunctionRead(d, meta) From 84d9a4d304b8373fbe5ea965533a2c2a214a84f9 Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sat, 29 Aug 2020 11:52:34 +0300 Subject: [PATCH 15/23] handle error --- aws/resource_aws_glue_user_defined_function.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function.go b/aws/resource_aws_glue_user_defined_function.go index e244da3ead86..5ddaa773b85d 100644 --- a/aws/resource_aws_glue_user_defined_function.go +++ b/aws/resource_aws_glue_user_defined_function.go @@ -230,7 +230,12 @@ func expandAwsGlueUserDefinedFunctionResourceUri(conf *schema.Set) []*glue.Resou result := make([]*glue.ResourceUri, 0, conf.Len()) for _, r := range conf.List() { - uriRaw := r.(map[string]interface{}) + uriRaw, ok := r.(map[string]interface{}) + + if !ok { + continue + } + uri := &glue.ResourceUri{ ResourceType: aws.String(uriRaw["resource_type"].(string)), Uri: aws.String(uriRaw["uri"].(string)), From a3040946baea3f877b5dfa1d4b00cd863f71f8f7 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:16 +0300 Subject: [PATCH 16/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index b88d10dd460e..41776f6a8c8e 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -176,7 +176,7 @@ func testAccCheckGlueUserDefinedFunctionExists(name string) resource.TestCheckFu } if out.UserDefinedFunction == nil { - return fmt.Errorf("No Glue Database Found") + return fmt.Errorf("No Glue User Defined Function Found") } if *out.UserDefinedFunction.FunctionName != funcName { From 0e026b6d6fb29a9348752c3e181d507d4468ec5f Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:23 +0300 Subject: [PATCH 17/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 41776f6a8c8e..86b5817f1953 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -106,7 +106,6 @@ func TestAccAWSGlueUserDefinedFunction_disappears(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), - Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), testAccCheckResourceDisappears(testAccProvider, resourceAwsGlueUserDefinedFunction(), resourceName), From aed0a5bd2e06624c3e10d77cf7d941236f0bd814 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:29 +0300 Subject: [PATCH 18/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 86b5817f1953..6c9045d3a50a 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -85,7 +85,6 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { }, { Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), - Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), From 4c2a1e84f9d8af4ab68d47893382c05f05cd58b0 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:35 +0300 Subject: [PATCH 19/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 6c9045d3a50a..62ca0eabbb85 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -77,7 +77,6 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { }, { Config: testAccGlueUserDefinedFunctionResourceURIConfig2(rName), - Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "2"), From 989440b197d175615ae2afd9562f869f493add2d Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:41 +0300 Subject: [PATCH 20/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 62ca0eabbb85..7551c8c6b4e2 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -64,7 +64,6 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), - Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), From d691370409f5cf89776243ce8be3e91309af9b9e Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:47 +0300 Subject: [PATCH 21/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 7551c8c6b4e2..685f1a4604e7 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -40,7 +40,6 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { }, { Config: testAccGlueUserDefinedFunctionBasicConfig(rName, updated), - Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", rName), From e919350a2601ce258a9f2a49456e92ad66f01a33 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 29 Aug 2020 11:53:53 +0300 Subject: [PATCH 22/23] Update aws/resource_aws_glue_user_defined_function_test.go Co-authored-by: Brian Flad --- aws/resource_aws_glue_user_defined_function_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 685f1a4604e7..171eff3211f2 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -23,7 +23,6 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), - Destroy: false, Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), testAccCheckResourceAttrRegionalARN(resourceName, "arn", "glue", fmt.Sprintf("userDefinedFunction/%s/%s", rName, rName)), From 9c4483a41edecc312bb3e67d0844aeb401d2a38b Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Sat, 29 Aug 2020 11:56:18 +0300 Subject: [PATCH 23/23] fmt --- aws/resource_aws_glue_user_defined_function_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aws/resource_aws_glue_user_defined_function_test.go b/aws/resource_aws_glue_user_defined_function_test.go index 171eff3211f2..4b1e58963704 100644 --- a/aws/resource_aws_glue_user_defined_function_test.go +++ b/aws/resource_aws_glue_user_defined_function_test.go @@ -22,7 +22,7 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { CheckDestroy: testAccCheckGlueUDFDestroy, Steps: []resource.TestStep{ { - Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), + Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), testAccCheckResourceAttrRegionalARN(resourceName, "arn", "glue", fmt.Sprintf("userDefinedFunction/%s/%s", rName, rName)), @@ -38,7 +38,7 @@ func TestAccAWSGlueUserDefinedFunction_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccGlueUserDefinedFunctionBasicConfig(rName, updated), + Config: testAccGlueUserDefinedFunctionBasicConfig(rName, updated), Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "name", rName), @@ -61,7 +61,7 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { CheckDestroy: testAccCheckGlueUDFDestroy, Steps: []resource.TestStep{ { - Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), + Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), @@ -73,14 +73,14 @@ func TestAccAWSGlueUserDefinedFunction_resource_uri(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccGlueUserDefinedFunctionResourceURIConfig2(rName), + Config: testAccGlueUserDefinedFunctionResourceURIConfig2(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "2"), ), }, { - Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), + Config: testAccGlueUserDefinedFunctionResourceURIConfig1(rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), resource.TestCheckResourceAttr(resourceName, "resource_uris.#", "1"), @@ -100,7 +100,7 @@ func TestAccAWSGlueUserDefinedFunction_disappears(t *testing.T) { CheckDestroy: testAccCheckGlueUDFDestroy, Steps: []resource.TestStep{ { - Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), + Config: testAccGlueUserDefinedFunctionBasicConfig(rName, rName), Check: resource.ComposeTestCheckFunc( testAccCheckGlueUserDefinedFunctionExists(resourceName), testAccCheckResourceDisappears(testAccProvider, resourceAwsGlueUserDefinedFunction(), resourceName),