Skip to content

Commit 098a3f6

Browse files
committed
keep url/sha updated, use config as source of values
1 parent 2b11d94 commit 098a3f6

File tree

2 files changed

+113
-10
lines changed

2 files changed

+113
-10
lines changed

internal/provider/resource_tfe_opa_version.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,18 @@ func (r *OPAVersionResource) Schema(ctx context.Context, req resource.SchemaRequ
6565
"url": schema.StringAttribute{
6666
Optional: true,
6767
Computed: true,
68+
PlanModifiers: []planmodifier.String{
69+
stringplanmodifier.UseStateForUnknown(),
70+
SyncTopLevelURLSHAWithAMD64(),
71+
},
6872
},
6973
"sha": schema.StringAttribute{
7074
Optional: true,
7175
Computed: true,
76+
PlanModifiers: []planmodifier.String{
77+
stringplanmodifier.UseStateForUnknown(),
78+
SyncTopLevelURLSHAWithAMD64(),
79+
},
7280
},
7381
"official": schema.BoolAttribute{
7482
Optional: true,
@@ -114,7 +122,7 @@ func (r *OPAVersionResource) Schema(ctx context.Context, req resource.SchemaRequ
114122
Optional: true,
115123
PlanModifiers: []planmodifier.Set{
116124
setplanmodifier.UseStateForUnknown(), // This ensures that we don't show a warning for invisible changes in updates when using refresh-only mode
117-
PreserveAMD64ArchsOnChange(), // This ensures that we don't remove AMD64 archs when the URL/SHA changes
125+
PreserveAMD64ArchsOnChange(), // This ensures that we update the amd64 archs when top level url/sha are updated
118126
},
119127
},
120128
},

internal/provider/tool_helpers.go

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
1414
"github.com/hashicorp/terraform-plugin-framework/types"
1515
"github.com/hashicorp/terraform-plugin-log/tflog"
16+
"strings"
1617

1718
tfe "github.com/hashicorp/go-tfe"
1819
)
@@ -257,17 +258,17 @@ func (m *preserveAMD64ArchsModifier) PlanModifySet(ctx context.Context, req plan
257258
return
258259
}
259260

260-
var stateURL, planURL, stateSHA, planSHA types.String
261+
var configURL, planURL, configSHA, planSHA types.String
261262

262263
// Get values from state and plan
263-
req.State.GetAttribute(ctx, path.Root("url"), &stateURL)
264+
req.Config.GetAttribute(ctx, path.Root("url"), &configURL)
264265
req.Plan.GetAttribute(ctx, path.Root("url"), &planURL)
265-
req.State.GetAttribute(ctx, path.Root("sha"), &stateSHA)
266+
req.State.GetAttribute(ctx, path.Root("sha"), &configSHA)
266267
req.Plan.GetAttribute(ctx, path.Root("sha"), &planSHA)
267268

268269
// Check if values are changing
269-
urlChanged := !stateURL.Equal(planURL)
270-
shaChanged := !stateSHA.Equal(planSHA)
270+
urlChanged := !configURL.Equal(planURL)
271+
shaChanged := !configSHA.Equal(planSHA)
271272

272273
// If neither URL nor SHA is changing, do nothing
273274
if !urlChanged && !shaChanged {
@@ -300,9 +301,9 @@ func (m *preserveAMD64ArchsModifier) PlanModifySet(ctx context.Context, req plan
300301
"stateArchsList": stateArchsList,
301302
"urlChanged": urlChanged,
302303
"shaChanged": shaChanged,
303-
"stateURL": stateURL,
304+
"stateURL": configURL,
304305
"planURL": planURL,
305-
"stateSHA": stateSHA,
306+
"stateSHA": configSHA,
306307
"planSHA": planSHA,
307308
})
308309
// Check if AMD64 is already in the plan
@@ -317,10 +318,10 @@ func (m *preserveAMD64ArchsModifier) PlanModifySet(ctx context.Context, req plan
317318
// If we found AMD64, update its URL and SHA if they are changing
318319
// If URL or SHA is changing, update the AMD64 arch to match
319320
if urlChanged {
320-
arch.URL = planURL
321+
arch.URL = configURL
321322
}
322323
if shaChanged {
323-
arch.Sha = planSHA
324+
arch.Sha = configURL
324325
}
325326

326327
// Update the plan with the modified AMD64 arch
@@ -341,6 +342,100 @@ func (m *preserveAMD64ArchsModifier) PlanModifySet(ctx context.Context, req plan
341342
}
342343
}
343344

