Skip to content

Commit 5a700a5

Browse files
authored
fix: explicitly preserve existing expiration and grace_period from state (#401)
Signed-off-by: Slavina <slavina.stefanova@chainguard.dev>
1 parent fff8918 commit 5a700a5

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

internal/provider/resource_image_repo.go

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ func (r *imageRepoResource) Create(ctx context.Context, req resource.CreateReque
336336
return
337337
}
338338
// Populate computed fields from API response
339-
// Note: Source is NOT populated here to avoid overwriting user input
340339
cfg.Expiration = types.StringValue(repo.SyncConfig.Expiration.AsTime().Format(time.RFC3339))
341340
cfg.UniqueTags = types.BoolValue(repo.SyncConfig.UniqueTags)
342341
cfg.GracePeriod = types.BoolValue(repo.SyncConfig.GracePeriod)
@@ -471,6 +470,13 @@ func (r *imageRepoResource) Update(ctx context.Context, req resource.UpdateReque
471470
if resp.Diagnostics.HasError() {
472471
return
473472
}
473+
474+
// Also get current state to preserve computed values user didn't change
475+
var state imageRepoResourceModel
476+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
477+
if resp.Diagnostics.HasError() {
478+
return
479+
}
474480
tflog.Info(ctx, fmt.Sprintf("update image repo request: %s", data.ID))
475481

476482
// Lock to prevent concurrent update of the same repo.
@@ -484,8 +490,19 @@ func (r *imageRepoResource) Update(ctx context.Context, req resource.UpdateReque
484490
if resp.Diagnostics.HasError() {
485491
return
486492
}
493+
494+
// Get current state values to preserve when user doesn't provide new ones
495+
var stateCfg syncConfig
496+
if !state.SyncConfig.IsNull() {
497+
resp.Diagnostics.Append(state.SyncConfig.As(ctx, &stateCfg, basetypes.ObjectAsOptions{})...)
498+
if resp.Diagnostics.HasError() {
499+
return
500+
}
501+
}
502+
487503
var expiration *timestamppb.Timestamp
488504
if !cfg.Expiration.IsNull() && cfg.Expiration.ValueString() != "" {
505+
// User provided new expiration value
489506
ts, err := time.Parse(time.RFC3339, cfg.Expiration.ValueString())
490507
if err != nil {
491508
resp.Diagnostics.Append(errorToDiagnostic(err, "failed to parse timestamp"))
@@ -494,6 +511,12 @@ func (r *imageRepoResource) Update(ctx context.Context, req resource.UpdateReque
494511
}
495512
}
496513
expiration = timestamppb.New(ts)
514+
} else if !stateCfg.Expiration.IsNull() && stateCfg.Expiration.ValueString() != "" {
515+
// User didn't provide new value, preserve existing from state
516+
ts, err := time.Parse(time.RFC3339, stateCfg.Expiration.ValueString())
517+
if err == nil {
518+
expiration = timestamppb.New(ts)
519+
}
497520
}
498521
sc = &registry.SyncConfig{
499522
Source: cfg.Source.ValueString(),
@@ -504,9 +527,11 @@ func (r *imageRepoResource) Update(ctx context.Context, req resource.UpdateReque
504527
ApkoOverlay: cfg.ApkoOverlay.ValueString(),
505528
// UniqueTags is computed (read-only), don't send to API
506529
}
507-
// Only set grace_period if provided by user
530+
// Set grace_period: use user's new value if provided, else preserve from state
508531
if !cfg.GracePeriod.IsNull() {
509532
sc.GracePeriod = cfg.GracePeriod.ValueBool()
533+
} else if !stateCfg.GracePeriod.IsNull() {
534+
sc.GracePeriod = stateCfg.GracePeriod.ValueBool()
510535
}
511536
}
512537

@@ -558,15 +583,24 @@ func (r *imageRepoResource) Update(ctx context.Context, req resource.UpdateReque
558583
data.Tier = types.StringNull()
559584
}
560585

561-
// Populate computed fields from API response
586+
// Populate computed sync_config fields from API response
562587
if repo.SyncConfig != nil && !data.SyncConfig.IsNull() {
563588
var cfg syncConfig
564-
resp.Diagnostics.Append(data.SyncConfig.As(ctx, &cfg, basetypes.ObjectAsOptions{})...)
565-
if resp.Diagnostics.HasError() {
589+
if diags := data.SyncConfig.As(ctx, &cfg, basetypes.ObjectAsOptions{}); diags.HasError() {
590+
resp.Diagnostics.Append(diags...)
566591
return
567592
}
593+
// Populate all computed fields from API response (don't overwrite Source)
594+
cfg.Expiration = types.StringValue(repo.SyncConfig.Expiration.AsTime().Format(time.RFC3339))
568595
cfg.UniqueTags = types.BoolValue(repo.SyncConfig.UniqueTags)
569-
data.SyncConfig, _ = types.ObjectValueFrom(ctx, data.SyncConfig.AttributeTypes(ctx), cfg)
596+
cfg.GracePeriod = types.BoolValue(repo.SyncConfig.GracePeriod)
597+
598+
if objVal, diags := types.ObjectValueFrom(ctx, data.SyncConfig.AttributeTypes(ctx), cfg); diags.HasError() {
599+
resp.Diagnostics.Append(diags...)
600+
return
601+
} else {
602+
data.SyncConfig = objVal
603+
}
570604
}
571605

572606
var diags diag.Diagnostics

0 commit comments

Comments
 (0)