diff --git a/CHANGELOG.md b/CHANGELOG.md index 936eb53df..01bc1d10b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Added - Logging of Kibana action connectors HTTP requests and responses when [Terraform logs are enabled](https://developer.hashicorp.com/terraform/internals/debugging). +- Add `skip_destroy` flag to `elasticstack_fleet_agent_policy` resource ([#357](https://github.com/elastic/terraform-provider-elasticstack/pull/357)) ## [0.6.1] - 2023-05-30 diff --git a/docs/resources/fleet_agent_policy.md b/docs/resources/fleet_agent_policy.md index 5a7039f87..d1a36ae24 100644 --- a/docs/resources/fleet_agent_policy.md +++ b/docs/resources/fleet_agent_policy.md @@ -45,6 +45,7 @@ resource "elasticstack_fleet_agent_policy" "test_policy" { - `monitor_metrics` (Boolean) Enable collection of agent metrics. - `monitoring_output_id` (String) The identifier for monitoring output. - `policy_id` (String) Unique identifier of the agent policy. +- `skip_destroy` (Boolean) Set to true if you do not wish the agent policy to be deleted at destroy time, and instead just remove the agent policy from the Terraform state. - `sys_monitoring` (Boolean) Enable collection of system logs and metrics. ### Read-Only diff --git a/internal/fleet/agent_policy_resource.go b/internal/fleet/agent_policy_resource.go index d78575507..f490ba979 100644 --- a/internal/fleet/agent_policy_resource.go +++ b/internal/fleet/agent_policy_resource.go @@ -5,6 +5,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/internal/clients/fleet" "github.com/elastic/terraform-provider-elasticstack/internal/clients/fleet/fleetapi" + "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -73,6 +74,11 @@ func ResourceAgentPolicy() *schema.Resource { Type: schema.TypeBool, Optional: true, }, + "skip_destroy": { + Description: "Set to true if you do not wish the agent policy to be deleted at destroy time, and instead just remove the agent policy from the Terraform state.", + Type: schema.TypeBool, + Optional: true, + }, } return &schema.Resource{ @@ -264,6 +270,11 @@ func resourceAgentPolicyRead(ctx context.Context, d *schema.ResourceData, meta i } func resourceAgentPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + if d.Get("skip_destroy").(bool) { + tflog.Debug(ctx, "Skipping destroy of Agent Policy", map[string]interface{}{"policy_id": d.Id()}) + return nil + } + fleetClient, diags := getFleetClient(d, meta) if diags.HasError() { return diags diff --git a/internal/fleet/agent_policy_resource_test.go b/internal/fleet/agent_policy_resource_test.go index de146ae8f..8b8e4493f 100644 --- a/internal/fleet/agent_policy_resource_test.go +++ b/internal/fleet/agent_policy_resource_test.go @@ -27,31 +27,57 @@ func TestAccResourceAgentPolicy(t *testing.T) { Steps: []resource.TestStep{ { SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionAgentPolicy), - Config: testAccResourceAgentPolicyCreate(policyName), + Config: testAccResourceAgentPolicyCreate(policyName, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "name", fmt.Sprintf("Policy %s", policyName)), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "namespace", "default"), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "description", "Test Agent Policy"), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_logs", "true"), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_metrics", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "skip_destroy", "false"), ), }, { SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionAgentPolicy), - Config: testAccResourceAgentPolicyUpdate(policyName), + Config: testAccResourceAgentPolicyUpdate(policyName, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "name", fmt.Sprintf("Updated Policy %s", policyName)), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "namespace", "default"), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "description", "This policy was updated"), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_logs", "true"), resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_metrics", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "skip_destroy", "false"), ), }, }, }) } -func testAccResourceAgentPolicyCreate(id string) string { +func TestAccResourceAgentPolicySkipDestroy(t *testing.T) { + policyName := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + CheckDestroy: checkResourceAgentPolicySkipDestroy, + ProtoV5ProviderFactories: acctest.Providers, + Steps: []resource.TestStep{ + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionAgentPolicy), + Config: testAccResourceAgentPolicyCreate(policyName, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "name", fmt.Sprintf("Policy %s", policyName)), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "namespace", "default"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "description", "Test Agent Policy"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_logs", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_metrics", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "skip_destroy", "true"), + ), + }, + }, + }) +} + +func testAccResourceAgentPolicyCreate(id string, skipDestroy bool) string { return fmt.Sprintf(` provider "elasticstack" { elasticsearch {} @@ -64,16 +90,17 @@ resource "elasticstack_fleet_agent_policy" "test_policy" { description = "Test Agent Policy" monitor_logs = true monitor_metrics = true + skip_destroy = %t } data "elasticstack_fleet_enrollment_tokens" "test_policy" { policy_id = elasticstack_fleet_agent_policy.test_policy.policy_id } -`, fmt.Sprintf("Policy %s", id)) +`, fmt.Sprintf("Policy %s", id), skipDestroy) } -func testAccResourceAgentPolicyUpdate(id string) string { +func testAccResourceAgentPolicyUpdate(id string, skipDestroy bool) string { return fmt.Sprintf(` provider "elasticstack" { elasticsearch {} @@ -86,12 +113,13 @@ resource "elasticstack_fleet_agent_policy" "test_policy" { description = "This policy was updated" monitor_logs = true monitor_metrics = true + skip_destroy = %t } data "elasticstack_fleet_enrollment_tokens" "test_policy" { policy_id = elasticstack_fleet_agent_policy.test_policy.policy_id } -`, fmt.Sprintf("Updated Policy %s", id)) +`, fmt.Sprintf("Updated Policy %s", id), skipDestroy) } func checkResourceAgentPolicyDestroy(s *terraform.State) error { @@ -119,3 +147,33 @@ func checkResourceAgentPolicyDestroy(s *terraform.State) error { } return nil } + +func checkResourceAgentPolicySkipDestroy(s *terraform.State) error { + client, err := clients.NewAcceptanceTestingClient() + if err != nil { + return err + } + + for _, rs := range s.RootModule().Resources { + if rs.Type != "elasticstack_fleet_agent_policy" { + continue + } + + fleetClient, err := client.GetFleetClient() + if err != nil { + return err + } + packagePolicy, diag := fleet.ReadAgentPolicy(context.Background(), fleetClient, rs.Primary.ID) + if diag.HasError() { + return fmt.Errorf(diag[0].Summary) + } + if packagePolicy == nil { + return fmt.Errorf("agent policy id=%v does not exist, but should still exist when skip_destroy is true", rs.Primary.ID) + } + + if diag = fleet.DeleteAgentPolicy(context.Background(), fleetClient, rs.Primary.ID); diag.HasError() { + return fmt.Errorf(diag[0].Summary) + } + } + return nil +}