From fb28c48fed0e6e9684a0dff1e79158694dff7b95 Mon Sep 17 00:00:00 2001 From: Tim Reibe Date: Fri, 26 Jun 2026 14:19:31 +0200 Subject: [PATCH 1/2] WIP: waiting for forgejo PR --- .../00-bootstrap/.terraform.lock.hcl | 24 +++++++++ .../00-bootstrap/000-variables.tf | 43 +++++++++++++++ .../00-bootstrap/010-provider.tf | 29 ++++++++++ .../00-bootstrap/020-project.tf | 19 +++++++ .../00-bootstrap/030-git.tf | 24 +++++++++ .../00-bootstrap/040-output.tf | 18 +++++++ .../00-bootstrap/README.md | 23 ++++++++ .../00-bootstrap/terraform.tfvars.example | 31 +++++++++++ .../01-example-project/.terraform.lock.hcl | 24 +++++++++ .../01-example-project/000-variables.tf | 43 +++++++++++++++ .../01-example-project/010-backend.tf | 17 ++++++ .../01-example-project/020-provider.tf | 28 ++++++++++ .../01-example-project/030-project.tf | 19 +++++++ .../01-example-project/README.md | 53 +++++++++++++++++++ .../01-example-project/backend.conf.example | 12 +++++ .../scripts/validate_lock.sh | 44 +++++++++++++++ .../terraform.tfvars.example | 31 +++++++++++ .../MAINTAINERS.md | 9 ++++ .../README.md | 12 +++++ 19 files changed, 503 insertions(+) create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/.terraform.lock.hcl create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/000-variables.tf create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/010-provider.tf create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/020-project.tf create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/030-git.tf create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/040-output.tf create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/README.md create mode 100644 examples/terraform-git-backend-state-locking/00-bootstrap/terraform.tfvars.example create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/.terraform.lock.hcl create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/000-variables.tf create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/010-backend.tf create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/020-provider.tf create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/030-project.tf create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/README.md create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example create mode 100755 examples/terraform-git-backend-state-locking/01-example-project/scripts/validate_lock.sh create mode 100644 examples/terraform-git-backend-state-locking/01-example-project/terraform.tfvars.example create mode 100644 examples/terraform-git-backend-state-locking/MAINTAINERS.md create mode 100644 examples/terraform-git-backend-state-locking/README.md diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/.terraform.lock.hcl b/examples/terraform-git-backend-state-locking/00-bootstrap/.terraform.lock.hcl new file mode 100644 index 0000000..ac34bd3 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/.terraform.lock.hcl @@ -0,0 +1,24 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/stackitcloud/stackit" { + version = "0.99.0" + constraints = ">= 0.99.0" + hashes = [ + "h1:a9z0j1z/8GmGjz+VygIhgyBbMqxx7jlXGqCvWBDD1NY=", + "zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f", + "zh:396c0392b9ef5ec7f8613c29a64e183545cc16dda0ceb876393fc003dba71c73", + "zh:40d86a1fb1c9ed4579583acb8ecc219edca44f9ee5221bfdcbc1bee2ce6654e7", + "zh:4ccbbecc3575737d87195ad13448d06071be9925760a2da5b7e5e8b91517f876", + "zh:506d786647c4566a82487fc3ffe0792f37a63ec8d6b54821aa3c7485e5ed6760", + "zh:848f638c500f1928f8593ae189472add1a0871c1e056d7df06871652ddee3409", + "zh:9ed739aec2c60cdfae3a33e4f349fa630fd0fd0ab50fcec5745774d42a6d6e70", + "zh:c0ac883dd73bd886e419d912c28ec29bb90a611b023cf4ae1b0534945cce1694", + "zh:df28663578694b25453b9d0a1cd7633a0f7fb1c113870cd3c133e9dc05d35946", + "zh:eaacb4a4512f41d44e46f82f042a19ab96c9d90d470890e2fd82c6cafb33bf0e", + "zh:ef9dd9b10571804f3a4dd6062405d0e473df270d75f05f897901c54d7d6c3d9d", + "zh:f40add9cd4fd4a7cda53f4a418c5f47a220b5ba5c4fc2377f60b1e16368f87d9", + "zh:f65deb30c1e3e8018a888d1aed56e895ea1e26b880f22a5772771e9836c9b5a4", + "zh:f8d14feddfd9d785d3ee6469937234a631998758ea5e8c16ecf61cdb94b07564", + ] +} diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/000-variables.tf b/examples/terraform-git-backend-state-locking/00-bootstrap/000-variables.tf new file mode 100644 index 0000000..95546e5 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/000-variables.tf @@ -0,0 +1,43 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +variable "stackit_service_account_key_path" { + description = "Path to the STACKIT service account key file (JSON). Keep this file out of version control." + type = string +} + +variable "stackit_organization_id" { + description = "STACKIT Organization ID (UUID). Found in the portal under Organization > Settings." + type = string +} + +variable "stackit_project_name" { + description = "Display name of the hub project in STACKIT." + type = string +} + +variable "stackit_org_admin" { + description = "Email address of the STACKIT user who will be set as project owner." + type = string +} + +variable "stackit_region" { + description = "STACKIT region (e.g. eu01)." + type = string +} + +variable "default_zone" { + description = "Availability zone within the region (e.g. eu01-1)." + type = string +} diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/010-provider.tf b/examples/terraform-git-backend-state-locking/00-bootstrap/010-provider.tf new file mode 100644 index 0000000..319b6ae --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/010-provider.tf @@ -0,0 +1,29 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = ">= 0.99.0" + } + } +} + +provider "stackit" { + default_region = var.stackit_region + service_account_key_path = var.stackit_service_account_key_path + enable_beta_resources = true + +} diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/020-project.tf b/examples/terraform-git-backend-state-locking/00-bootstrap/020-project.tf new file mode 100644 index 0000000..1169d4f --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/020-project.tf @@ -0,0 +1,19 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +resource "stackit_resourcemanager_project" "this" { + parent_container_id = var.stackit_organization_id + name = var.stackit_project_name + owner_email = var.stackit_org_admin +} diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/030-git.tf b/examples/terraform-git-backend-state-locking/00-bootstrap/030-git.tf new file mode 100644 index 0000000..79f4c6a --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/030-git.tf @@ -0,0 +1,24 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Provision Git Instance +resource "stackit_git" "this" { + project_id = stackit_resourcemanager_project.this.project_id + name = "tf-states" + acl = [ + # WARNING: Open ACL is for development only. Restrict to your specific egress IP ranges in production. + "0.0.0.0/0" + ] + flavor = "git-10" +} diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/040-output.tf b/examples/terraform-git-backend-state-locking/00-bootstrap/040-output.tf new file mode 100644 index 0000000..4893519 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/040-output.tf @@ -0,0 +1,18 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +output "git_instance_url" { + description = "Git Instance URL" + value = stackit_git.this.url +} diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/README.md b/examples/terraform-git-backend-state-locking/00-bootstrap/README.md new file mode 100644 index 0000000..b8398d5 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/README.md @@ -0,0 +1,23 @@ +# Phase 0: Bootstrap + +This module provisions the STACKIT PostgreSQL Flex instance, the `terraform_state` database, and the dedicated `tf_state_user`. Its state is kept locally (or in an independent CI/CD backend) to prevent dependency conflicts. + +## Implementation Steps + +1. Initialize Terraform with the default local backend: + + ```sh + terraform init + ``` + +2. Provision the PostgreSQL Flex resources: + + ```sh + terraform apply + ``` + +3. Extract the generated PostgreSQL connection string from the Terraform outputs. This URI is required to configure the remote backend in the next phase. + + ```sh + terraform output -raw pg_connection_uri + ``` diff --git a/examples/terraform-git-backend-state-locking/00-bootstrap/terraform.tfvars.example b/examples/terraform-git-backend-state-locking/00-bootstrap/terraform.tfvars.example new file mode 100644 index 0000000..a144c2d --- /dev/null +++ b/examples/terraform-git-backend-state-locking/00-bootstrap/terraform.tfvars.example @@ -0,0 +1,31 @@ +# --------------------------------------------------------------------------- +# terraform.tfvars.example +# +# Copy this file into a project directory (e.g. 00-bootcamp/terraform.tfvars) +# and fill in your values. Do NOT commit terraform.tfvars to version control. +# +# Alternatively, export variables as environment variables: +# export TF_VAR_stackit_organization_id="" +# --------------------------------------------------------------------------- + +# --- STACKIT Identity -------------------------------------------------------- + +# Your STACKIT Organization ID. +# Portal: Organization > Settings > Organization ID +stackit_organization_id = "" + +## Name of the bootstrapping project +stackit_project_name = "00-bootstrap" + +# Email address of the STACKIT user set as project owner. +stackit_org_admin = " Service Accounts > Keys > Create key +stackit_service_account_key_path = "./keys/service-account.json" + +# --- Region ------------------------------------------------------------------ +stackit_region = "eu01" +default_zone = "eu01-1" diff --git a/examples/terraform-git-backend-state-locking/01-example-project/.terraform.lock.hcl b/examples/terraform-git-backend-state-locking/01-example-project/.terraform.lock.hcl new file mode 100644 index 0000000..ac34bd3 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/.terraform.lock.hcl @@ -0,0 +1,24 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/stackitcloud/stackit" { + version = "0.99.0" + constraints = ">= 0.99.0" + hashes = [ + "h1:a9z0j1z/8GmGjz+VygIhgyBbMqxx7jlXGqCvWBDD1NY=", + "zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f", + "zh:396c0392b9ef5ec7f8613c29a64e183545cc16dda0ceb876393fc003dba71c73", + "zh:40d86a1fb1c9ed4579583acb8ecc219edca44f9ee5221bfdcbc1bee2ce6654e7", + "zh:4ccbbecc3575737d87195ad13448d06071be9925760a2da5b7e5e8b91517f876", + "zh:506d786647c4566a82487fc3ffe0792f37a63ec8d6b54821aa3c7485e5ed6760", + "zh:848f638c500f1928f8593ae189472add1a0871c1e056d7df06871652ddee3409", + "zh:9ed739aec2c60cdfae3a33e4f349fa630fd0fd0ab50fcec5745774d42a6d6e70", + "zh:c0ac883dd73bd886e419d912c28ec29bb90a611b023cf4ae1b0534945cce1694", + "zh:df28663578694b25453b9d0a1cd7633a0f7fb1c113870cd3c133e9dc05d35946", + "zh:eaacb4a4512f41d44e46f82f042a19ab96c9d90d470890e2fd82c6cafb33bf0e", + "zh:ef9dd9b10571804f3a4dd6062405d0e473df270d75f05f897901c54d7d6c3d9d", + "zh:f40add9cd4fd4a7cda53f4a418c5f47a220b5ba5c4fc2377f60b1e16368f87d9", + "zh:f65deb30c1e3e8018a888d1aed56e895ea1e26b880f22a5772771e9836c9b5a4", + "zh:f8d14feddfd9d785d3ee6469937234a631998758ea5e8c16ecf61cdb94b07564", + ] +} diff --git a/examples/terraform-git-backend-state-locking/01-example-project/000-variables.tf b/examples/terraform-git-backend-state-locking/01-example-project/000-variables.tf new file mode 100644 index 0000000..95546e5 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/000-variables.tf @@ -0,0 +1,43 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +variable "stackit_service_account_key_path" { + description = "Path to the STACKIT service account key file (JSON). Keep this file out of version control." + type = string +} + +variable "stackit_organization_id" { + description = "STACKIT Organization ID (UUID). Found in the portal under Organization > Settings." + type = string +} + +variable "stackit_project_name" { + description = "Display name of the hub project in STACKIT." + type = string +} + +variable "stackit_org_admin" { + description = "Email address of the STACKIT user who will be set as project owner." + type = string +} + +variable "stackit_region" { + description = "STACKIT region (e.g. eu01)." + type = string +} + +variable "default_zone" { + description = "Availability zone within the region (e.g. eu01-1)." + type = string +} diff --git a/examples/terraform-git-backend-state-locking/01-example-project/010-backend.tf b/examples/terraform-git-backend-state-locking/01-example-project/010-backend.tf new file mode 100644 index 0000000..376ca1b --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/010-backend.tf @@ -0,0 +1,17 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + backend "http" {} +} \ No newline at end of file diff --git a/examples/terraform-git-backend-state-locking/01-example-project/020-provider.tf b/examples/terraform-git-backend-state-locking/01-example-project/020-provider.tf new file mode 100644 index 0000000..7a2d3c4 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/020-provider.tf @@ -0,0 +1,28 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = ">= 0.99.0" + } + } +} + +provider "stackit" { + default_region = var.stackit_region + service_account_key_path = var.stackit_service_account_key_path + enable_beta_resources = true +} diff --git a/examples/terraform-git-backend-state-locking/01-example-project/030-project.tf b/examples/terraform-git-backend-state-locking/01-example-project/030-project.tf new file mode 100644 index 0000000..1169d4f --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/030-project.tf @@ -0,0 +1,19 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +resource "stackit_resourcemanager_project" "this" { + parent_container_id = var.stackit_organization_id + name = var.stackit_project_name + owner_email = var.stackit_org_admin +} diff --git a/examples/terraform-git-backend-state-locking/01-example-project/README.md b/examples/terraform-git-backend-state-locking/01-example-project/README.md new file mode 100644 index 0000000..c4d3947 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/README.md @@ -0,0 +1,53 @@ +# Phase 1: Example Infrastructure + +This module contains the core infrastructure configuration. It uses the `http` backend to store state and enforce state locks via the STACKIT Git instance provisioned in Phase 0. + +## Implementation Steps + +1. Create a `backend.conf` from `backend.conf.example` and define the required variables using the Git Instance URL generated by the bootstrap module and your personal access token with permissions to write packages (`write:package`). + + +2. Initialize Terraform and bind it to the remote PostgreSQL backend + + ```sh + terraform init -backend-config=backend.conf + ``` + +3. Provision the infrastructure or run the lock validation script: + + ```sh + chmod +x ./scripts/validate_lock.sh + ./scripts/validate_lock.sh + ``` + +## Log Output + +```sh +➜ 01-example-project ~ ./scripts/test-state-lock.sh +[INFO] Initiating background 'terraform apply' to acquire the state lock... +[INFO] Attempting concurrent 'terraform plan'... +[INFO] ------------------------------------------------------------------ +╷ +│ Error: Error acquiring the state lock +│ +│ Error message: Already locked for workspace creation: default +│ Lock Info: +│ ID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX +│ Path: +│ Operation: OperationTypePlan +│ Who: XXXX +│ Version: 1.14.9 +│ Created: 2026-06-25 16:21:59.636986 +0000 UTC +│ Info: +│ +│ +│ Terraform acquires a state lock to protect the state from being written +│ by multiple users at the same time. Please resolve the issue above and try +│ again. For most commands, you can disable locking with the "-lock=false" +│ flag, but this is not recommended. +╵ +[INFO] ------------------------------------------------------------------ +[SUCCESS] Concurrent operation rejected. State locking is active and functional. +[INFO] Waiting for the background 'terraform apply' process to terminate... +[INFO] Evaluation complete. Cleaning up temporary logs... +``` diff --git a/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example b/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example new file mode 100644 index 0000000..3237512 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example @@ -0,0 +1,12 @@ +# Replace , (User or Organization), and +address = "/api/packages//terraform/state/" +lock_address = "/api/packages//terraform/state//lock" +unlock_address = "/api/packages//terraform/state//lock" + +lock_method = "POST" +unlock_method = "DELETE" +retry_wait_min = 5 + +# STACKIT Git credentials +username = "" +password = "" \ No newline at end of file diff --git a/examples/terraform-git-backend-state-locking/01-example-project/scripts/validate_lock.sh b/examples/terraform-git-backend-state-locking/01-example-project/scripts/validate_lock.sh new file mode 100755 index 0000000..d5ec204 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/scripts/validate_lock.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -u + +echo "[INFO] Initiating background 'terraform apply' to acquire the state lock..." +# Redirecting output to avoid console clutter during the concurrent test +terraform apply -auto-approve > apply_bg.log 2>&1 & +APPLY_PID=$! + +echo "[INFO] Attempting concurrent 'terraform plan'..." +echo "[INFO] ------------------------------------------------------------------" + +# Disable exit-on-error to capture the expected failure code +set +e +terraform plan +PLAN_EXIT_CODE=$? +set -e + +echo "[INFO] ------------------------------------------------------------------" + +if [ $PLAN_EXIT_CODE -ne 0 ]; then + echo "[SUCCESS] Concurrent operation rejected. State locking is active and functional." +else + echo "[ERROR] Concurrent operation succeeded. State locking failed or is misconfigured." +fi + +echo "[INFO] Waiting for the background 'terraform apply' process to terminate..." +wait $APPLY_PID + +echo "[INFO] Evaluation complete. Cleaning up temporary logs..." +rm -f apply_bg.log diff --git a/examples/terraform-git-backend-state-locking/01-example-project/terraform.tfvars.example b/examples/terraform-git-backend-state-locking/01-example-project/terraform.tfvars.example new file mode 100644 index 0000000..d16ff30 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/01-example-project/terraform.tfvars.example @@ -0,0 +1,31 @@ +# --------------------------------------------------------------------------- +# terraform.tfvars.example +# +# Copy this file into a project directory (e.g. 00-bootcamp/terraform.tfvars) +# and fill in your values. Do NOT commit terraform.tfvars to version control. +# +# Alternatively, export variables as environment variables: +# export TF_VAR_stackit_organization_id="" +# --------------------------------------------------------------------------- + +# --- STACKIT Identity -------------------------------------------------------- + +# Your STACKIT Organization ID. +# Portal: Organization > Settings > Organization ID +stackit_organization_id = "" + +## Name of the bootstrapping project +stackit_project_name = "01-example-project" + +# Email address of the STACKIT user set as project owner. +stackit_org_admin = " Service Accounts > Keys > Create key +stackit_service_account_key_path = "./keys/service-account.json" + +# --- Region ------------------------------------------------------------------ +stackit_region = "eu01" +default_zone = "eu01-1" diff --git a/examples/terraform-git-backend-state-locking/MAINTAINERS.md b/examples/terraform-git-backend-state-locking/MAINTAINERS.md new file mode 100644 index 0000000..f852b06 --- /dev/null +++ b/examples/terraform-git-backend-state-locking/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Tim Reibe () + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/terraform-git-backend-state-locking/README.md b/examples/terraform-git-backend-state-locking/README.md new file mode 100644 index 0000000..55f096f --- /dev/null +++ b/examples/terraform-git-backend-state-locking/README.md @@ -0,0 +1,12 @@ +# STACKIT Terraform Git Backend with State Locking and Versioning + +This repository demonstrates how to configure STACKIT Git as a Terraform backend to enable remote state storage and native state locking and state versioning. + +To resolve the circular dependency of provisioning a state backend using Terraform, the deployment is split into two isolated stages: + +1. **`00-bootstrap/`**: Provisions the backend infrastructure (Git instance). +2. **`01-example/`**: Represents the primary infrastructure, utilizing the provisioned Git instance as its remote backend. + +--- + +**⚠️ Security Notice:** The Git instance in `00-bootstrap/` is configured with an open ACL (`0.0.0.0/0`) for development convenience. Before deploying to production, restrict the ACL to your specific egress IP ranges to prevent the Git instance from being accessible via the public internet. -- 2.49.1 From 4ab900ab548e98f81f45f139cc0ab24bf022c127 Mon Sep 17 00:00:00 2001 From: Tim Reibe Date: Fri, 26 Jun 2026 14:20:39 +0200 Subject: [PATCH 2/2] updated readme --- .../01-example-project/backend.conf.example | 8 ++++---- examples/terraform-git-backend-state-locking/README.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example b/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example index 3237512..39c2010 100644 --- a/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example +++ b/examples/terraform-git-backend-state-locking/01-example-project/backend.conf.example @@ -1,7 +1,7 @@ -# Replace , (User or Organization), and -address = "/api/packages//terraform/state/" -lock_address = "/api/packages//terraform/state//lock" -unlock_address = "/api/packages//terraform/state//lock" +# Replace , (User or Organization), and +address = "/api/packages//terraform/state/" +lock_address = "/api/packages//terraform/state//lock" +unlock_address = "/api/packages//terraform/state//lock" lock_method = "POST" unlock_method = "DELETE" diff --git a/examples/terraform-git-backend-state-locking/README.md b/examples/terraform-git-backend-state-locking/README.md index 55f096f..322fb7e 100644 --- a/examples/terraform-git-backend-state-locking/README.md +++ b/examples/terraform-git-backend-state-locking/README.md @@ -1,6 +1,6 @@ # STACKIT Terraform Git Backend with State Locking and Versioning -This repository demonstrates how to configure STACKIT Git as a Terraform backend to enable remote state storage and native state locking and state versioning. +This repository demonstrates how to configure STACKIT Git as a Terraform backend to enable remote state storage with native state locking and state versioning. To resolve the circular dependency of provisioning a state backend using Terraform, the deployment is split into two isolated stages: -- 2.49.1