diff --git a/modules/dummy/.terraform-docs.yml b/modules/dummy/.terraform-docs.yml
new file mode 100644
index 000000000..3a69365ff
--- /dev/null
+++ b/modules/dummy/.terraform-docs.yml
@@ -0,0 +1,48 @@
+formatter: "markdown"
+
+version: ""
+
+header-from: docs/header.md
+footer-from: docs/footer.md
+
+recursive:
+ enabled: false
+ path: modules
+ include-main: true
+
+sections:
+ hide: []
+ show: []
+
+content: ""
+
+output:
+ file: "README.md"
+ mode: inject
+ template: |-
+
+ {{ .Content }}
+
+
+output-values:
+ enabled: false
+ from: ""
+
+sort:
+ enabled: true
+ by: name
+
+settings:
+ anchor: true
+ color: true
+ default: true
+ description: false
+ escape: true
+ hide-empty: false
+ html: true
+ indent: 2
+ lockfile: true
+ read-comments: true
+ required: true
+ sensitive: true
+ type: true
diff --git a/modules/dummy/README.md b/modules/dummy/README.md
index aa740c9e3..4985cad71 100644
--- a/modules/dummy/README.md
+++ b/modules/dummy/README.md
@@ -1,102 +1,128 @@
-# Terraform Diagnostic Executor Module
+
+# **Dummy Terraform Module**
-This module is designed for DevOps testing and CI/CD pipeline validation. It provides features to simulate network latency (sleep) and catastrophic failures (crash) at both the terraform plan and terraform apply stages.
+## Overview
-It leverages the external data source (for plan-time checks) and null_resource with local-exec provisioners (for apply-time actions).
+This Terraform module is designed for DevOps testing and CI/CD pipeline validation. It provides controls to simulate latency and failures at every phase of the Terraform lifecycle — plan, apply, and destroy — without affecting real infrastructure.
-## Prerequisites
+The module uses the `external` data source to execute a Node.js script for plan-time diagnostics and `null_resource` with `local-exec` provisioners for apply-time and destroy-time behavior. This makes it easy to reproduce slow or failing pipeline runs in a controlled, repeatable way.
-- Terraform: Required version ~> 1.0.
+Typical use cases include testing CI/CD pipeline timeouts, verifying failure-handling logic, and validating destroy-phase behavior in automated workflows.
-- Node.js: Must be installed and accessible via the PATH on the machine running terraform plan and terraform apply.
+## Key Features
-- Required Providers: hashicorp/external and hashicorp/null.
+- **Plan-time controls**: Simulate slow or failing `terraform plan` runs via a Node.js script executed by the `external` data source.
+- **Apply-time controls**: Introduce configurable delays or intentional failures during `terraform apply` using `null_resource` provisioners.
+- **Destroy-time controls**: Reliably gate sleep and crash behavior during `terraform destroy`, always present in state so destroy provisioners execute as expected.
+- **Deterministic destroy ordering**: The crash resource depends on the sleep resource, ensuring sleep always runs before crash when both are enabled.
+- **Input validation**: The `sleep_on_destroy` variable is validated to require a non-negative integer, preventing silent misconfigurations.
-## Module Usage
+## Basic Usage
-The module requires four primary boolean and numeric variables to control its diagnostic behavior.
+### Simulate apply-time delay and destroy-time failure
-Example
+```hcl
+module "dummy" {
+ source = "git::https://github.com/prefapp/tfm.git//modules/dummy"
-```terraform
-module "diagnostic_test" {
- source = "./node-executor"
-
- # Base input
instance_name = "ci-pipeline-check"
- # PLAN TIME CONTROLS
- sleep_on_plan = 5 # Delays 'terraform plan' by 5 seconds
- crash_on_plan = false # Set to true to force 'terraform plan' failure
-
- # APPLY TIME CONTROLS
- sleep_on_apply = 10 # Delays 'terraform apply' by 10 seconds
- crash_on_apply = false # Set to true to force 'terraform apply' failure
-}
-
-output "plan_status" {
- value = module.diagnostic_test.plan_message
+ sleep_on_apply = 10
+ crash_on_destroy = true
}
```
+### Simulate plan-time crash and destroy-time delay
-## Inputs
+```hcl
+module "dummy" {
+ source = "git::https://github.com/prefapp/tfm.git//modules/dummy"
-## Inputs
+ instance_name = "ci-pipeline-check"
-| Name | Description | Type | Default | Control Phase |
-|---|---|---|---|---|
-| `instance_name` | A unique identifier for the diagnostic run. | `string` | `"default-test"` | Both |
-| `sleep_on_plan` | Duration in seconds to delay the `terraform plan` execution. | `number` | `0` | Plan |
-| `crash_on_plan` | If set to true, forces `terraform plan` to fail immediately. | `bool` | `false` | Plan |
-| `sleep_on_apply` | Duration in seconds to delay the `terraform apply` execution. | `number` | `0` | Apply |
-| `crash_on_apply` | If set to true, forces `terraform apply` to fail immediately. | `bool` | `false` | Apply |
+ crash_on_plan = true
+ sleep_on_destroy = 30
+}
+```
+## File Structure
-## Outputs
+```
+dummy/
+├── .terraform-docs.yml # terraform-docs configuration
+├── README.md # Auto-generated documentation
+├── main.tf # Module resources and provisioners
+├── variables.tf # Input variable definitions
+├── outputs.tf # Output value definitions
+├── script.js # Node.js script for plan-time diagnostics
+├── _examples/ # Usage examples
+│ └── basic/ # Basic configuration example
+│ └── main.tf
+└── docs/ # Documentation source files
+ ├── header.md # This file
+ └── footer.md # Additional resources and support
+```
-| Name | Description | Value Source |
-| ----- | ----- | ----- |
-| `plan_message` | A status message from the plan-time script execution. | `data.external` |
-| `plan_timestamp` | The timestamp when the plan-time script executed. | `data.external` |
-| `plan_slept_for_s` | The actual seconds the script slept during plan. | `data.external` |
-| `plan_crashed` | Status indicating if the crash logic was executed during plan. | `data.external` |
+## Requirements
+No requirements.
-## Diagnostic Scenarios
+## Providers
-### 1. Test Plan Failure
+| Name | Version |
+|------|---------|
+| [external](#provider\_external) | n/a |
+| [null](#provider\_null) | n/a |
-To test how your CI/CD pipeline handles a plan failure:
+## Modules
-```terraform
-# Set crash_on_plan to true via command line
-terraform plan -var="crash_on_plan=true"
-```
+No modules.
+## Resources
+| Name | Type |
+|------|------|
+| [null_resource.conditional_crash](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [null_resource.conditional_destroy_crash](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [null_resource.conditional_destroy_sleep](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [null_resource.conditional_sleep](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [null_resource.diagnostic_base_logic](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [external_external.script_executor](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) | data source |
-Expected Result: The terraform plan command will exit with a non-zero exit code (failure) as the data "external" source executes the Node.js script, which calls process.exit(1).
+## Inputs
-### 2. Test Apply Failure
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [crash\_on\_apply](#input\_crash\_on\_apply) | Set to true to force a non-zero exit code during the 'apply' phase. | `bool` | `false` | no |
+| [crash\_on\_destroy](#input\_crash\_on\_destroy) | Set to true to force a non-zero exit code during the 'destroy' phase. | `bool` | `false` | no |
+| [crash\_on\_plan](#input\_crash\_on\_plan) | Set to true to force a non-zero exit code during the 'plan' phase. | `bool` | `false` | no |
+| [instance\_name](#input\_instance\_name) | A unique identifier for this module instance. | `string` | n/a | yes |
+| [sleep\_on\_apply](#input\_sleep\_on\_apply) | Number of seconds to sleep during the 'apply' phase. | `number` | `0` | no |
+| [sleep\_on\_destroy](#input\_sleep\_on\_destroy) | Number of seconds to sleep during the 'destroy' phase. | `number` | `0` | no |
+| [sleep\_on\_plan](#input\_sleep\_on\_plan) | Number of seconds to sleep during the 'plan' phase. | `number` | `0` | no |
-To test infrastructure deployment failure:
+## Outputs
-```terraform
-# Set crash_on_apply to true via command line
-terraform apply -auto-approve -var="crash_on_apply=true"
-```
+| Name | Description |
+|------|-------------|
+| [apply\_resource\_id](#output\_apply\_resource\_id) | The ID of the base null resource, indicating apply logic executed. |
+| [script\_message](#output\_script\_message) | The message returned by the external script (ran during plan). |
+| [script\_timestamp](#output\_script\_timestamp) | The timestamp returned by the external script (ran during plan). |
-Expected Result: The terraform apply command will fail when it attempts to create the null_resource.diagnostic_crash_logic because its local-exec provisioner executes the exit 1 shell command.
+## Examples
-### 3. Test Apply Timeout/Latency
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/dummy/_examples):
-To test pipeline timeouts during execution:
+- [Basic](https://github.com/prefapp/tfm/tree/main/modules/dummy/_examples/basic) - Minimal configuration showing plan, apply, and destroy controls
-```
-# Set a 30 second delay during the apply phase
-terraform apply -auto-approve -var="sleep_on_apply=30"
-```
+## Resources
+
+- **Terraform null provider**: [https://registry.terraform.io/providers/hashicorp/null/latest](https://registry.terraform.io/providers/hashicorp/null/latest)
+- **Terraform external provider**: [https://registry.terraform.io/providers/hashicorp/external/latest](https://registry.terraform.io/providers/hashicorp/external/latest)
+- **Terraform local-exec provisioner**: [https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec)
+## Support
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
+
diff --git a/modules/dummy/_examples/basic/main.tf b/modules/dummy/_examples/basic/main.tf
new file mode 100644
index 000000000..d8d3cb816
--- /dev/null
+++ b/modules/dummy/_examples/basic/main.tf
@@ -0,0 +1,29 @@
+# Basic example: simulate a 5-second delay during apply.
+# Useful for validating CI/CD pipeline timeout and failure-handling logic.
+# Set crash_on_destroy = true to test destroy-time failure behavior.
+
+module "dummy" {
+ source = "git::https://github.com/prefapp/tfm.git//modules/dummy"
+
+ instance_name = "ci-pipeline-check"
+
+ # PLAN TIME CONTROLS
+ sleep_on_plan = 0
+ crash_on_plan = false
+
+ # APPLY TIME CONTROLS
+ sleep_on_apply = 5 # Delays 'terraform apply' by 5 seconds
+ crash_on_apply = false
+
+ # DESTROY TIME CONTROLS
+ sleep_on_destroy = 0
+ crash_on_destroy = false # Set to true to force 'terraform destroy' failure
+}
+
+output "script_message" {
+ value = module.dummy.script_message
+}
+
+output "apply_resource_id" {
+ value = module.dummy.apply_resource_id
+}
diff --git a/modules/dummy/docs/footer.md b/modules/dummy/docs/footer.md
new file mode 100644
index 000000000..38fafb99a
--- /dev/null
+++ b/modules/dummy/docs/footer.md
@@ -0,0 +1,15 @@
+## Examples
+
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/dummy/_examples):
+
+- [Basic](https://github.com/prefapp/tfm/tree/main/modules/dummy/_examples/basic) - Minimal configuration showing plan, apply, and destroy controls
+
+## Resources
+
+- **Terraform null provider**: [https://registry.terraform.io/providers/hashicorp/null/latest](https://registry.terraform.io/providers/hashicorp/null/latest)
+- **Terraform external provider**: [https://registry.terraform.io/providers/hashicorp/external/latest](https://registry.terraform.io/providers/hashicorp/external/latest)
+- **Terraform local-exec provisioner**: [https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec)
+
+## Support
+
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
diff --git a/modules/dummy/docs/header.md b/modules/dummy/docs/header.md
new file mode 100644
index 000000000..08d599f6f
--- /dev/null
+++ b/modules/dummy/docs/header.md
@@ -0,0 +1,63 @@
+# **Dummy Terraform Module**
+
+## Overview
+
+This Terraform module is designed for DevOps testing and CI/CD pipeline validation. It provides controls to simulate latency and failures at every phase of the Terraform lifecycle — plan, apply, and destroy — without affecting real infrastructure.
+
+The module uses the `external` data source to execute a Node.js script for plan-time diagnostics and `null_resource` with `local-exec` provisioners for apply-time and destroy-time behavior. This makes it easy to reproduce slow or failing pipeline runs in a controlled, repeatable way.
+
+Typical use cases include testing CI/CD pipeline timeouts, verifying failure-handling logic, and validating destroy-phase behavior in automated workflows.
+
+## Key Features
+
+- **Plan-time controls**: Simulate slow or failing `terraform plan` runs via a Node.js script executed by the `external` data source.
+- **Apply-time controls**: Introduce configurable delays or intentional failures during `terraform apply` using `null_resource` provisioners.
+- **Destroy-time controls**: Reliably gate sleep and crash behavior during `terraform destroy`, always present in state so destroy provisioners execute as expected.
+- **Deterministic destroy ordering**: The crash resource depends on the sleep resource, ensuring sleep always runs before crash when both are enabled.
+- **Input validation**: The `sleep_on_destroy` variable is validated to require a non-negative integer, preventing silent misconfigurations.
+
+## Basic Usage
+
+### Simulate apply-time delay and destroy-time failure
+
+```hcl
+module "dummy" {
+ source = "git::https://github.com/prefapp/tfm.git//modules/dummy"
+
+ instance_name = "ci-pipeline-check"
+
+ sleep_on_apply = 10
+ crash_on_destroy = true
+}
+```
+
+### Simulate plan-time crash and destroy-time delay
+
+```hcl
+module "dummy" {
+ source = "git::https://github.com/prefapp/tfm.git//modules/dummy"
+
+ instance_name = "ci-pipeline-check"
+
+ crash_on_plan = true
+ sleep_on_destroy = 30
+}
+```
+
+## File Structure
+
+```
+dummy/
+├── .terraform-docs.yml # terraform-docs configuration
+├── README.md # Auto-generated documentation
+├── main.tf # Module resources and provisioners
+├── variables.tf # Input variable definitions
+├── outputs.tf # Output value definitions
+├── script.js # Node.js script for plan-time diagnostics
+├── _examples/ # Usage examples
+│ └── basic/ # Basic configuration example
+│ └── main.tf
+└── docs/ # Documentation source files
+ ├── header.md # This file
+ └── footer.md # Additional resources and support
+```
diff --git a/modules/dummy/main.tf b/modules/dummy/main.tf
index bf1c9e70c..9d34dca0e 100644
--- a/modules/dummy/main.tf
+++ b/modules/dummy/main.tf
@@ -3,13 +3,13 @@
data "external" "script_executor" {
# Execute the node binary directly for better reliability and bypass complex shell nesting issues.
program = [
- "node",
+ "node",
"${path.module}/script.js"
]
# Pass only the variables relevant to the PLAN phase to the script
query = {
- instance_name = var.instance_name
+ instance_name = var.instance_name
sleep_duration = var.sleep_on_plan
enable_crash = var.crash_on_plan
}
@@ -30,11 +30,11 @@ resource "null_resource" "conditional_sleep" {
triggers = {
run_always = timestamp()
}
-
+
provisioner "local-exec" {
# Executes the command using a standard sh interpreter
- interpreter = ["sh", "-c"]
-
+ interpreter = ["sh", "-c"]
+
# Echo message and then sleep. We use count[0] to access the instance.
command = "echo '--- APPLY-TIME DELAY --- Sleeping for ${var.sleep_on_apply} seconds...' && sleep ${var.sleep_on_apply}"
when = create
@@ -44,7 +44,7 @@ resource "null_resource" "conditional_sleep" {
# 3. Conditional Crash: This resource is only created if 'crash_on_apply' is true.
resource "null_resource" "conditional_crash" {
count = var.crash_on_apply ? 1 : 0
-
+
# Force re-creation on every apply to ensure the provisioner runs
triggers = {
run_always = timestamp()
@@ -52,30 +52,54 @@ resource "null_resource" "conditional_crash" {
provisioner "local-exec" {
# Executes the command using a standard sh interpreter
- interpreter = ["sh", "-c"]
-
+ interpreter = ["sh", "-c"]
+
# Echo message and then use 'exit 1' to deliberately cause failure
command = "echo '--- APPLY-TIME CRASH --- INTENTIONAL FAILURE' && exit 1"
when = create
}
}
-# --- Module Outputs ---
+# 4. Conditional Sleep on DESTROY
+resource "null_resource" "conditional_destroy_sleep" {
+ count = 1
-# Output from the PLAN-TIME script
-output "script_message" {
- description = "The message returned by the external script (ran during plan)."
- value = data.external.script_executor.result.message
-}
+ triggers = {
+ sleep_on_destroy = var.sleep_on_destroy
+ }
-# Output from the PLAN-TIME script
-output "script_timestamp" {
- description = "The timestamp returned by the external script (ran during plan)."
- value = data.external.script_executor.result.timestamp
+ provisioner "local-exec" {
+ when = destroy
+ interpreter = ["sh", "-c"]
+ command = <<-EOT
+ if [ "${self.triggers.sleep_on_destroy}" -gt 0 ]; then
+ echo '--- DESTROY-TIME DELAY --- Sleeping for ${self.triggers.sleep_on_destroy} seconds...'
+ sleep ${self.triggers.sleep_on_destroy}
+ else
+ echo '--- DESTROY-TIME DELAY --- Skipping sleep; sleep_on_destroy <= 0 ---'
+ fi
+ EOT
+ }
}
-# Check to ensure the base apply-time resource was created
-output "apply_resource_id" {
- description = "The ID of the base null resource, indicating apply logic executed."
- value = null_resource.diagnostic_base_logic.id
+# 5. Conditional Crash on DESTROY
+resource "null_resource" "conditional_destroy_crash" {
+ count = 1
+
+ triggers = {
+ crash_on_destroy = var.crash_on_destroy
+ }
+
+ provisioner "local-exec" {
+ when = destroy
+ interpreter = ["sh", "-c"]
+ command = <<-EOT
+ if [ "${self.triggers.crash_on_destroy}" = "true" ]; then
+ echo '--- DESTROY-TIME CRASH --- INTENTIONAL FAILURE'
+ exit 1
+ else
+ echo '--- DESTROY-TIME CRASH --- Skipping crash; crash_on_destroy = false ---'
+ fi
+ EOT
+ }
}
diff --git a/modules/dummy/outputs.tf b/modules/dummy/outputs.tf
new file mode 100644
index 000000000..4d5cb96d5
--- /dev/null
+++ b/modules/dummy/outputs.tf
@@ -0,0 +1,14 @@
+output "script_message" {
+ description = "The message returned by the external script (ran during plan)."
+ value = data.external.script_executor.result.message
+}
+
+output "script_timestamp" {
+ description = "The timestamp returned by the external script (ran during plan)."
+ value = data.external.script_executor.result.timestamp
+}
+
+output "apply_resource_id" {
+ description = "The ID of the base null resource, indicating apply logic executed."
+ value = null_resource.diagnostic_base_logic.id
+}
diff --git a/modules/dummy/variables.tf b/modules/dummy/variables.tf
index 09fa11316..1c6212e43 100644
--- a/modules/dummy/variables.tf
+++ b/modules/dummy/variables.tf
@@ -32,3 +32,21 @@ variable "crash_on_plan" {
default = false
}
+# 5. Sleep during 'terraform destroy'
+variable "sleep_on_destroy" {
+ description = "Number of seconds to sleep during the 'destroy' phase."
+ type = number
+ default = 0
+
+ validation {
+ condition = var.sleep_on_destroy >= 0 && floor(var.sleep_on_destroy) == var.sleep_on_destroy
+ error_message = "sleep_on_destroy must be a non-negative integer number of seconds."
+ }
+}
+
+# 6. Crash during 'terraform destroy'
+variable "crash_on_destroy" {
+ description = "Set to true to force a non-zero exit code during the 'destroy' phase."
+ type = bool
+ default = false
+}