Terraform Assignment– 5

Advanced Terraform Features

Basic Questions

  1. Initialize workspaces and create three environments named dev, stage, and prod.
  2. List all workspaces and select the dev workspace.
  3. Output the active workspace using terraform.workspace in an output block.
  4. Prefix a resource name with the current workspace (e.g., “${terraform.workspace}-sg”).
  5. Run plan separately in dev, stage, and prod and save each plan to a file.
  6. Apply a trivial resource in dev only, then destroy it using the same workspace.
  7. Create a string variable and print its length using the length() function.
  8. Use lookup() to safely read a value from a map variable with a default.
  9. Concatenate two lists using concat() and print the result as an output.
  10. Join a list of CIDRs into a comma-separated string using join().
  11. Split a comma-separated string into a list using split() and print index 0.
  12. Create a simple dynamic block to render multiple tags on a resource from a map.
  13. Create two similar resources using for_each over a set of names.
  14. Add a local-exec provisioner that writes “post-apply” to a local file.
  15. Add a remote-exec provisioner that runs echo hello on a test instance.
  16. Enable detailed logs by setting TF_LOG=DEBUG and run terraform plan.
  17. Use terraform console to evaluate an expression using contains() and upper().
  18. Format and validate the configuration using terraform fmt and terraform validate.
  19. Add depends_on to enforce creation order between two resources.
  20. Configure a basic multi-environment variable pattern with dev.tfvars, stage.tfvars, and prod.tfvars.

Intermediate Questions

  1. Configure a remote backend key that includes the workspace name (e.g., state/${terraform.workspace}/tfstate).
  2. For each workspace (dev, stage, prod), run plan with the matching -var-file.
  3. Use for_each on a map of subnets to create multiple subnet resources with tags.
  4. Use a dynamic block to generate multiple ingress rules from a list of objects.
  5. Build a map of common tags with merge() and apply it to all resources.
  6. Use coalesce() to fall back to a default AMI when a variable is empty.
  7. Use a conditional expression to choose instance size by environment.
  8. Replace a remote-exec bootstrap step with user data/cloud-init to avoid provisioners.
  9. Replace a local-exec artifact copy with a native Terraform resource/data source.
  10. Add variable validation (e.g., regex for environment names dev|stage|prod).
  11. Add a precondition check to ensure a CIDR block is within 10.0.0.0/8.
  12. Add a postcondition that asserts an output (e.g., subnet count > 0).
  13. Create a module call that passes different inputs per workspace using a lookup table.
  14. Compare count vs for_each by creating resources with both and documenting the differences in code comments.
  15. Use try() to handle a missing attribute and provide a safe default.
  16. Use keys() and values() to iterate a map and output a formatted string list.
  17. Generate a minimal dependency graph using terraform graph and save to a file.
  18. Simulate an error (invalid AMI) and capture diagnostics using TF_LOG and -json plan output.
  19. Add lifecycle { prevent_destroy = true } to a critical resource and test a destroy plan.
  20. Create a makefile or script to automate init → workspace select → plan → apply for dev.

Advanced Questions

  1. Implement a complete multi-environment stack where all resource names, tags, and backend keys are derived from terraform.workspace.
  2. Build a reusable module that accepts a map of environments and returns structured outputs; consume it from dev, stage, and prod.
  3. Create nested dynamic blocks (e.g., listeners → rules) driven by a list-of-maps variable.
  4. Use for expressions to transform a complex object variable into a flattened list for a resource argument.
  5. Compose functions (format(), replace(), trimsuffix(), coalescelist()) to compute image IDs and names per environment.
  6. Add robust input validation with multiple validation blocks and clear error messages for wrong types or ranges.
  7. Integrate a minimal smoke test: apply in dev, output a URL/IP, and verify reachability via a null_resource with local-exec curl (document why to avoid it in production).
  8. Introduce error-resilient rollout: use create_before_destroy and ignore_changes where appropriate, and demonstrate with a blue/green variable flag.
  9. Implement workspace-aware logging: send plan/apply logs to logs/${terraform.workspace}/YYYYMMDD-HHMM.txt.
  10. Deliver a hands-on multi-environment solution: init backend → create/select workspaces → apply dev with dev.tfvars → promote to stage and prod via the same config using only different workspaces and variable files.