Skip to content

fix: idempotent lifecycle ops#1303

Open
DominikPildner wants to merge 12 commits intostackitcloud:mainfrom
intive:fix/idempotent-lifecycle-ops
Open

fix: idempotent lifecycle ops#1303
DominikPildner wants to merge 12 commits intostackitcloud:mainfrom
intive:fix/idempotent-lifecycle-ops

Conversation

@DominikPildner
Copy link
Copy Markdown

@DominikPildner DominikPildner commented Mar 18, 2026

Description

Issue: #1338

This PR brings resource lifecycle operations in line with Terraform plugin framework best practices (see Read and Delete guidelines), to fix handling of missing resources:

  1. Read with missing ID: When Read is called before Create (e.g. by tools that observe existing infrastructure), resource IDs that are server-assigned will be empty. Previously this caused API errors from requests with empty IDs. Now the resource is gracefully removed from state instead.

  2. Delete of already-deleted resource: When a resource has already been deleted outside of Terraform, Delete now handles the not-found response gracefully instead of returning an error.

Checklist

  • Issue was linked above
  • Code format was applied: make fmt
  • Examples were added / adjusted (see examples/ directory)
  • Docs are up-to-date: make generate-docs (will be checked by CI)
  • Unit tests got implemented or updated
  • Acceptance tests got implemented or updated (see e.g. here)
  • Unit tests are passing: make test (will be checked by CI)
  • No linter issues: make lint (will be checked by CI)

@DominikPildner DominikPildner requested a review from a team as a code owner March 18, 2026 08:03
@DominikPildner DominikPildner changed the title Fix: idempotent lifecycle ops fix: idempotent lifecycle ops Mar 18, 2026
@github-actions
Copy link
Copy Markdown

This PR was marked as stale after 7 days of inactivity and will be closed after another 7 days of further inactivity. If this PR should be kept open, just add a comment, remove the stale label or push new commits to it.

@github-actions github-actions Bot added the Stale PR is marked as stale due to inactivity. label Mar 26, 2026
@DominikPildner
Copy link
Copy Markdown
Author

Hello, is there anything I can do to help move this PR forward? Such as creating a Issue to link to it?

@github-actions github-actions Bot removed the Stale PR is marked as stale due to inactivity. label Mar 27, 2026
@marceljk
Copy link
Copy Markdown
Contributor

Hello,
I created a ticket in our internal backlog to review your PR soon.

@karawedi
Copy link
Copy Markdown

Hi @DominikPildner! We see the same behavior with SKE. Does this PR fix this aswell implicitly? I cannot see any SKE-Code touched.

@DominikPildner
Copy link
Copy Markdown
Author

@karawedi good point, for the 404 Code check I only covered resources that I used in my tests. I now tried to find all similar places and applied the same fix. This depends on the API actually returning 404 though, which I did not test for the new changes.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

This PR was marked as stale after 7 days of inactivity and will be closed after another 7 days of further inactivity. If this PR should be kept open, just add a comment, remove the stale label or push new commits to it.

@github-actions github-actions Bot added the Stale PR is marked as stale due to inactivity. label Apr 8, 2026
@DominikPildner
Copy link
Copy Markdown
Author

waiting for review

@github-actions github-actions Bot removed the Stale PR is marked as stale due to inactivity. label Apr 14, 2026
@cgoetz-inovex
Copy link
Copy Markdown
Contributor

Hi @DominikPildner,

don't know how to make a suggestion here to an unchanged file.
Could you please add this patch, so that our contribution example matches your changes?

Index: .github/docs/contribution-guide/resource.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/.github/docs/contribution-guide/resource.go b/.github/docs/contribution-guide/resource.go
--- a/.github/docs/contribution-guide/resource.go	(revision 937cb6eaae39c0a32dc51099681e5997ab333cbd)
+++ b/.github/docs/contribution-guide/resource.go	(date 1776259148171)
@@ -2,7 +2,9 @@
 
 import (
 	"context"
+	"errors"
 	"fmt"
+	"net/http"
 	"strings"
 
 	"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -12,10 +14,12 @@
 	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
 	"github.com/hashicorp/terraform-plugin-framework/types"
 	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
 	"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
 	"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
 	fooUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/foo/utils"
 	"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
 
 	"github.com/stackitcloud/stackit-sdk-go/services/foo"      // Import service "foo" from the STACKIT SDK for Go
 	"github.com/stackitcloud/stackit-sdk-go/services/foo/wait" // Import service "foo" waiters from the STACKIT SDK for Go (in case the service API has asynchronous endpoints)
@@ -255,12 +259,21 @@
 	projectId := model.ProjectId.ValueString()
 	region := r.providerData.GetRegionWithOverride(model.Region)
 	barId := model.BarId.ValueString()
+	if barId == "" {
+		// Resource not yet created; ID is unknown.
+		resp.State.RemoveResource(ctx)
+		return
+	}
 	ctx = tflog.SetField(ctx, "project_id", projectId)
 	ctx = tflog.SetField(ctx, "region", region)
 	ctx = tflog.SetField(ctx, "bar_id", barId)
 
 	barResp, err := r.client.GetBar(ctx, projectId, region, barId).Execute()
 	if err != nil {
+		if oapiErr, ok := errors.AsType[*oapierror.GenericOpenAPIError](err); ok && oapiErr.StatusCode == http.StatusNotFound {
+			resp.State.RemoveResource(ctx)
+			return
+		}
 		core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading bar", fmt.Sprintf("Calling API: %v", err))
 		return
 	}
@@ -308,6 +321,10 @@
 	// Delete existing bar
 	_, err := r.client.DeleteBar(ctx, projectId, region, barId).Execute()
 	if err != nil {
+		if oapiErr, ok := errors.AsType[*oapierror.GenericOpenAPIError](err); ok && oapiErr.StatusCode == http.StatusNotFound {
+			resp.State.RemoveResource(ctx)
+			return
+		}
 		core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting bar", fmt.Sprintf("Calling API: %v", err))
 	}
 

Comment thread stackit/internal/services/dns/recordset/resource.go
Comment thread stackit/internal/services/git/instance/resource.go
Comment thread stackit/internal/services/iaas/networkarearegion/resource.go
Comment thread stackit/internal/services/iaas/networkarearoute/resource.go
Comment thread stackit/internal/services/iaas/routingtable/route/resource.go
Comment thread stackit/internal/services/iaas/routingtable/route/resource.go Outdated
Comment thread stackit/internal/services/observability/credential/resource.go
@cgoetz-inovex
Copy link
Copy Markdown
Contributor

Thanks for your contribution!
Checked request funcs used without 404 check, if they can return a 404.

Hint for 2nd review:
In the Delete funcs there are inconsistencies regarding calling of RemoveResource(). TF will remove a resource if Delete does not return an error. So this mixture is ok.

@DominikPildner
Copy link
Copy Markdown
Author

Thanks for the feedback, all requested changes were implemented.

cgoetz-inovex
cgoetz-inovex previously approved these changes Apr 20, 2026
@cgoetz-inovex
Copy link
Copy Markdown
Contributor

Hi @DominikPildner,
the branch currently has some conflicts, could you please either resolve them or give us permission to do so?
See: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork for the 2nd option.

@DominikPildner
Copy link
Copy Markdown
Author

@cgoetz-inovex I have resolved the conflicts. Seems the option to grant maintainers access is not available for organization repos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read and Delete do not handle missing resources gracefully

4 participants