From 731550703809293ed751054818d7478b7c74a268 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Thu, 5 May 2022 23:01:26 +0200 Subject: [PATCH 01/10] Implement base operations --- internal/provider/provider.go | 3 + internal/service/location/map.go | 186 ++++++++++++++++++++++++++ internal/service/location/map_test.go | 142 ++++++++++++++++++++ 3 files changed, 331 insertions(+) create mode 100644 internal/service/location/map.go create mode 100644 internal/service/location/map_test.go diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 842c03c7618..f5ba97c54c1 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -111,6 +111,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/service/lexmodels" "github.com/hashicorp/terraform-provider-aws/internal/service/licensemanager" "github.com/hashicorp/terraform-provider-aws/internal/service/lightsail" + "github.com/hashicorp/terraform-provider-aws/internal/service/location" "github.com/hashicorp/terraform-provider-aws/internal/service/logs" "github.com/hashicorp/terraform-provider-aws/internal/service/macie" "github.com/hashicorp/terraform-provider-aws/internal/service/macie2" @@ -1607,6 +1608,8 @@ func Provider() *schema.Provider { "aws_lightsail_static_ip": lightsail.ResourceStaticIP(), "aws_lightsail_static_ip_attachment": lightsail.ResourceStaticIPAttachment(), + "aws_location_map": location.ResourceMap(), + "aws_macie_member_account_association": macie.ResourceMemberAccountAssociation(), "aws_macie_s3_bucket_association": macie.ResourceS3BucketAssociation(), diff --git a/internal/service/location/map.go b/internal/service/location/map.go new file mode 100644 index 00000000000..df00bfeb266 --- /dev/null +++ b/internal/service/location/map.go @@ -0,0 +1,186 @@ +package location + +import ( + "fmt" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/locationservice" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" +) + +func ResourceMap() *schema.Resource { + return &schema.Resource{ + Create: resourceMapCreate, + Read: resourceMapRead, + Update: resourceMapUpdate, + Delete: resourceMapDelete, + Schema: map[string]*schema.Schema{ + "configuration": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "style": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 100), + }, + }, + }, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 1000), + }, + "map_arn": { + Type: schema.TypeString, + Computed: true, + }, + "map_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 100), + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceMapCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).LocationConn + // defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig + // tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) + + input := &locationservice.CreateMapInput{} + + if v, ok := d.GetOk("configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + input.Configuration = expandConfiguration(v.([]interface{})[0].(map[string]interface{})) + } + + if v, ok := d.GetOk("description"); ok { + input.Description = aws.String(v.(string)) + } + + if v, ok := d.GetOk("map_name"); ok { + input.MapName = aws.String(v.(string)) + } + + // if len(tags) > 0 { + // input.Tags = Tags(tags.IgnoreAWS()) + // } + + output, err := conn.CreateMap(input) + + if err != nil { + return fmt.Errorf("error creating map: %w", err) + } + + if output == nil { + return fmt.Errorf("error creating map: empty result") + } + + d.SetId(aws.StringValue(output.MapName)) + + return resourceMapRead(d, meta) +} + +func resourceMapRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).LocationConn + + input := &locationservice.DescribeMapInput{ + MapName: aws.String(d.Id()), + } + + output, err := conn.DescribeMap(input) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, locationservice.ErrCodeResourceNotFoundException) { + log.Printf("[WARN] Location Service Map (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error getting Location Service Map (%s): %w", d.Id(), err) + } + + if output == nil { + return fmt.Errorf("error getting Location Service Map (%s): empty response", d.Id()) + } + + d.Set("configuration", []interface{}{flattenConfiguration(output.Configuration)}) + d.Set("create_time", aws.TimeValue(output.CreateTime).Format(time.RFC3339)) + d.Set("description", output.Description) + d.Set("map_arn", output.MapArn) + d.Set("map_name", output.MapName) + d.Set("update_time", aws.TimeValue(output.CreateTime).Format(time.RFC3339)) + + return nil +} + +func resourceMapUpdate(d *schema.ResourceData, meta interface{}) error { + return nil +} + +func resourceMapDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).LocationConn + + input := &locationservice.DeleteMapInput{ + MapName: aws.String(d.Id()), + } + + _, err := conn.DeleteMap(input) + + if tfawserr.ErrCodeEquals(err, locationservice.ErrCodeResourceNotFoundException) { + return nil + } + + if err != nil { + return fmt.Errorf("error deleting Location Service Map (%s): %w", d.Id(), err) + } + + return nil +} + +func expandConfiguration(tfMap map[string]interface{}) *locationservice.MapConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &locationservice.MapConfiguration{} + + if v, ok := tfMap["style"].(string); ok && v != "" { + apiObject.Style = aws.String(v) + } + + return apiObject +} + +func flattenConfiguration(apiObject *locationservice.MapConfiguration) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.Style; v != nil { + tfMap["style"] = aws.StringValue(v) + } + + return tfMap +} diff --git a/internal/service/location/map_test.go b/internal/service/location/map_test.go new file mode 100644 index 00000000000..4e5412bd33b --- /dev/null +++ b/internal/service/location/map_test.go @@ -0,0 +1,142 @@ +package location_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/locationservice" + "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" +) + +func TestAccLocationMap_basic(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_location_map.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccConfigMap_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "configuration.0.style", "VectorHereBerlin"), + acctest.CheckResourceAttrRFC3339(resourceName, "create_time"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + acctest.CheckResourceAttrRegionalARN(resourceName, "map_arn", "geo", fmt.Sprintf("map/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "map_name", rName), + acctest.CheckResourceAttrRFC3339(resourceName, "update_time"), + ), + }, + }, + }) +} + +func TestAccLocationMap_description(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_location_map.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccConfigMap_description(rName, "Test Description"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", "Test Description"), + ), + }, + }, + }) +} + +func testAccCheckMapDestroy(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).LocationConn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_location_map" { + continue + } + + input := &locationservice.DescribeMapInput{ + MapName: aws.String(rs.Primary.ID), + } + + output, err := conn.DescribeMap(input) + + if tfawserr.ErrCodeEquals(err, locationservice.ErrCodeResourceNotFoundException) { + continue + } + + if err != nil { + return fmt.Errorf("error getting Location Service Map (%s): %w", rs.Primary.ID, err) + } + + if output != nil { + return fmt.Errorf("Location Service Map (%s) still exists", rs.Primary.ID) + } + } + + return nil +} + +func testAccCheckMapExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).LocationConn + + input := &locationservice.DescribeMapInput{ + MapName: aws.String(rs.Primary.ID), + } + + _, err := conn.DescribeMap(input) + + if err != nil { + return fmt.Errorf("error getting Location Service Map (%s): %w", rs.Primary.ID, err) + } + + return nil + } +} + +func testAccConfigMap_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_location_map" "test" { + configuration { + style = "VectorHereBerlin" + } + + map_name = %[1]q +} +`, rName) +} + +func testAccConfigMap_description(rName, description string) string { + return fmt.Sprintf(` +resource "aws_location_map" "test" { + configuration { + style = "VectorHereBerlin" + } + + map_name = %[1]q + description = %[2]q +} +`, rName, description) +} From 60115c8264f03f9df780ba060ebc08dc4ebb52c1 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Thu, 5 May 2022 23:28:49 +0200 Subject: [PATCH 02/10] Implement update operation --- internal/service/location/map.go | 20 +++++++++++++++++++- internal/service/location/map_test.go | 11 +++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/internal/service/location/map.go b/internal/service/location/map.go index df00bfeb266..77bd01c2e60 100644 --- a/internal/service/location/map.go +++ b/internal/service/location/map.go @@ -134,7 +134,25 @@ func resourceMapRead(d *schema.ResourceData, meta interface{}) error { } func resourceMapUpdate(d *schema.ResourceData, meta interface{}) error { - return nil + conn := meta.(*conns.AWSClient).LocationConn + + if d.HasChange("description") { + input := &locationservice.UpdateMapInput{ + MapName: aws.String(d.Id()), + } + + if v, ok := d.GetOk("description"); ok { + input.Description = aws.String(v.(string)) + } + + _, err := conn.UpdateMap(input) + + if err != nil { + return fmt.Errorf("error updating Location Service Map (%s): %w", d.Id(), err) + } + } + + return resourceMapRead(d, meta) } func resourceMapDelete(d *schema.ResourceData, meta interface{}) error { diff --git a/internal/service/location/map_test.go b/internal/service/location/map_test.go index 4e5412bd33b..48ad2b2c893 100644 --- a/internal/service/location/map_test.go +++ b/internal/service/location/map_test.go @@ -52,10 +52,17 @@ func TestAccLocationMap_description(t *testing.T) { CheckDestroy: testAccCheckMapDestroy, Steps: []resource.TestStep{ { - Config: testAccConfigMap_description(rName, "Test Description"), + Config: testAccConfigMap_description(rName, "description1"), Check: resource.ComposeTestCheckFunc( testAccCheckMapExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "description", "Test Description"), + resource.TestCheckResourceAttr(resourceName, "description", "description1"), + ), + }, + { + Config: testAccConfigMap_description(rName, "description2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", "description2"), ), }, }, From 96ceb23c031ec9d8be1d36179374498bdd349399 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Thu, 5 May 2022 23:29:20 +0200 Subject: [PATCH 03/10] Check if configuration is nil before setting --- internal/service/location/map.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/service/location/map.go b/internal/service/location/map.go index 77bd01c2e60..ba3135be092 100644 --- a/internal/service/location/map.go +++ b/internal/service/location/map.go @@ -123,7 +123,12 @@ func resourceMapRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error getting Location Service Map (%s): empty response", d.Id()) } - d.Set("configuration", []interface{}{flattenConfiguration(output.Configuration)}) + if output.Configuration != nil { + d.Set("configuration", []interface{}{flattenConfiguration(output.Configuration)}) + } else { + d.Set("configuration", nil) + } + d.Set("create_time", aws.TimeValue(output.CreateTime).Format(time.RFC3339)) d.Set("description", output.Description) d.Set("map_arn", output.MapArn) From 08532549249b959fe6892df6f4ef9be8ef2ca7b6 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Thu, 5 May 2022 23:56:38 +0200 Subject: [PATCH 04/10] Support tags & importer --- internal/service/location/generate.go | 4 + internal/service/location/map.go | 38 +++++++-- internal/service/location/map_test.go | 111 ++++++++++++++++++++++++++ internal/service/location/tags_gen.go | 58 ++++++++++++++ 4 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 internal/service/location/generate.go create mode 100644 internal/service/location/tags_gen.go diff --git a/internal/service/location/generate.go b/internal/service/location/generate.go new file mode 100644 index 00000000000..86ff1b32d8c --- /dev/null +++ b/internal/service/location/generate.go @@ -0,0 +1,4 @@ +//go:generate go run ../../generate/tags/main.go -ServiceTagsMap -UpdateTags +// ONLY generate directives and package declaration! Do not add anything else to this file. + +package location diff --git a/internal/service/location/map.go b/internal/service/location/map.go index ba3135be092..6a79fe055f5 100644 --- a/internal/service/location/map.go +++ b/internal/service/location/map.go @@ -11,6 +11,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/verify" ) func ResourceMap() *schema.Resource { @@ -19,6 +21,9 @@ func ResourceMap() *schema.Resource { Read: resourceMapRead, Update: resourceMapUpdate, Delete: resourceMapDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "configuration": { Type: schema.TypeList, @@ -58,14 +63,17 @@ func ResourceMap() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "tags": tftags.TagsSchema(), + "tags_all": tftags.TagsSchemaComputed(), }, + CustomizeDiff: verify.SetTagsDiff, } } func resourceMapCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).LocationConn - // defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig - // tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) + defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig + tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) input := &locationservice.CreateMapInput{} @@ -81,9 +89,9 @@ func resourceMapCreate(d *schema.ResourceData, meta interface{}) error { input.MapName = aws.String(v.(string)) } - // if len(tags) > 0 { - // input.Tags = Tags(tags.IgnoreAWS()) - // } + if len(tags) > 0 { + input.Tags = Tags(tags.IgnoreAWS()) + } output, err := conn.CreateMap(input) @@ -102,6 +110,8 @@ func resourceMapCreate(d *schema.ResourceData, meta interface{}) error { func resourceMapRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*conns.AWSClient).LocationConn + defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig + ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig input := &locationservice.DescribeMapInput{ MapName: aws.String(d.Id()), @@ -135,6 +145,16 @@ func resourceMapRead(d *schema.ResourceData, meta interface{}) error { d.Set("map_name", output.MapName) d.Set("update_time", aws.TimeValue(output.CreateTime).Format(time.RFC3339)) + tags := KeyValueTags(output.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) + + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return fmt.Errorf("error setting tags: %w", err) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return fmt.Errorf("error setting tags_all: %w", err) + } + return nil } @@ -157,6 +177,14 @@ func resourceMapUpdate(d *schema.ResourceData, meta interface{}) error { } } + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") + + if err := UpdateTags(conn, d.Get("map_arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags for Location Service Map (%s): %w", d.Id(), err) + } + } + return resourceMapRead(d, meta) } diff --git a/internal/service/location/map_test.go b/internal/service/location/map_test.go index 48ad2b2c893..f4f326815b9 100644 --- a/internal/service/location/map_test.go +++ b/internal/service/location/map_test.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tflocation "github.com/hashicorp/terraform-provider-aws/internal/service/location" ) func TestAccLocationMap_basic(t *testing.T) { @@ -35,8 +36,36 @@ func TestAccLocationMap_basic(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, "map_arn", "geo", fmt.Sprintf("map/%s", rName)), resource.TestCheckResourceAttr(resourceName, "map_name", rName), acctest.CheckResourceAttrRFC3339(resourceName, "update_time"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccLocationMap_disappears(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_location_map.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccConfigMap_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tflocation.ResourceMap(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, }, }) } @@ -58,6 +87,11 @@ func TestAccLocationMap_description(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "description", "description1"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccConfigMap_description(rName, "description2"), Check: resource.ComposeTestCheckFunc( @@ -69,6 +103,50 @@ func TestAccLocationMap_description(t *testing.T) { }) } +func TestAccLocationMap_tags(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_location_map.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccConfigMap_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccConfigMap_tags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccConfigMap_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMapExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func testAccCheckMapDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).LocationConn @@ -147,3 +225,36 @@ resource "aws_location_map" "test" { } `, rName, description) } + +func testAccConfigMap_tags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_location_map" "test" { + configuration { + style = "VectorHereBerlin" + } + + map_name = %[1]q + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccConfigMap_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_location_map" "test" { + configuration { + style = "VectorHereBerlin" + } + + map_name = %[1]q + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} diff --git a/internal/service/location/tags_gen.go b/internal/service/location/tags_gen.go new file mode 100644 index 00000000000..f870f844d21 --- /dev/null +++ b/internal/service/location/tags_gen.go @@ -0,0 +1,58 @@ +// Code generated by internal/generate/tags/main.go; DO NOT EDIT. +package location + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/locationservice" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" +) + +// map[string]*string handling + +// Tags returns location service tags. +func Tags(tags tftags.KeyValueTags) map[string]*string { + return aws.StringMap(tags.Map()) +} + +// KeyValueTags creates KeyValueTags from location service tags. +func KeyValueTags(tags map[string]*string) tftags.KeyValueTags { + return tftags.New(tags) +} + +// UpdateTags updates location service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func UpdateTags(conn *locationservice.LocationService, identifier string, oldTagsMap interface{}, newTagsMap interface{}) error { + oldTags := tftags.New(oldTagsMap) + newTags := tftags.New(newTagsMap) + + if removedTags := oldTags.Removed(newTags); len(removedTags) > 0 { + input := &locationservice.UntagResourceInput{ + ResourceArn: aws.String(identifier), + TagKeys: aws.StringSlice(removedTags.IgnoreAWS().Keys()), + } + + _, err := conn.UntagResource(input) + + if err != nil { + return fmt.Errorf("error untagging resource (%s): %w", identifier, err) + } + } + + if updatedTags := oldTags.Updated(newTags); len(updatedTags) > 0 { + input := &locationservice.TagResourceInput{ + ResourceArn: aws.String(identifier), + Tags: Tags(updatedTags.IgnoreAWS()), + } + + _, err := conn.TagResource(input) + + if err != nil { + return fmt.Errorf("error tagging resource (%s): %w", identifier, err) + } + } + + return nil +} From 8b690f7211ac025a34f2d648a02c29d673d2e700 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Fri, 6 May 2022 18:10:05 +0200 Subject: [PATCH 05/10] Use acctest.ProviderFactories --- internal/service/location/map_test.go | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/internal/service/location/map_test.go b/internal/service/location/map_test.go index f4f326815b9..a0b76d1270b 100644 --- a/internal/service/location/map_test.go +++ b/internal/service/location/map_test.go @@ -20,10 +20,10 @@ func TestAccLocationMap_basic(t *testing.T) { resourceName := "aws_location_map.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckMapDestroy, + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckMapDestroy, Steps: []resource.TestStep{ { Config: testAccConfigMap_basic(rName), @@ -53,10 +53,10 @@ func TestAccLocationMap_disappears(t *testing.T) { resourceName := "aws_location_map.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckMapDestroy, + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckMapDestroy, Steps: []resource.TestStep{ { Config: testAccConfigMap_basic(rName), @@ -75,10 +75,10 @@ func TestAccLocationMap_description(t *testing.T) { resourceName := "aws_location_map.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckMapDestroy, + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckMapDestroy, Steps: []resource.TestStep{ { Config: testAccConfigMap_description(rName, "description1"), @@ -108,10 +108,10 @@ func TestAccLocationMap_tags(t *testing.T) { resourceName := "aws_location_map.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckMapDestroy, + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, locationservice.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckMapDestroy, Steps: []resource.TestStep{ { Config: testAccConfigMap_tags1(rName, "key1", "value1"), From a88ccc5ea0334aa111fa523622a51005ee20f8f3 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Fri, 6 May 2022 18:10:36 +0200 Subject: [PATCH 06/10] Create documentation page --- website/docs/r/location_map.html.markdown | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 website/docs/r/location_map.html.markdown diff --git a/website/docs/r/location_map.html.markdown b/website/docs/r/location_map.html.markdown new file mode 100644 index 00000000000..c46209ea005 --- /dev/null +++ b/website/docs/r/location_map.html.markdown @@ -0,0 +1,58 @@ +--- +subcategory: "Location" +layout: "aws" +page_title: "AWS: aws_location_map" +description: |- + Provides a Location Service Map. +--- + +# Resource: aws_location_map + +Provides a Location Service Map. + +## Example Usage + +```terraform +resource "aws_location_map" "example" { + configuration { + style = "VectorHereBerlin" + } + + map_name = "example" +} +``` + +## Argument Reference + +The following arguments are required: + +* `configuration` - (Required) Configuration block with the map style selected from an available data provider. Detailed below. +* `map_name` - (Required) The name for the map resource. + +The following arguments are optional: + +* `description` - (Optional) An optional description for the map resource. +* `tags` - (Optional) Key-value tags for the map. If configured with a provider [`default_tags` configuration block](https://www.terraform.io/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `map_arn` - The Amazon Resource Name (ARN) for the map resource. Used to specify a resource across all AWS. +* `create_time` - The timestamp for when the map resource was created in ISO 8601 format. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://www.terraform.io/docs/providers/aws/index.html#default_tags-configuration-block). +* `update_time` - The timestamp for when the map resource was last update in ISO 8601. + +## configuration + +The following arguments are required: + +* `style` - (Required) Specifies the map style selected from an available data provider. Valid values can be found in the [Location Service CreateMap API Reference](https://docs.aws.amazon.com/location-maps/latest/APIReference/API_CreateMap.html). + +## Import + +`aws_location_map` resources can be imported using the map name, e.g.: + +``` +$ terraform import aws_imagebuilder_image_pipeline.example example +``` From 4be1aa376f59b4864004a3f7ec545f259b6128c5 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Fri, 6 May 2022 18:12:30 +0200 Subject: [PATCH 07/10] Make configuration.style argument force new resource --- internal/service/location/map.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/service/location/map.go b/internal/service/location/map.go index 6a79fe055f5..25dd22e5bf0 100644 --- a/internal/service/location/map.go +++ b/internal/service/location/map.go @@ -35,6 +35,7 @@ func ResourceMap() *schema.Resource { "style": { Type: schema.TypeString, Required: true, + ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 100), }, }, From a6bee5e0abc4b7e6ba5d73e19374ddc359111c83 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Fri, 6 May 2022 18:13:32 +0200 Subject: [PATCH 08/10] Use output.UpdateTime instead of output.CreateTime --- internal/service/location/map.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/location/map.go b/internal/service/location/map.go index 25dd22e5bf0..fe389dbbb7b 100644 --- a/internal/service/location/map.go +++ b/internal/service/location/map.go @@ -144,7 +144,7 @@ func resourceMapRead(d *schema.ResourceData, meta interface{}) error { d.Set("description", output.Description) d.Set("map_arn", output.MapArn) d.Set("map_name", output.MapName) - d.Set("update_time", aws.TimeValue(output.CreateTime).Format(time.RFC3339)) + d.Set("update_time", aws.TimeValue(output.UpdateTime).Format(time.RFC3339)) tags := KeyValueTags(output.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) From 59e20a7b36f3251f5b444f244eb37c895333f282 Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Fri, 6 May 2022 18:15:12 +0200 Subject: [PATCH 09/10] Add changelog --- .changelog/24682.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/24682.txt diff --git a/.changelog/24682.txt b/.changelog/24682.txt new file mode 100644 index 00000000000..af66266da7d --- /dev/null +++ b/.changelog/24682.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_location_map +``` From 730a03edda05dff99a30ea59a469728b38a60d7d Mon Sep 17 00:00:00 2001 From: Kamil Turek Date: Fri, 6 May 2022 18:28:02 +0200 Subject: [PATCH 10/10] Fix import section in docs --- website/docs/r/location_map.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/location_map.html.markdown b/website/docs/r/location_map.html.markdown index c46209ea005..35a4d150aa7 100644 --- a/website/docs/r/location_map.html.markdown +++ b/website/docs/r/location_map.html.markdown @@ -54,5 +54,5 @@ The following arguments are required: `aws_location_map` resources can be imported using the map name, e.g.: ``` -$ terraform import aws_imagebuilder_image_pipeline.example example +$ terraform import aws_location_map.example example ```