Skip to content

Commit

Permalink
U-4293 Catalog and Policies v3 tweaks (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
PetrHeinz authored Jan 31, 2025
1 parent f6e6c7f commit e9ff404
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 4 deletions.
14 changes: 13 additions & 1 deletion internal/provider/resource_catalog_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,19 @@ func catalogRecordDelete(ctx context.Context, d *schema.ResourceData, meta inter
}

func catalogRecordCopyAttrs(d *schema.ResourceData, in *catalogRecord) diag.Diagnostics {
if err := d.Set("attribute", flattenCatalogRecordAttributes(in.Attributes)); err != nil {
attributes := flattenCatalogRecordAttributes(in.Attributes)

// Remove item_id, name, and email from attributes if they were not configured, avoid loading them from API
for attributeIndex, attribute := range attributes {
attributeMap := attribute.(map[string]interface{})
for _, field := range []string{"item_id", "name", "email"} {
if value, ok := d.GetOk(fmt.Sprintf("attribute.%d.%s", attributeIndex, field)); !ok || value == "" {
delete(attributeMap, field)
}
}
}

if err := d.Set("attribute", attributes); err != nil {
return diag.FromErr(err)
}
return nil
Expand Down
79 changes: 79 additions & 0 deletions internal/provider/resource_catalog_record_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package provider

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
Expand Down Expand Up @@ -190,3 +193,79 @@ func TestResourceCatalogRecordValidation(t *testing.T) {
})
}
}

func TestResourceCatalogRecordStateCleanup(t *testing.T) {
server := newResourceServer(t, "/api/v2/catalog/relations/123/records", "2")
defer server.Close()

resource.Test(t, resource.TestCase{
IsUnitTest: true,
ProviderFactories: map[string]func() (*schema.Provider, error){
"betteruptime": func() (*schema.Provider, error) {
return New(WithURL(server.URL)), nil
},
},
Steps: []resource.TestStep{
// Step 1 - Create with User type
{
Config: `
provider "betteruptime" {
api_token = "foo"
}
resource "betteruptime_catalog_record" "test" {
relation_id = "123"
attribute {
attribute_id = "789"
type = "User"
email = "test@example.com"
}
}
`,
Check: resource.ComposeTestCheckFunc(
// Simulate API setting computed fields
func(s *terraform.State) error {
rs, ok := s.RootModule().Resources["betteruptime_catalog_record.test"]
if !ok {
return fmt.Errorf("resource not found")
}
rs.Primary.Attributes["attribute.0.item_id"] = "456"
rs.Primary.Attributes["attribute.0.name"] = "Test User"
return nil
},
// Verify all User type fields are present
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.type", "User"),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.email", "test@example.com"),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.item_id", "456"),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.name", "Test User"),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.value", ""),
),
},
// Step 2 - Update to String type, should clean up computed fields
{
Config: `
provider "betteruptime" {
api_token = "foo"
}
resource "betteruptime_catalog_record" "test" {
relation_id = "123"
attribute {
attribute_id = "789"
type = "String"
value = "test@example.com"
}
}
`,
Check: resource.ComposeTestCheckFunc(
// Verify only String type fields are present
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.type", "String"),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.value", "test@example.com"),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.email", ""),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.item_id", ""),
resource.TestCheckResourceAttr("betteruptime_catalog_record.test", "attribute.0.name", ""),
),
},
},
})
}
3 changes: 0 additions & 3 deletions internal/provider/resource_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,16 @@ var metadataValueSchema = map[string]*schema.Schema{
Description: "ID of the referenced item when type is different than String.",
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"name": {
Description: "Human readable name of the referenced item when type is different than String and the item has a name.",
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"email": {
Description: "Email of the referenced user when type is User.",
Type: schema.TypeString,
Optional: true,
Computed: true,
},
}

Expand Down
21 changes: 21 additions & 0 deletions internal/provider/resource_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,32 @@ func resourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta interf

func policyCopyAttrs(d *schema.ResourceData, in *policy) diag.Diagnostics {
var derr diag.Diagnostics

// Remove item_id, name, and email from metadata values in policy steps if they were not configured, avoid loading them from API
if in.Steps != nil {
for stepIndex, step := range *in.Steps {
if step.MetadataValues != nil {
for valueIndex := range *step.MetadataValues {
if value, ok := d.GetOk(fmt.Sprintf("steps.%d.metadata_value.%d.item_id", stepIndex, valueIndex)); !ok || value == "" {
(*(*in.Steps)[stepIndex].MetadataValues)[valueIndex].ItemID = ""
}
if value, ok := d.GetOk(fmt.Sprintf("steps.%d.metadata_value.%d.email", stepIndex, valueIndex)); !ok || value == "" {
(*(*in.Steps)[stepIndex].MetadataValues)[valueIndex].Email = nil
}
if value, ok := d.GetOk(fmt.Sprintf("steps.%d.metadata_value.%d.name", stepIndex, valueIndex)); !ok || value == "" {
(*(*in.Steps)[stepIndex].MetadataValues)[valueIndex].Name = nil
}
}
}
}
}

for _, e := range policyRef(in) {
if err := d.Set(e.k, reflect.Indirect(reflect.ValueOf(e.v)).Interface()); err != nil {
derr = append(derr, diag.FromErr(err)[0])
}
}

return derr
}

Expand Down
84 changes: 84 additions & 0 deletions internal/provider/resource_policy_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package provider

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestResourcePolicy(t *testing.T) {
Expand Down Expand Up @@ -560,3 +562,85 @@ func TestResourcePolicyMetadataValidation(t *testing.T) {
})
}
}

func TestResourcePolicyMetadataValueStateCleanup(t *testing.T) {
server := newResourceServer(t, "/api/v3/policies", "1")
defer server.Close()

resource.Test(t, resource.TestCase{
IsUnitTest: true,
ProviderFactories: map[string]func() (*schema.Provider, error){
"betteruptime": func() (*schema.Provider, error) {
return New(WithURL(server.URL)), nil
},
},
Steps: []resource.TestStep{
// Step 1 - Create with User type
{
Config: `
provider "betteruptime" {
api_token = "foo"
}
resource "betteruptime_policy" "test" {
name = "Test Policy"
steps {
type = "metadata_branching"
metadata_key = "owner"
metadata_value {
type = "User"
email = "test@example.com"
}
}
}
`,
Check: resource.ComposeTestCheckFunc(
// Simulate API setting computed fields
func(s *terraform.State) error {
rs, ok := s.RootModule().Resources["betteruptime_policy.test"]
if !ok {
return fmt.Errorf("resource not found")
}
rs.Primary.Attributes["steps.0.metadata_value.0.item_id"] = "456"
rs.Primary.Attributes["steps.0.metadata_value.0.name"] = "Test User"
return nil
},
// Verify all User type fields are present
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.type", "User"),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.email", "test@example.com"),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.item_id", "456"),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.name", "Test User"),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.value", ""),
),
},
// Step 2 - Update to String type, should clean up computed fields
{
Config: `
provider "betteruptime" {
api_token = "foo"
}
resource "betteruptime_policy" "test" {
name = "Test Policy"
steps {
type = "metadata_branching"
metadata_key = "owner"
metadata_value {
type = "String"
value = "test@example.com"
}
}
}
`,
Check: resource.ComposeTestCheckFunc(
// Verify only String type fields are present
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.type", "String"),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.value", "test@example.com"),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.email", ""),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.item_id", ""),
resource.TestCheckResourceAttr("betteruptime_policy.test", "steps.0.metadata_value.0.name", ""),
),
},
},
})
}

0 comments on commit e9ff404

Please sign in to comment.