diff --git a/aws/resource_aws_appmesh_test.go b/aws/resource_aws_appmesh_test.go index 03ead6d8beb..645a92babe9 100644 --- a/aws/resource_aws_appmesh_test.go +++ b/aws/resource_aws_appmesh_test.go @@ -24,6 +24,7 @@ func TestAccAWSAppmesh(t *testing.T) { }, "VirtualRouter": { "basic": testAccAwsAppmeshVirtualRouter_basic, + "tags": testAccAwsAppmeshVirtualRouter_tags, }, "VirtualService": { "virtualNode": testAccAwsAppmeshVirtualService_virtualNode, diff --git a/aws/resource_aws_appmesh_virtual_router.go b/aws/resource_aws_appmesh_virtual_router.go index 66742a11f19..c4a4f6188cc 100644 --- a/aws/resource_aws_appmesh_virtual_router.go +++ b/aws/resource_aws_appmesh_virtual_router.go @@ -110,6 +110,8 @@ func resourceAwsAppmeshVirtualRouter() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "tags": tagsSchema(), }, } } @@ -121,6 +123,7 @@ func resourceAwsAppmeshVirtualRouterCreate(d *schema.ResourceData, meta interfac MeshName: aws.String(d.Get("mesh_name").(string)), VirtualRouterName: aws.String(d.Get("name").(string)), Spec: expandAppmeshVirtualRouterSpec(d.Get("spec").([]interface{})), + Tags: tagsFromMapAppmesh(d.Get("tags").(map[string]interface{})), } log.Printf("[DEBUG] Creating App Mesh virtual router: %#v", req) @@ -165,6 +168,16 @@ func resourceAwsAppmeshVirtualRouterRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("error setting spec: %s", err) } + err = saveTagsAppmesh(conn, d, aws.StringValue(resp.VirtualRouter.Metadata.Arn)) + if isAWSErr(err, appmesh.ErrCodeNotFoundException, "") { + log.Printf("[WARN] App Mesh virtual router (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("error saving tags: %s", err) + } + return nil } @@ -186,6 +199,16 @@ func resourceAwsAppmeshVirtualRouterUpdate(d *schema.ResourceData, meta interfac } } + err := setTagsAppmesh(conn, d, d.Get("arn").(string)) + if isAWSErr(err, appmesh.ErrCodeNotFoundException, "") { + log.Printf("[WARN] App Mesh virtual router (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + return resourceAwsAppmeshVirtualRouterRead(d, meta) } diff --git a/aws/resource_aws_appmesh_virtual_router_test.go b/aws/resource_aws_appmesh_virtual_router_test.go index 28813fbc5a9..e8911bb9319 100644 --- a/aws/resource_aws_appmesh_virtual_router_test.go +++ b/aws/resource_aws_appmesh_virtual_router_test.go @@ -151,6 +151,62 @@ func testAccAwsAppmeshVirtualRouter_basic(t *testing.T) { }) } +func testAccAwsAppmeshVirtualRouter_tags(t *testing.T) { + var vr appmesh.VirtualRouterData + resourceName := "aws_appmesh_virtual_router.foo" + meshName := fmt.Sprintf("tf-test-mesh-%d", acctest.RandInt()) + vrName := fmt.Sprintf("tf-test-router-%d", acctest.RandInt()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAppmeshVirtualRouterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAppmeshVirtualRouterConfig_tags(meshName, vrName, "foo", "bar", "good", "bad"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshVirtualRouterExists( + resourceName, &vr), + resource.TestCheckResourceAttr( + resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr( + resourceName, "tags.foo", "bar"), + resource.TestCheckResourceAttr( + resourceName, "tags.good", "bad"), + ), + }, + { + Config: testAccAppmeshVirtualRouterConfig_tags(meshName, vrName, "foo2", "bar", "good", "bad2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshVirtualRouterExists( + resourceName, &vr), + resource.TestCheckResourceAttr( + resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr( + resourceName, "tags.foo2", "bar"), + resource.TestCheckResourceAttr( + resourceName, "tags.good", "bad2"), + ), + }, + { + Config: testAccAppmeshVirtualRouterConfig_basic(meshName, vrName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAppmeshVirtualRouterExists( + resourceName, &vr), + resource.TestCheckResourceAttr( + resourceName, "tags.%", "0"), + ), + }, + { + ResourceName: resourceName, + ImportStateId: fmt.Sprintf("%s/%s", meshName, vrName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckAppmeshVirtualRouterDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).appmeshconn @@ -244,3 +300,30 @@ resource "aws_appmesh_virtual_router" "foo" { } `, meshName, vrName) } + +func testAccAppmeshVirtualRouterConfig_tags(meshName, vrName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_appmesh_mesh" "foo" { + name = "%[1]s" +} + +resource "aws_appmesh_virtual_router" "foo" { + name = "%[2]s" + mesh_name = "${aws_appmesh_mesh.foo.id}" + + spec { + listener { + port_mapping { + port = 8080 + protocol = "http" + } + } + } + + tags = { + %[3]s = %[4]q + %[5]s = %[6]q + } +} +`, meshName, vrName, tagKey1, tagValue1, tagKey2, tagValue2) +} diff --git a/website/docs/r/appmesh_virtual_router.html.markdown b/website/docs/r/appmesh_virtual_router.html.markdown index 3747180c8a7..319b0a7bf2f 100644 --- a/website/docs/r/appmesh_virtual_router.html.markdown +++ b/website/docs/r/appmesh_virtual_router.html.markdown @@ -47,6 +47,7 @@ The following arguments are supported: * `name` - (Required) The name to use for the virtual router. * `mesh_name` - (Required) The name of the service mesh in which to create the virtual router. * `spec` - (Required) The virtual router specification to apply. +* `tags` - (Optional) A mapping of tags to assign to the resource. The `spec` object supports the following: