Skip to content

Commit

Permalink
update times to support timezones
Browse files Browse the repository at this point in the history
  • Loading branch information
benPearce1 committed Dec 2, 2024
1 parent 0b61d02 commit 5d661ff
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 26 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ require (
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.21.0 // indirect
github.com/hashicorp/terraform-json v0.22.1 // indirect
github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smP
github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ=
github.com/hashicorp/terraform-plugin-framework v1.11.0 h1:M7+9zBArexHFXDx/pKTxjE6n/2UCXY6b8FIq9ZYhwfE=
github.com/hashicorp/terraform-plugin-framework v1.11.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM=
github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 h1:v3DapR8gsp3EM8fKMh6up9cJUFQ2iRaFsYLP8UJnCco=
github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0/go.mod h1:c3PnGE9pHBDfdEVG9t1S1C9ia5LW+gkFR0CygXlM8ak=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co=
Expand Down
93 changes: 67 additions & 26 deletions octopusdeploy_framework/resource_deployment_freeze.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"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-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"time"
Expand All @@ -15,9 +17,9 @@ import (
const deploymentFreezeResourceName = "deployment_freeze"

type deploymentFreezeModel struct {
Name types.String `tfsdk:"name"`
Start types.String `tfsdk:"start"`
End types.String `tfsdk:"end"`
Name types.String `tfsdk:"name"`
Start timetypes.RFC3339 `tfsdk:"start"`
End timetypes.RFC3339 `tfsdk:"end"`

schemas.ResourceModel
}
Expand Down Expand Up @@ -62,7 +64,11 @@ func (f *deploymentFreezeResource) Read(ctx context.Context, req resource.ReadRe
return
}

mapToState(state, deploymentFreeze, true)
if deploymentFreeze.Name != state.Name.ValueString() {
state.Name = types.StringValue(deploymentFreeze.Name)
}

mapToState(ctx, state, deploymentFreeze)

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}
Expand All @@ -78,10 +84,9 @@ func (f *deploymentFreezeResource) Create(ctx context.Context, req resource.Crea
return
}

var deploymentFreeze *deploymentfreezes.DeploymentFreeze
deploymentFreeze, err := mapFromState(plan)
if err != nil {
resp.Diagnostics.AddError("error while creating deployment freeze", err.Error())
deploymentFreeze, diags := mapFromState(plan)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}

Expand All @@ -91,9 +96,11 @@ func (f *deploymentFreezeResource) Create(ctx context.Context, req resource.Crea
return
}

mapToState(plan, createdFreeze, false)
diags = resp.State.Set(ctx, plan)
resp.Diagnostics.Append(diags...)
diags.Append(mapToState(ctx, plan, createdFreeze)...)
if diags.HasError() {
return
}
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
}

func (f *deploymentFreezeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
Expand All @@ -112,9 +119,9 @@ func (f *deploymentFreezeResource) Update(ctx context.Context, req resource.Upda
return
}

updatedFreeze, err := mapFromState(plan)
if err != nil {
resp.Diagnostics.AddError("error while mapping deployment freeze", err.Error())
updatedFreeze, diags := mapFromState(plan)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
return
}

Expand All @@ -130,7 +137,10 @@ func (f *deploymentFreezeResource) Update(ctx context.Context, req resource.Upda
return
}

mapToState(plan, updatedFreeze, false)
diags.Append(mapToState(ctx, plan, updatedFreeze)...)
if diags.HasError() {
resp.Diagnostics.Append(diags...)
}

resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
}
Expand Down Expand Up @@ -160,26 +170,57 @@ func (f *deploymentFreezeResource) Delete(ctx context.Context, req resource.Dele
resp.State.RemoveResource(ctx)
}

func mapToState(state *deploymentFreezeModel, deploymentFreeze *deploymentfreezes.DeploymentFreeze, useSourceForDates bool) {
func mapToState(ctx context.Context, state *deploymentFreezeModel, deploymentFreeze *deploymentfreezes.DeploymentFreeze) diag.Diagnostics {
state.ID = types.StringValue(deploymentFreeze.ID)
state.Name = types.StringValue(deploymentFreeze.Name)
if useSourceForDates {
state.Start = types.StringValue(deploymentFreeze.Start.Format(time.RFC3339))
state.End = types.StringValue(deploymentFreeze.End.Format(time.RFC3339))

updatedStart, diags := calculateStateTime(ctx, state.Start, *deploymentFreeze.Start)
if diags.HasError() {
return diags
}
state.Start = updatedStart

updatedEnd, diags := calculateStateTime(ctx, state.End, *deploymentFreeze.End)
if diags.HasError() {
return diags
}
state.End = updatedEnd

return nil
}

func mapFromState(state *deploymentFreezeModel) (*deploymentfreezes.DeploymentFreeze, error) {
start, err := time.Parse(time.RFC3339, state.Start.ValueString())
if err != nil {
return nil, err
func calculateStateTime(ctx context.Context, stateValue timetypes.RFC3339, updatedValue time.Time) (timetypes.RFC3339, diag.Diagnostics) {
stateTime, diags := stateValue.ValueRFC3339Time()
if diags.HasError() {
return timetypes.RFC3339{}, diags
}
end, err := time.Parse(time.RFC3339, state.End.ValueString())
if err != nil {
return nil, err
stateTimeUTC := timetypes.NewRFC3339TimeValue(stateTime.UTC())
updatedValueUTC := updatedValue.UTC()
valuesAreEqual, diags := stateTimeUTC.StringSemanticEquals(ctx, timetypes.NewRFC3339TimeValue(updatedValueUTC))
if diags.HasError() {
return timetypes.NewRFC3339Null(), diags
}

if valuesAreEqual {
return stateValue, diags
}

location := stateTime.Location()
newValue := timetypes.NewRFC3339TimeValue(updatedValueUTC.In(location))
return newValue, diags
}

func mapFromState(state *deploymentFreezeModel) (*deploymentfreezes.DeploymentFreeze, diag.Diagnostics) {
start, diags := state.Start.ValueRFC3339Time()
if diags.HasError() {
return nil, diags
}
start = start.UTC()

end, diags := state.End.ValueRFC3339Time()
if diags.HasError() {
return nil, diags
}
end = end.UTC()

freeze := deploymentfreezes.DeploymentFreeze{
Expand Down
2 changes: 2 additions & 0 deletions octopusdeploy_framework/schemas/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package schemas

import (
"fmt"
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
Expand Down Expand Up @@ -439,6 +440,7 @@ func GetDateTimeResourceSchema(description string, isRequired bool) resourceSche
return resourceSchema.StringAttribute{
Description: description,
Required: isRequired,
CustomType: timetypes.RFC3339Type{},
Validators: []validator.String{
stringvalidator.RegexMatches(regexp.MustCompile(regex), fmt.Sprintf("must match RFC3339 format, %s", regex)),
},
Expand Down

0 comments on commit 5d661ff

Please sign in to comment.