-
Notifications
You must be signed in to change notification settings - Fork 991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle Jobs with ttl_seconds_after_finished = 0 correctly #2596
Conversation
var oldTTLStr, newTTLStr string | ||
|
||
if oldTTLRaw != nil { | ||
oldTTLStr, _ = oldTTLRaw.(string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just omit the , _
here if you're not going to check the type assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
,_ is not omitted, thanks for the feedback!
…st skip the diff logic and not throw an error
`, name, imageName) | ||
} | ||
|
||
func testAccKubernetesJobV1Config_customizeDiff_ttlFive(name, imageName string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having 2 configs, you could just make the ttl value of a parameter to the function and template it in.
func resourceKubernetesJobV1CustomizeDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { | ||
if d.Id() == "" { | ||
log.Printf("[DEBUG] Resource ID is empty, resource not created yet.") | ||
return nil | ||
} | ||
|
||
// Retrieve old and new TTL values | ||
oldTTLRaw, newTTLRaw := d.GetChange("spec.0.ttl_seconds_after_finished") | ||
|
||
// If both TTL values are not set or are empty, skip TTL diff | ||
if (oldTTLRaw == nil && newTTLRaw == nil) || (oldTTLRaw == "" && newTTLRaw == "") { | ||
log.Printf("[DEBUG] No ttl_seconds_after_finished provided or both values are empty; skipping TTL diff") | ||
return nil | ||
} | ||
|
||
// Only check TTL if present | ||
var oldTTLStr, newTTLStr string | ||
if oldTTLRaw != nil { | ||
oldTTLStr = oldTTLRaw.(string) | ||
} | ||
if newTTLRaw != nil { | ||
newTTLStr = newTTLRaw.(string) | ||
} | ||
|
||
oldTTLInt, err := strconv.Atoi(oldTTLStr) | ||
if err != nil { | ||
log.Printf("[DEBUG] Invalid old TTL value: %s, skipping diff", oldTTLStr) | ||
return nil | ||
} | ||
newTTLInt, err := strconv.Atoi(newTTLStr) | ||
if err != nil { | ||
log.Printf("[DEBUG] Invalid new TTL value: %s, skipping diff", newTTLStr) | ||
return nil | ||
} | ||
|
||
// Suppress the diff if the old and new TTL values are the same | ||
if oldTTLInt == newTTLInt { | ||
log.Printf("[DEBUG] ttl_seconds_after_finished has not changed; suppressing diff") | ||
d.Clear("spec") | ||
d.Clear("metadata") | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't make sense to me why we would have a diff function that checks if the value of ttl_seconds_after_finished
hasn't changed and then suppress the diff?
I tried removing this function completely and your tests still pass.
_, err = conn.BatchV1().Jobs(namespace).Get(ctx, name, metav1.GetOptions{}) | ||
if err != nil { | ||
if apierrors.IsNotFound(err) { | ||
// Job is missing; check TTL | ||
ttlAttr := d.Get("spec.0.ttl_seconds_after_finished") | ||
ttlStr, _ := ttlAttr.(string) | ||
ttlInt, err := strconv.Atoi(ttlStr) | ||
if err != nil { | ||
ttlInt = 0 | ||
} | ||
|
||
if ttlInt >= 0 { | ||
// Job was deleted due to TTL nothing to update | ||
log.Printf("[INFO] Job %s not found but ttl_seconds_after_finished = %v; nothing to update", d.Id(), ttlInt) | ||
return nil | ||
} | ||
|
||
// Job was deleted unexpectedly; return an error | ||
return diag.Errorf("Job %s not found; cannot update because it has been deleted", d.Id()) | ||
} | ||
return diag.Errorf("Error retrieving Job: %s", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need this logic either. In the read function it's going to check if the job exists and then set the ID to ""
if it doesn't which will force recreation and so the update function wont get called.
I tried commenting this code out and all your tests still pass too.
Description
Fixes #2531
When a Kubernetes Job has ttl_seconds_after_finished set to 0, Kubernetes deletes the Job immediately after it completes. This can cause Terraform to plan the recreation of the Job in subsequent runs, which is sort of undesirable behavior. The expected behavior is for Terraform to recognize that the Job was deleted intentionally and not attempt to recreate it or show any diffs.
Changes made
- Read function:
- When the read crud func encounters a
NotFound
error for a job, it now checks ifttl
is set to 0, if so it keeps theresource in the state without marking it as destroyed, this helps prevent the recreation of the job. If it is not 0, it
behaves as before by removing the resource from the state.
CustomizeDiff function introduced:
- Supressing diffs when the job has been deleted due to due to ttl = 0
Acceptance tests
Output from acceptance testing:
Release Note
Release note for CHANGELOG:
References
Fixes #2531
Community Note