Skip to content

Commit 79b10df

Browse files
committed
OCM-23281 | fix: change rhcs_hcp_default_ingress to fall back to var.wait_for_create_complete
1 parent 9530e9b commit 79b10df

6 files changed

Lines changed: 96 additions & 2 deletions

File tree

.cursor/rules/rosa-hcp-terraform.mdc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ This repository implements **ROSA with Hosted Control Plane (HCP)** only. Do not
3333
## Security
3434

3535
- Do not hardcode secrets or long-lived AWS keys in Terraform. Align with existing **`examples/`** and Red Hat guidance for STS, OIDC, and IRSA. Use **`sensitive`** where appropriate; avoid exposing secrets in outputs, state-adjacent logging, or ad-hoc debug prints.
36+
- **Outputs:** If a submodule output is **`sensitive = true`**, any **root** (or parent) output that passes it through (e.g. **`value = module.child.output_name`**) must also use **`sensitive = true`**. Terraform requires this when the value is or derives from sensitive data; keep child and parent aligned (e.g. **`cluster_admin_username`** alongside **`cluster_admin_password`**).
3637

3738
## Variables
3839

3940
- Every variable: `type`, `description`, and `default` when optional — match tone and structure of existing `variables.tf`.
4041
- Use **`snake_case`** for names (Terraform convention). Prefer **validation** / **lifecycle precondition** for simple checks (null/empty/enum); let the provider enforce complex cross-field rules.
4142
- **Nullable values in `validation` conditions:** Do not pass a possibly-**`null`** expression into **`contains(...)`** (or similar functions that reject null). That can surface as **`Invalid value for "value" parameter: argument must not be null.`** during validation/plan. Use a **short-circuiting ternary** so `contains` runs only when the value is non-null, e.g. `var.example == null ? true : contains(["a", "b"], var.example)` — not `var.example == null || contains(..., var.example)`.
43+
- **Import-safe `count` / `for_each`:** Avoid boolean **`count`** / **`for_each`** conditions that depend **only** on a **resource or data source attribute** that can be **`null`** in partial state (e.g. immediately after **`terraform import`** before refresh). Terraform requires **`true` or `false`**; **`null`** triggers **`The condition value is null. Conditions must either be true or false.`** Prefer driving **`count` / `for_each` from `var.*`** only.
4244
- **Typed maps vs `map(any)`:** When a map’s values are the same logical object (e.g. keyed log forwarders, pools), prefer **`map(object({ ... }))`** with **`optional(...)`** for nullable blocks — not **`map(any)`** — so mixed entries (e.g. one key uses `s3`, another `cloudwatch`) type-check without “all map elements must have the same type”. Add root **`validation`** blocks for cross-field rules users hit early; child modules may keep **`lifecycle` precondition** as a second line of defense.
4345

4446
## Procedures and commands

AGENTS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Useful skills for this codebase:
5050
**Agent-oriented checks** when editing Terraform, **`examples/`**, and tests:
5151

5252
- Do **not** hardcode secrets, API keys, or long-lived AWS access keys in Terraform, examples, or tests. Prefer patterns in existing **`examples/`** and Red Hat documentation (STS, OIDC, IRSA, short-lived credentials).
53-
- Use **`sensitive`** on variables and outputs where values must not appear in logs or casual `terraform show` output; avoid echoing secrets in `local` values used only for debugging.
53+
- Use **`sensitive`** on variables and outputs where values must not appear in logs or casual `terraform show` output; avoid echoing secrets in `local` values used only for debugging. Passthrough outputs (**`module.*` → root output**) must match submodule sensitivity—see **Security** in [`.cursor/rules/rosa-hcp-terraform.mdc`](.cursor/rules/rosa-hcp-terraform.mdc).
5454
- Do not add logging, outputs, or comments that expose credentials or session tokens.
5555

5656
## Critical Module Guardrails
@@ -74,4 +74,6 @@ New features should include a new `.tftest.hcl` file or an update to an existing
7474

7575
Use mocks for AWS and RHCS resources to verify logic without requiring live credentials.
7676

77+
When module behavior branches on a **boolean variable** (e.g. **`count = var.x ? 1 : 0`**), prefer **more than one `run` block** (or clearly separated scenarios) so **both** outcomes are covered—typically **`true` / `count = 1`** and **`false` / `count = 0`**—not only the default or “happy” path. That avoids regressions where the positive case passes but the opt-out path breaks.
78+
7779
For exact commands and pass/fail criteria, follow **`CONTRIBUTING.md`**.

