Skip to content

Commit

Permalink
Fix tenant tags producing inconsistent result after apply after updat…
Browse files Browse the repository at this point in the history
…ing to plugin framework (#817)

* fix: Tenant tags producing incosistent result after apply after updating to plugin framework

* Update docs and test
  • Loading branch information
mik-ky authored Nov 19, 2024
1 parent 696ec1f commit e688aa7
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 30 deletions.
2 changes: 1 addition & 1 deletion docs/data-sources/tenants.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ Read-Only:
- `id` (String) The unique ID for this resource.
- `name` (String) The name of this resource.
- `space_id` (String) The space ID associated with this tenant.
- `tenant_tags` (List of String) A list of tenant tags associated with this resource.
- `tenant_tags` (Set of String) A list of tenant tags associated with this resource.


2 changes: 1 addition & 1 deletion docs/resources/tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This resource manages tenants in Octopus Deploy.
- `cloned_from_tenant_id` (String) The ID of the tenant from which this tenant was cloned.
- `description` (String) The description of this tenant.
- `space_id` (String) The space ID associated with this tenant.
- `tenant_tags` (List of String) A list of tenant tags associated with this resource.
- `tenant_tags` (Set of String) A list of tenant tags associated with this resource.

### Read-Only

Expand Down
38 changes: 22 additions & 16 deletions octopusdeploy_framework/resource_tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ package octopusdeploy_framework
import (
"context"
"fmt"

"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tenants"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal/errors"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
"sort"
)

type tenantTypeResource struct {
Expand Down Expand Up @@ -48,7 +48,7 @@ func (r *tenantTypeResource) Create(ctx context.Context, req resource.CreateRequ
return
}

tenant, err := mapStateToTenant(data)
tenant, err := mapStateToTenant(ctx, data)
if err != nil {
return
}
Expand All @@ -61,7 +61,7 @@ func (r *tenantTypeResource) Create(ctx context.Context, req resource.CreateRequ
return
}

mapTenantToState(data, createdTenant)
mapTenantToState(ctx, data, createdTenant)

tflog.Info(ctx, fmt.Sprintf("Tenant created (%s)", data.ID))
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
Expand All @@ -85,7 +85,7 @@ func (r *tenantTypeResource) Read(ctx context.Context, req resource.ReadRequest,
return
}

mapTenantToState(data, tenant)
mapTenantToState(ctx, data, tenant)

tflog.Info(ctx, fmt.Sprintf("Tenant read (%s)", tenant.GetID()))
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
Expand All @@ -106,7 +106,7 @@ func (r *tenantTypeResource) Update(ctx context.Context, req resource.UpdateRequ

tenantFromApi, err := tenants.GetByID(r.Config.Client, data.SpaceID.ValueString(), data.ID.ValueString())

tenant, err := mapStateToTenant(data)
tenant, err := mapStateToTenant(ctx, data)
tenant.ID = state.ID.ValueString()
if err != nil {
resp.Diagnostics.AddError("unable to map to tenant", err.Error())
Expand All @@ -122,7 +122,7 @@ func (r *tenantTypeResource) Update(ctx context.Context, req resource.UpdateRequ
return
}

mapTenantToState(data, updatedTenant)
mapTenantToState(ctx, data, updatedTenant)

tflog.Info(ctx, fmt.Sprintf("Tenant updated (%s)", data.ID))

Expand All @@ -146,30 +146,36 @@ func (r *tenantTypeResource) Delete(ctx context.Context, req resource.DeleteRequ
}
}

func mapStateToTenant(data *schemas.TenantModel) (*tenants.Tenant, error) {
func mapStateToTenant(ctx context.Context, data *schemas.TenantModel) (*tenants.Tenant, error) {
tenant := tenants.NewTenant(data.Name.ValueString())
tenant.ID = data.ID.ValueString()
tenant.ClonedFromTenantID = data.ClonedFromTenantId.ValueString()
tenant.Description = data.Description.ValueString()
tenant.SpaceID = data.SpaceID.ValueString()
if len(data.TenantTags.Elements()) > 0 {
tenant.TenantTags = util.ExpandStringList(data.TenantTags)
} else {
tenant.TenantTags = []string{}

convertedTenantTags, diags := util.SetToStringArray(ctx, data.TenantTags)
if diags.HasError() {
tflog.Error(ctx, fmt.Sprintf("Error converting tenant tags: %v\n", diags))
}
sort.Strings(tenant.TenantTags)

tenant.TenantTags = convertedTenantTags

return tenant, nil
}

func mapTenantToState(data *schemas.TenantModel, tenant *tenants.Tenant) {
func mapTenantToState(ctx context.Context, data *schemas.TenantModel, tenant *tenants.Tenant) {
data.ID = types.StringValue(tenant.ID)
data.ClonedFromTenantId = types.StringValue(tenant.ClonedFromTenantID)
data.Description = types.StringValue(tenant.Description)
data.SpaceID = types.StringValue(tenant.SpaceID)
data.Name = types.StringValue(tenant.Name)
sort.Strings(tenant.TenantTags)
data.TenantTags = util.Ternary(tenant.TenantTags != nil && len(tenant.TenantTags) > 0, util.FlattenStringList(tenant.TenantTags), types.ListValueMust(types.StringType, make([]attr.Value, 0)))

convertedTenantTags, diags := util.SetToStringArray(ctx, data.TenantTags)
if diags.HasError() {
tflog.Error(ctx, fmt.Sprintf("Error converting tenant tags: %v\n", diags))
}

data.TenantTags = basetypes.SetValue(util.FlattenStringList(convertedTenantTags))
}

func (*tenantTypeResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
Expand Down
7 changes: 4 additions & 3 deletions octopusdeploy_framework/resource_tenant_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package octopusdeploy_framework

import (
"fmt"
"os"
"sort"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/stretchr/testify/assert"
"os"
"sort"
"testing"
)

func TestTenantResource_UpgradeFromSDK_ToPluginFramework(t *testing.T) {
Expand Down
18 changes: 9 additions & 9 deletions octopusdeploy_framework/schemas/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
datasourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/types"
)
Expand All @@ -16,7 +16,7 @@ type TenantModel struct {
Description types.String `tfsdk:"description"`
Name types.String `tfsdk:"name"`
SpaceID types.String `tfsdk:"space_id"`
TenantTags types.List `tfsdk:"tenant_tags"`
TenantTags types.Set `tfsdk:"tenant_tags"`

ResourceModel
}
Expand Down Expand Up @@ -47,7 +47,7 @@ func TenantObjectType() map[string]attr.Type {
"id": types.StringType,
"name": types.StringType,
"space_id": types.StringType,
"tenant_tags": types.ListType{ElemType: types.StringType},
"tenant_tags": types.SetType{ElemType: types.StringType},
}
}

Expand All @@ -56,15 +56,15 @@ func FlattenTenant(tenant *tenants.Tenant) attr.Value {
for i, value := range tenant.TenantTags {
tenantTags[i] = types.StringValue(value)
}
var tenantTagsList, _ = types.ListValue(types.StringType, tenantTags)
var tenantTagsSet, _ = types.SetValue(types.StringType, tenantTags)

return types.ObjectValueMust(TenantObjectType(), map[string]attr.Value{
"cloned_from_tenant_id": types.StringValue(tenant.ClonedFromTenantID),
"description": types.StringValue(tenant.Description),
"id": types.StringValue(tenant.GetID()),
"name": types.StringValue(tenant.Name),
"space_id": types.StringValue(tenant.SpaceID),
"tenant_tags": tenantTagsList,
"tenant_tags": tenantTagsSet,
})
}

Expand Down Expand Up @@ -108,7 +108,7 @@ func (t TenantSchema) GetDatasourceSchema() datasourceSchema.Schema {
"id": GetIdDatasourceSchema(true),
"name": GetReadonlyNameDatasourceSchema(),
"space_id": GetSpaceIdDatasourceSchema("tenant", true),
"tenant_tags": datasourceSchema.ListAttribute{
"tenant_tags": datasourceSchema.SetAttribute{
Computed: true,
Description: "A list of tenant tags associated with this resource.",
ElementType: types.StringType,
Expand All @@ -134,13 +134,13 @@ func (t TenantSchema) GetResourceSchema() resourceSchema.Schema {
"id": GetIdResourceSchema(),
"name": GetNameResourceSchema(true),
"space_id": GetSpaceIdResourceSchema("tenant"),
"tenant_tags": resourceSchema.ListAttribute{
"tenant_tags": resourceSchema.SetAttribute{
Description: "A list of tenant tags associated with this resource.",
ElementType: types.StringType,
Optional: true,
Computed: true,
PlanModifiers: []planmodifier.List{
listplanmodifier.UseStateForUnknown(),
PlanModifiers: []planmodifier.Set{
setplanmodifier.UseStateForUnknown(),
},
},
},
Expand Down

0 comments on commit e688aa7

Please sign in to comment.