From 0e7e8b8e40142751920e28d24f4cd585b595b073 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Wed, 1 Feb 2017 13:49:17 -0600 Subject: [PATCH] Closes #11567. Handled Rancher deleted resources. (#11607) * Fix some spec names. * Closes #11567 .Handle deleted/purged resources from Rancher. --- .../rancher/resource_rancher_environment.go | 6 ++ .../resource_rancher_environment_test.go | 47 ++++++++++- .../resource_rancher_registration_token.go | 6 ++ ...esource_rancher_registration_token_test.go | 81 +++++++++++++++++- .../rancher/resource_rancher_registry.go | 6 ++ .../resource_rancher_registry_credential.go | 6 ++ ...source_rancher_registry_credential_test.go | 84 ++++++++++++++++++- .../rancher/resource_rancher_registry_test.go | 84 ++++++++++++++++++- .../rancher/resource_rancher_stack.go | 2 +- .../rancher/resource_rancher_stack_test.go | 53 +++++++++++- builtin/providers/rancher/util.go | 9 ++ 11 files changed, 373 insertions(+), 11 deletions(-) diff --git a/builtin/providers/rancher/resource_rancher_environment.go b/builtin/providers/rancher/resource_rancher_environment.go index 6cbc7af7e122..33ae2913e87d 100644 --- a/builtin/providers/rancher/resource_rancher_environment.go +++ b/builtin/providers/rancher/resource_rancher_environment.go @@ -100,6 +100,12 @@ func resourceRancherEnvironmentRead(d *schema.ResourceData, meta interface{}) er return nil } + if removed(env.State) { + log.Printf("[INFO] Environment %s was removed on %v", d.Id(), env.Removed) + d.SetId("") + return nil + } + log.Printf("[INFO] Environment Name: %s", env.Name) d.Set("description", env.Description) diff --git a/builtin/providers/rancher/resource_rancher_environment_test.go b/builtin/providers/rancher/resource_rancher_environment_test.go index d71fd35d5782..23a49a6ff484 100644 --- a/builtin/providers/rancher/resource_rancher_environment_test.go +++ b/builtin/providers/rancher/resource_rancher_environment_test.go @@ -3,13 +3,14 @@ package rancher import ( "fmt" "testing" + "time" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" rancherClient "github.com/rancher/go-rancher/client" ) -func TestAccRancherEnvironment(t *testing.T) { +func TestAccRancherEnvironment_basic(t *testing.T) { var environment rancherClient.Project resource.Test(t, resource.TestCase{ @@ -39,6 +40,50 @@ func TestAccRancherEnvironment(t *testing.T) { }) } +func TestAccRancherEnvironment_disappears(t *testing.T) { + var environment rancherClient.Project + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRancherEnvironmentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRancherEnvironmentConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherEnvironmentExists("rancher_environment.foo", &environment), + testAccRancherEnvironmentDisappears(&environment), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccRancherEnvironmentDisappears(env *rancherClient.Project) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(*Config) + if err := client.Project.Delete(env); err != nil { + return fmt.Errorf("Error deleting Environment: %s", err) + } + stateConf := &resource.StateChangeConf{ + Pending: []string{"active", "removed", "removing"}, + Target: []string{"removed"}, + Refresh: EnvironmentStateRefreshFunc(client, env.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr := stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for environment (%s) to be removed: %s", env.Id, waitErr) + } + return nil + } +} + func testAccCheckRancherEnvironmentExists(n string, env *rancherClient.Project) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] diff --git a/builtin/providers/rancher/resource_rancher_registration_token.go b/builtin/providers/rancher/resource_rancher_registration_token.go index e6489dda4ba7..2dde85e3cca8 100644 --- a/builtin/providers/rancher/resource_rancher_registration_token.go +++ b/builtin/providers/rancher/resource_rancher_registration_token.go @@ -118,6 +118,12 @@ func resourceRancherRegistrationTokenRead(d *schema.ResourceData, meta interface return nil } + if removed(regT.State) { + log.Printf("[INFO] Registration Token %s was removed on %v", d.Id(), regT.Removed) + d.SetId("") + return nil + } + log.Printf("[INFO] RegistrationToken Name: %s", regT.Name) d.Set("description", regT.Description) diff --git a/builtin/providers/rancher/resource_rancher_registration_token_test.go b/builtin/providers/rancher/resource_rancher_registration_token_test.go index d150158e367a..ea1cbe96d134 100644 --- a/builtin/providers/rancher/resource_rancher_registration_token_test.go +++ b/builtin/providers/rancher/resource_rancher_registration_token_test.go @@ -3,13 +3,14 @@ package rancher import ( "fmt" "testing" + "time" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" rancherClient "github.com/rancher/go-rancher/client" ) -func TestAccRancherRegistrationToken(t *testing.T) { +func TestAccRancherRegistrationToken_basic(t *testing.T) { var registrationToken rancherClient.RegistrationToken resource.Test(t, resource.TestCase{ @@ -47,6 +48,82 @@ func TestAccRancherRegistrationToken(t *testing.T) { }) } +func TestAccRancherRegistrationToken_disappears(t *testing.T) { + var registrationToken rancherClient.RegistrationToken + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRancherRegistrationTokenDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRancherRegistrationTokenConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherRegistrationTokenExists("rancher_registration_token.foo", ®istrationToken), + testAccRancherRegistrationTokenDisappears(®istrationToken), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccRancherRegistrationTokenDisappears(token *rancherClient.RegistrationToken) resource.TestCheckFunc { + return func(s *terraform.State) error { + client, err := testAccProvider.Meta().(*Config).EnvironmentClient(token.AccountId) + if err != nil { + return err + } + + if _, e := client.RegistrationToken.ActionDeactivate(token); e != nil { + return fmt.Errorf("Error deactivating RegistrationToken: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{"active", "inactive", "deactivating"}, + Target: []string{"inactive"}, + Refresh: RegistrationTokenStateRefreshFunc(client, token.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr := stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for registration token (%s) to be deactivated: %s", token.Id, waitErr) + } + + // Update resource to reflect its state + token, err = client.RegistrationToken.ById(token.Id) + if err != nil { + return fmt.Errorf("Failed to refresh state of deactivated registration token (%s): %s", token.Id, err) + } + + // Step 2: Remove + if _, err := client.RegistrationToken.ActionRemove(token); err != nil { + return fmt.Errorf("Error removing RegistrationToken: %s", err) + } + + stateConf = &resource.StateChangeConf{ + Pending: []string{"inactive", "removed", "removing"}, + Target: []string{"removed"}, + Refresh: RegistrationTokenStateRefreshFunc(client, token.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr = stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for registration token (%s) to be removed: %s", token.Id, waitErr) + } + + return nil + } +} + func testAccCheckRancherRegistrationTokenExists(n string, regT *rancherClient.RegistrationToken) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -59,7 +136,7 @@ func testAccCheckRancherRegistrationTokenExists(n string, regT *rancherClient.Re return fmt.Errorf("No App Name is set") } - client := testAccProvider.Meta().(*Config) + client, _ := testAccProvider.Meta().(*Config).EnvironmentClient(rs.Primary.Attributes["environment_id"]) foundRegT, err := client.RegistrationToken.ById(rs.Primary.ID) if err != nil { diff --git a/builtin/providers/rancher/resource_rancher_registry.go b/builtin/providers/rancher/resource_rancher_registry.go index ba452917a07a..d22fd923ebdc 100644 --- a/builtin/providers/rancher/resource_rancher_registry.go +++ b/builtin/providers/rancher/resource_rancher_registry.go @@ -106,6 +106,12 @@ func resourceRancherRegistryRead(d *schema.ResourceData, meta interface{}) error return nil } + if removed(registry.State) { + log.Printf("[INFO] Registry %s was removed on %v", d.Id(), registry.Removed) + d.SetId("") + return nil + } + log.Printf("[INFO] Registry Name: %s", registry.Name) d.Set("description", registry.Description) diff --git a/builtin/providers/rancher/resource_rancher_registry_credential.go b/builtin/providers/rancher/resource_rancher_registry_credential.go index 8187246aa811..37d3ba62a065 100644 --- a/builtin/providers/rancher/resource_rancher_registry_credential.go +++ b/builtin/providers/rancher/resource_rancher_registry_credential.go @@ -120,6 +120,12 @@ func resourceRancherRegistryCredentialRead(d *schema.ResourceData, meta interfac return nil } + if removed(registryCred.State) { + log.Printf("[INFO] Registry Credential %s was removed on %v", d.Id(), registryCred.Removed) + d.SetId("") + return nil + } + log.Printf("[INFO] RegistryCredential Name: %s", registryCred.Name) d.Set("description", registryCred.Description) diff --git a/builtin/providers/rancher/resource_rancher_registry_credential_test.go b/builtin/providers/rancher/resource_rancher_registry_credential_test.go index b5f859f4f047..fd6a42be4bce 100644 --- a/builtin/providers/rancher/resource_rancher_registry_credential_test.go +++ b/builtin/providers/rancher/resource_rancher_registry_credential_test.go @@ -3,13 +3,14 @@ package rancher import ( "fmt" "testing" + "time" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" rancherClient "github.com/rancher/go-rancher/client" ) -func TestAccRancherRegistryCredential(t *testing.T) { +func TestAccRancherRegistryCredential_basic(t *testing.T) { var registry rancherClient.RegistryCredential resource.Test(t, resource.TestCase{ @@ -39,6 +40,83 @@ func TestAccRancherRegistryCredential(t *testing.T) { }) } +func TestAccRancherRegistryCredential_disappears(t *testing.T) { + var registry rancherClient.RegistryCredential + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRancherRegistryCredentialDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRancherRegistryCredentialConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherRegistryCredentialExists("rancher_registry_credential.foo", ®istry), + testAccRancherRegistryCredentialDisappears(®istry), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccRancherRegistryCredentialDisappears(reg *rancherClient.RegistryCredential) resource.TestCheckFunc { + return func(s *terraform.State) error { + client, err := testAccProvider.Meta().(*Config).EnvironmentClient(reg.AccountId) + if err != nil { + return err + } + + // Step 1: Deactivate + if _, e := client.RegistryCredential.ActionDeactivate(reg); e != nil { + return fmt.Errorf("Error deactivating RegistryCredential: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{"active", "inactive", "deactivating"}, + Target: []string{"inactive"}, + Refresh: RegistryCredentialStateRefreshFunc(client, reg.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr := stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for registry credential (%s) to be deactivated: %s", reg.Id, waitErr) + } + + // Update resource to reflect its state + reg, err = client.RegistryCredential.ById(reg.Id) + if err != nil { + return fmt.Errorf("Failed to refresh state of deactivated registry credential (%s): %s", reg.Id, err) + } + + // Step 2: Remove + if _, err := client.RegistryCredential.ActionRemove(reg); err != nil { + return fmt.Errorf("Error removing RegistryCredential: %s", err) + } + + stateConf = &resource.StateChangeConf{ + Pending: []string{"inactive", "removed", "removing"}, + Target: []string{"removed"}, + Refresh: RegistryCredentialStateRefreshFunc(client, reg.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr = stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for registry (%s) to be removed: %s", reg.Id, waitErr) + } + + return nil + } +} + func testAccCheckRancherRegistryCredentialExists(n string, reg *rancherClient.RegistryCredential) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -51,7 +129,7 @@ func testAccCheckRancherRegistryCredentialExists(n string, reg *rancherClient.Re return fmt.Errorf("No App Name is set") } - client := testAccProvider.Meta().(*Config) + client, _ := testAccProvider.Meta().(*Config).RegistryClient(rs.Primary.Attributes["registry_id"]) foundReg, err := client.RegistryCredential.ById(rs.Primary.ID) if err != nil { @@ -59,7 +137,7 @@ func testAccCheckRancherRegistryCredentialExists(n string, reg *rancherClient.Re } if foundReg.Resource.Id != rs.Primary.ID { - return fmt.Errorf("Environment not found") + return fmt.Errorf("RegistryCredential not found") } *reg = *foundReg diff --git a/builtin/providers/rancher/resource_rancher_registry_test.go b/builtin/providers/rancher/resource_rancher_registry_test.go index 308dc20f9192..5550284fb811 100644 --- a/builtin/providers/rancher/resource_rancher_registry_test.go +++ b/builtin/providers/rancher/resource_rancher_registry_test.go @@ -3,13 +3,14 @@ package rancher import ( "fmt" "testing" + "time" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" rancherClient "github.com/rancher/go-rancher/client" ) -func TestAccRancherRegistry(t *testing.T) { +func TestAccRancherRegistry_basic(t *testing.T) { var registry rancherClient.Registry resource.Test(t, resource.TestCase{ @@ -48,6 +49,83 @@ func TestAccRancherRegistry(t *testing.T) { }) } +func TestAccRancherRegistry_disappears(t *testing.T) { + var registry rancherClient.Registry + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRancherRegistryDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRancherRegistryConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherRegistryExists("rancher_registry.foo", ®istry), + testAccRancherRegistryDisappears(®istry), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccRancherRegistryDisappears(reg *rancherClient.Registry) resource.TestCheckFunc { + return func(s *terraform.State) error { + client, err := testAccProvider.Meta().(*Config).EnvironmentClient(reg.AccountId) + if err != nil { + return err + } + + // Step 1: Deactivate + if _, e := client.Registry.ActionDeactivate(reg); e != nil { + return fmt.Errorf("Error deactivating Registry: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{"active", "inactive", "deactivating"}, + Target: []string{"inactive"}, + Refresh: RegistryStateRefreshFunc(client, reg.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr := stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for registry (%s) to be deactivated: %s", reg.Id, waitErr) + } + + // Update resource to reflect its state + reg, err = client.Registry.ById(reg.Id) + if err != nil { + return fmt.Errorf("Failed to refresh state of deactivated registry (%s): %s", reg.Id, err) + } + + // Step 2: Remove + if _, err := client.Registry.ActionRemove(reg); err != nil { + return fmt.Errorf("Error removing Registry: %s", err) + } + + stateConf = &resource.StateChangeConf{ + Pending: []string{"inactive", "removed", "removing"}, + Target: []string{"removed"}, + Refresh: RegistryStateRefreshFunc(client, reg.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr = stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for registry (%s) to be removed: %s", reg.Id, waitErr) + } + + return nil + } +} + func testAccCheckRancherRegistryExists(n string, reg *rancherClient.Registry) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -60,7 +138,7 @@ func testAccCheckRancherRegistryExists(n string, reg *rancherClient.Registry) re return fmt.Errorf("No App Name is set") } - client := testAccProvider.Meta().(*Config) + client, _ := testAccProvider.Meta().(*Config).EnvironmentClient(rs.Primary.Attributes["environment_id"]) foundReg, err := client.Registry.ById(rs.Primary.ID) if err != nil { @@ -68,7 +146,7 @@ func testAccCheckRancherRegistryExists(n string, reg *rancherClient.Registry) re } if foundReg.Resource.Id != rs.Primary.ID { - return fmt.Errorf("Environment not found") + return fmt.Errorf("Registry not found") } *reg = *foundReg diff --git a/builtin/providers/rancher/resource_rancher_stack.go b/builtin/providers/rancher/resource_rancher_stack.go index 028b4f2b5071..50d90ae4857c 100644 --- a/builtin/providers/rancher/resource_rancher_stack.go +++ b/builtin/providers/rancher/resource_rancher_stack.go @@ -138,7 +138,7 @@ func resourceRancherStackRead(d *schema.ResourceData, meta interface{}) error { return nil } - if stack.State == "removed" { + if removed(stack.State) { log.Printf("[INFO] Stack %s was removed on %v", d.Id(), stack.Removed) d.SetId("") return nil diff --git a/builtin/providers/rancher/resource_rancher_stack_test.go b/builtin/providers/rancher/resource_rancher_stack_test.go index d949ebe2597f..189d48395e15 100644 --- a/builtin/providers/rancher/resource_rancher_stack_test.go +++ b/builtin/providers/rancher/resource_rancher_stack_test.go @@ -3,6 +3,7 @@ package rancher import ( "fmt" "testing" + "time" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -114,6 +115,56 @@ func TestAccRancherStack_catalog(t *testing.T) { }) } +func TestAccRancherStack_disappears(t *testing.T) { + var stack rancherClient.Environment + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRancherStackDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRancherStackConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherStackExists("rancher_stack.foo", &stack), + testAccRancherStackDisappears(&stack), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccRancherStackDisappears(stack *rancherClient.Environment) resource.TestCheckFunc { + return func(s *terraform.State) error { + client, err := testAccProvider.Meta().(*Config).EnvironmentClient(stack.AccountId) + if err != nil { + return err + } + + if err := client.Environment.Delete(stack); err != nil { + return fmt.Errorf("Error deleting Stack: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{"active", "removed", "removing"}, + Target: []string{"removed"}, + Refresh: StackStateRefreshFunc(client, stack.Id), + Timeout: 10 * time.Minute, + Delay: 1 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, waitErr := stateConf.WaitForState() + if waitErr != nil { + return fmt.Errorf( + "Error waiting for stack (%s) to be removed: %s", stack.Id, waitErr) + } + + return nil + } +} + func testAccCheckRancherStackExists(n string, stack *rancherClient.Environment) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -126,7 +177,7 @@ func testAccCheckRancherStackExists(n string, stack *rancherClient.Environment) return fmt.Errorf("No App Name is set") } - client := testAccProvider.Meta().(*Config) + client, _ := testAccProvider.Meta().(*Config).EnvironmentClient(rs.Primary.Attributes["environment_id"]) foundStack, err := client.Environment.ById(rs.Primary.ID) if err != nil { diff --git a/builtin/providers/rancher/util.go b/builtin/providers/rancher/util.go index 9e3ce8f1c332..1b7a50c85399 100644 --- a/builtin/providers/rancher/util.go +++ b/builtin/providers/rancher/util.go @@ -2,6 +2,11 @@ package rancher import "github.com/rancher/go-rancher/client" +const ( + REMOVED = "removed" + PURGED = "purged" +) + // GetActiveOrchestration get the name of the active orchestration for a environment func GetActiveOrchestration(project *client.Project) string { orch := "cattle" @@ -17,3 +22,7 @@ func GetActiveOrchestration(project *client.Project) string { return orch } + +func removed(state string) bool { + return state == REMOVED || state == PURGED +}