modules/rosa-cluster-hcp/main.tf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ resource "rhcs_hcp_cluster_autoscaler" "cluster_autoscaler" {
147147
}
148148

149149
resource "rhcs_hcp_default_ingress" "default_ingress" {
150-
count = rhcs_cluster_rosa_hcp.rosa_hcp_cluster.wait_for_create_complete ? 1 : 0
150+
# After import, cluster.wait_for_create_complete may be null until refresh;
151+
# always fall back to var and its default.
152+
count = var.wait_for_create_complete ? 1 : 0
151153
cluster = rhcs_cluster_rosa_hcp.rosa_hcp_cluster.id
152154
listening_method = var.default_ingress_listening_method != "" ? (
153155
var.default_ingress_listening_method) : (

modules/rosa-cluster-hcp/outputs.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ output "cluster_id" {
66
output "cluster_admin_username" {
77
value = rhcs_cluster_rosa_hcp.rosa_hcp_cluster.admin_credentials == null ? null : rhcs_cluster_rosa_hcp.rosa_hcp_cluster.admin_credentials.username
88
description = "The username of the admin user."
9+
sensitive = true
910
}
1011

1112
output "cluster_admin_password" {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# rhcs_hcp_default_ingress count follows var.wait_for_create_complete only (see main.tf).
2+
# Driving count from resource attributes that can be null after import caused:
3+
# "The condition value is null. Conditions must either be true or false."
4+
# These plan-mode runs assert both branches: count 1 when true, count 0 when false.
5+
6+
mock_provider "aws" {
7+
alias = "default"
8+
9+
mock_data "aws_partition" {
10+
defaults = {
11+
dns_suffix = "amazonaws.com"
12+
id = "aws"
13+
partition = "aws"
14+
reverse_dns_prefix = "amazonaws.com"
15+
}
16+
}
17+
18+
mock_data "aws_subnet" {
19+
defaults = {
20+
availability_zone = "us-east-1a"
21+
id = "subnet-fake12345"
22+
}
23+
}
24+
}
25+
26+
mock_provider "rhcs" {
27+
alias = "import_sim"
28+
override_during = plan
29+
30+
# Partial cluster state simulation for plan (not used for default_ingress count).
31+
mock_resource "rhcs_cluster_rosa_hcp" {
32+
defaults = {
33+
id = "rhcs-fake-cluster-id"
34+
wait_for_create_complete = null
35+
}
36+
}
37+
38+
mock_resource "rhcs_hcp_default_ingress" {
39+
defaults = {}
40+
}
41+
}
42+
43+
variables {
44+
cluster_name = "existing-cluster"
45+
openshift_version = "4.15.0"
46+
oidc_config_id = "00000000000000000000000000000000"
47+
operator_role_prefix = "test-operator-prefix"
48+
account_role_prefix = "test-account-prefix"
49+
aws_subnet_ids = ["subnet-fake12345"]
50+
aws_availability_zones = ["us-east-1a"]
51+
aws_account_id = "123456789012"
52+
aws_account_arn = "arn:aws:iam::123456789012:root"
53+
aws_region = "us-east-1"
54+
}
55+
56+
run "plan_default_ingress_count_when_wait_for_create_complete_true" {
57+
command = plan
58+
59+
providers = {
60+
aws = aws.default
61+
rhcs = rhcs.import_sim
62+
}
63+
64+
assert {
65+
condition = length(rhcs_hcp_default_ingress.default_ingress) == 1
66+
error_message = "rhcs_hcp_default_ingress.default_ingress must have count 1 when var.wait_for_create_complete is true."
67+
}
68+
}
69+
70+
run "plan_default_ingress_count_when_wait_for_create_complete_false" {
71+
command = plan
72+
73+
providers = {
74+
aws = aws.default
75+
rhcs = rhcs.import_sim
76+
}
77+
78+
variables {
79+
wait_for_create_complete = false
80+
}
81+
82+
assert {
83+
condition = length(rhcs_hcp_default_ingress.default_ingress) == 0
84+
error_message = "rhcs_hcp_default_ingress.default_ingress must have count 0 when var.wait_for_create_complete is false."
85+
}
86+
}

outputs.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ output "cluster_id" {
88
output "cluster_admin_username" {
99
value = module.rosa_cluster_hcp.cluster_admin_username
1010
description = "The username of the admin user."
11+
sensitive = true
1112
}
1213

1314
output "cluster_admin_password" {

0 commit comments

Comments
 (0)