From 2579caffdb4f1fca27fd3f2ac30a8bf6a8065c2c Mon Sep 17 00:00:00 2001 From: OneMatchFox Date: Wed, 13 Mar 2019 09:22:44 +0100 Subject: [PATCH] Fix refresh of target if upstream no longer exists (#70) * Fix refresh of target if upstream no longer exists Provider should not throw error when upstream no longer exists as that means that the target no longer exists either. * Adjust documentation of upstream name to match Kong's description Hopefully removes confusion regarding presence of upstream_url on service resource (https://github.com/kevholditch/terraform-provider-kong/issues/52#issuecomment-461586178) * goimports * Code review adjustments --- README.md | 2 +- kong/resource_kong_target.go | 11 +++++--- kong/resource_kong_target_test.go | 42 ++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2d5d6766..6fd83c91 100644 --- a/README.md +++ b/README.md @@ -353,7 +353,7 @@ resource "kong_upstream" "upstream" { } ``` -- `name` is a hostname like name that can be referenced in the upstream_url field of a service. +- `name` is a hostname, which must be equal to the host of a Service. - `slots` is the number of slots in the load balancer algorithm (10-65536, defaults to 10000). - `hash_on` is a hashing input type: `none `(resulting in a weighted-round-robin scheme with no hashing), `consumer`, `ip`, `header`, or `cookie`. Defaults to `none`. - `hash_fallback` is a hashing input type if the primary `hash_on` does not return a hash (eg. header is missing, or no consumer identified). One of: `none`, `consumer`, `ip`, `header`, or `cookie`. Not available if `hash_on` is set to `cookie`. Defaults to `none`. diff --git a/kong/resource_kong_target.go b/kong/resource_kong_target.go index 0dd8a495..9253840a 100644 --- a/kong/resource_kong_target.go +++ b/kong/resource_kong_target.go @@ -55,6 +55,13 @@ func resourceKongTargetCreate(d *schema.ResourceData, meta interface{}) error { func resourceKongTargetRead(d *schema.ResourceData, meta interface{}) error { var ids = strings.Split(d.Id(), "/") + + // First check if the upstream exists. If it does not then the target no longer exists either. + if upstream, _ := meta.(*gokong.KongAdminClient).Upstreams().GetById(ids[0]); upstream == nil { + d.SetId("") + return nil + } + targets, err := meta.(*gokong.KongAdminClient).Targets().GetTargetsFromUpstreamId(ids[0]) if err != nil { @@ -79,9 +86,7 @@ func resourceKongTargetRead(d *schema.ResourceData, meta interface{}) error { func resourceKongTargetDelete(d *schema.ResourceData, meta interface{}) error { var ids = strings.Split(d.Id(), "/") - err := meta.(*gokong.KongAdminClient).Targets().DeleteFromUpstreamById(ids[0], ids[1]) - - if err != nil { + if err := meta.(*gokong.KongAdminClient).Targets().DeleteFromUpstreamById(ids[0], ids[1]); err != nil { return fmt.Errorf("could not delete kong target: %v", err) } diff --git a/kong/resource_kong_target_test.go b/kong/resource_kong_target_test.go index b1bf85bd..e6102eaf 100644 --- a/kong/resource_kong_target_test.go +++ b/kong/resource_kong_target_test.go @@ -60,6 +60,26 @@ func TestAccKongTargetDelete(t *testing.T) { }) } +func TestAccKongTargetCreateAndRefreshFromNonExistentUpstream(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckKongTargetDestroy, + Steps: []resource.TestStep{ + { + Config: testCreateTargetConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckKongTargetExists("kong_target.target"), + resource.TestCheckResourceAttr("kong_target.target", "target", "mytarget:4000"), + resource.TestCheckResourceAttr("kong_target.target", "weight", "100"), + deleteUpstream("kong_upstream.upstream"), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccKongTargetImport(t *testing.T) { resource.Test(t, resource.TestCase{ @@ -160,12 +180,32 @@ func testAccCheckKongTargetDoesNotExist(targetResourceKey string, upstreamResour return fmt.Errorf("no upstream ID is set") } - targets, _ := testAccProvider.Meta().(*gokong.KongAdminClient).Targets().GetTargetsFromUpstreamId(rs.Primary.ID) + targets, err := testAccProvider.Meta().(*gokong.KongAdminClient).Targets().GetTargetsFromUpstreamId(rs.Primary.ID) if len(targets) > 0 { return fmt.Errorf("expecting zero target resources found %v", len(targets)) } + if err != nil { + return fmt.Errorf("error thrown when trying to read target: %v", err) + } + + return nil + } +} + +func deleteUpstream(upstreamResourceKey string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[upstreamResourceKey] + + if !ok { + return fmt.Errorf("not found: %s", upstreamResourceKey) + } + + if err := testAccProvider.Meta().(*gokong.KongAdminClient).Upstreams().DeleteById(rs.Primary.ID); err != nil { + return fmt.Errorf("could not delete kong upstream: %v", err) + } + return nil } }