docs: add Terraform certification notes and tasks
This commit is contained in:
129
terraform/task-32.md
Normal file
129
terraform/task-32.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Assignment
|
||||
|
||||
The Nautilus DevOps team is currently engaged in a cleanup process, focusing on removing unnecessary data and services from their AWS account. As part of the migration process, several resources were created for one-time use only, necessitating a cleanup effort to optimize their AWS environment.
|
||||
|
||||
Delete the IAM role named iamrole_ammar using Terraform. Make sure to keep the provisioning code, as we might need to provision this instance again later.
|
||||
|
||||
The Terraform working directory is /home/bob/terraform.
|
||||
|
||||
Note: Right-click under the EXPLORER section in VS Code and select Open in Integrated Terminal to launch the terminal.
|
||||
|
||||
# Solution
|
||||
|
||||
# Delete IAM Role (Keep Code) — `iamrole_ammar`
|
||||
|
||||
Same "delete but keep the code" pattern: **destroy** the role while leaving its
|
||||
provisioning block in `main.tf` for later reuse. A **targeted destroy** does exactly
|
||||
this — it acts on the real resource and Terraform state only, never on your `.tf`
|
||||
source.
|
||||
|
||||
## `main.tf` — leave unchanged
|
||||
|
||||
Do **not** delete or comment out the block. It stays exactly as given:
|
||||
|
||||
```hcl
|
||||
resource "aws_iam_role" "role" {
|
||||
name = "iamrole_ammar"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Version = "2012-10-17",
|
||||
Statement = [
|
||||
{
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "ec2.amazonaws.com"
|
||||
}
|
||||
Action = "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
tags = {
|
||||
Name = "iamrole_ammar"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## How to run
|
||||
|
||||
```bash
|
||||
cd /home/bob/terraform
|
||||
|
||||
# Destroy ONLY this IAM role; leaves the code in main.tf intact.
|
||||
terraform destroy -target=aws_iam_role.role -auto-approve
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
### Targeted destroy vs. the wrong approaches
|
||||
|
||||
| Approach | Result |
|
||||
|----------|--------|
|
||||
| Delete the resource block, then `apply` | Role is destroyed, but the **code is gone** — violates "keep the provisioning code." |
|
||||
| `terraform destroy` (no target) | Destroys **everything** in the config, not just this role. |
|
||||
| `terraform destroy -target=aws_iam_role.role` | Destroys **only** this role; code stays in `main.tf`. ✅ |
|
||||
|
||||
The `-target` flag scopes the operation to the single resource address
|
||||
(`aws_iam_role.role` — the **Terraform resource name** `role`, not the AWS role name
|
||||
`iamrole_ammar`). Terraform calls `DeleteRole`, removes the resource from state, and
|
||||
leaves your configuration untouched, because destroy operates on infrastructure and
|
||||
state, never on source code.
|
||||
|
||||
### Why the code surviving matters
|
||||
|
||||
Keeping the block means the role is trivially re-creatable later: a plain
|
||||
`terraform apply` will see it declared in config but absent from state and recreate
|
||||
it — assume-role policy and all. That satisfies "we might need to provision this
|
||||
again."
|
||||
|
||||
### One caveat for IAM roles
|
||||
|
||||
`DeleteRole` only succeeds if the role has **nothing attached**: no managed policies,
|
||||
no inline policies, and no instance profile referencing it. The `assume_role_policy`
|
||||
(trust policy) shown here is part of the role itself and does **not** block deletion —
|
||||
only *permission* policies and instance-profile links do. If the destroy errors with
|
||||
`DeleteConflict`, clear those first, then re-run:
|
||||
|
||||
```bash
|
||||
# Detach managed policies
|
||||
aws iam list-attached-role-policies --role-name iamrole_ammar \
|
||||
--query 'AttachedPolicies[].PolicyArn' --output text | \
|
||||
xargs -r -n1 -I{} aws iam detach-role-policy --role-name iamrole_ammar --policy-arn {}
|
||||
|
||||
# Delete inline policies
|
||||
aws iam list-role-policies --role-name iamrole_ammar \
|
||||
--query 'PolicyNames[]' --output text | \
|
||||
xargs -r -n1 -I{} aws iam delete-role-policy --role-name iamrole_ammar --policy-name {}
|
||||
|
||||
# Remove from any instance profiles
|
||||
aws iam list-instance-profiles-for-role --role-name iamrole_ammar \
|
||||
--query 'InstanceProfiles[].InstanceProfileName' --output text | \
|
||||
xargs -r -n1 -I{} aws iam remove-role-from-instance-profile --instance-profile-name {} --role-name iamrole_ammar
|
||||
|
||||
# Then retry
|
||||
terraform destroy -target=aws_iam_role.role -auto-approve
|
||||
```
|
||||
|
||||
For a bare role like this one (only a trust policy, no permissions attached), the
|
||||
plain targeted destroy works directly.
|
||||
|
||||
### Expected state afterward
|
||||
|
||||
After the destroy, the config still declares a resource that no longer exists in
|
||||
state, so `terraform plan` will show Terraform wants to **create** `iamrole_ammar`
|
||||
again (`+ 1 to add`). That's expected — **do not apply it**. The task wants the role
|
||||
deleted with the code retained, which is exactly this state.
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
aws iam get-role --role-name iamrole_ammar 2>&1 | grep -q 'NoSuchEntity' \
|
||||
&& echo "Role deleted." \
|
||||
|| echo "Role still exists."
|
||||
|
||||
# Confirm the code is still present
|
||||
grep -A18 'resource "aws_iam_role" "role"' /home/bob/terraform/main.tf
|
||||
```
|
||||
|
||||
Expected — `get-role` fails with `NoSuchEntity` (role gone), and the resource block is
|
||||
still present in `main.tf`.
|
||||
Reference in New Issue
Block a user