345+
// SyncTopLevelURLSHAWithAMD64 creates a plan modifier that synchronizes the top-level URL/SHA with the AMD64 architecture on updates where URL or SHA is not set in the config,
346+
func SyncTopLevelURLSHAWithAMD64() planmodifier.String {
347+
return &SyncTopLevelURLSHAWithAMD64Modifier{}
348+
}
349+
350+
// Implement the plan modifier interface
351+
type SyncTopLevelURLSHAWithAMD64Modifier struct{}
352+
353+
// Description provides a plain text description of the plan modifier
354+
func (m *SyncTopLevelURLSHAWithAMD64Modifier) Description(ctx context.Context) string {
355+
return "Combines top-level URL/SHA with AMD64 architecture"
356+
}
357+
358+
// MarkdownDescription provides markdown documentation
359+
func (m *SyncTopLevelURLSHAWithAMD64Modifier) MarkdownDescription(ctx context.Context) string {
360+
return "Combines top-level URL/SHA with AMD64 architecture"
361+
}
362+
363+
// PlanModifySet modifies the plan to combine URL/SHA with AMD64 architecture
364+
func (m *SyncTopLevelURLSHAWithAMD64Modifier) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) {
365+
// Skip if we're destroying the resource or no state
366+
if req.Plan.Raw.IsNull() || req.State.Raw.IsNull() || req.StateValue.IsNull() {
367+
tflog.Debug(ctx, "Skipping AMD64 URL/SHA combination because state or plan is null")
368+
return
369+
}
370+
371+
if !req.ConfigValue.IsUnknown() && !req.ConfigValue.IsNull() {
372+
tflog.Debug(ctx, "Skipping because value is set in config")
373+
return
374+
}
375+
376+
// if config archs is not set we will not modify the plan
377+
// get the config archs
378+
379+
var configArchs types.Set
380+
diags := req.Config.GetAttribute(ctx, path.Root("archs"), &configArchs)
381+
if diags.HasError() {
382+
tflog.Debug(ctx, "Error extracting config architectures", map[string]interface{}{
383+
"diagnostics": diags,
384+
})
385+
return
386+
}
387+
388+
if configArchs.IsNull() && configArchs.IsUnknown() {
389+
tflog.Debug(ctx, "Skipping top level arch modifying because archs are NOT set in config")
390+
return
391+
}
392+
393+
// we do not know the name of the attibute
394+
// we are modifying, so we will use the path to get the attribute name
395+
segments := req.Path.String()
396+
attributeName := segments[strings.LastIndex(segments, ".")+1:]
397+
398+
// get the archs from the plan
399+
// get the amd arch from the configArchs
400+
var amd64Arch ToolArchitecture
401+
var configArchsList []ToolArchitecture
402+
diags = configArchs.ElementsAs(ctx, &configArchsList, false)
403+
if diags.HasError() {
404+
tflog.Debug(ctx, "Error extracting config architectures", map[string]interface{}{
405+
"diagnostics": diags,
406+
})
407+
return
408+
}
409+
410+
for _, arch := range configArchsList {
411+
if arch.Arch.ValueString() == "amd64" {
412+
amd64Arch = arch
413+
break
414+
}
415+
}
416+
417+
if amd64Arch.Arch.IsNull() || amd64Arch.Arch.IsUnknown() {
418+
tflog.Debug(ctx, "No AMD64 architecture found in config archs, skipping modification")
419+
return
420+
}
421+
422+
// Get the value of the attributeName from the amd64 arch
423+
switch attributeName {
424+
case "url":
425+
// set the plan value to the URL of the AMD64 arch
426+
resp.PlanValue = types.StringValue(amd64Arch.URL.ValueString())
427+
case "sha":
428+
// set the plan value to the SHA of the AMD64 arch
429+
resp.PlanValue = types.StringValue(amd64Arch.Sha.ValueString())
430+
default:
431+
tflog.Debug(ctx, "Unsupported attribute for AMD64 combination", map[string]interface{}{
432+
"attribute": attributeName,
433+
})
434+
return
435+
}
436+
437+
}
438+
344439
//
345440
// // ValidateToolVersion provides common validation for tool version resources
346441
// func ValidateToolVersion(ctx context.Context, url, sha types.String, archs types.Set, resourceType string) diag.Diagnostics {

0 commit comments

Comments
 (0)