Skip to content

Commit c43ea76

Browse files
authored
feat: replace the time_sleep.wait_for_subscription resource with terraform_data.check_hyperconverged_status which will now run a scirpt to check readiness.<br>- updated the OCP DA dependency to v3.80.3<br>- updated the default value of "default_worker_pool_machine_type" to bx2d.metal.96x384 (#103)
1 parent b7be7e3 commit c43ea76

File tree

8 files changed

+179
-39
lines changed

8 files changed

+179
-39
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ You need the following permissions to run this module.
116116
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 3.0.0, <4.0.0 |
117117
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.79.1, <2.0.0 |
118118
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 3.0.0, < 4.0.0 |
119-
| <a name="requirement_time"></a> [time](#requirement\_time) | >= 0.9.1, < 1.0.0 |
120119

121120
### Modules
122121

@@ -130,12 +129,12 @@ No modules.
130129
| [helm_release.subscription](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
131130
| [kubernetes_config_map_v1_data.disable_default_storageclass](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map_v1_data) | resource |
132131
| [kubernetes_config_map_v1_data.set_vpc_file_default_storage_class](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map_v1_data) | resource |
132+
| [terraform_data.check_hyperconverged_status](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
133133
| [terraform_data.config_map_status](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
134134
| [terraform_data.enable_catalog_source](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
135135
| [terraform_data.install_required_binaries](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
136136
| [terraform_data.storageprofile_status](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
137137
| [terraform_data.update_storage_profile](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
138-
| [time_sleep.wait_for_subscription](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
139138
| [ibm_container_cluster_config.cluster_config](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/data-sources/container_cluster_config) | data source |
140139
| [ibm_container_vpc_cluster.cluster](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/data-sources/container_vpc_cluster) | data source |
141140

ibm_catalog.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@
669669
"key": "default_worker_pool_machine_type",
670670
"required": true,
671671
"type": "string",
672-
"default_value": "cx2d.metal.96x192",
672+
"default_value": "bx2d.metal.96x384",
673673
"description": "Specifies the machine type for the default worker pool. This determines the CPU, memory, and disk resources available to each worker node. For OpenShift Virtualization installation, machines should be VPC bare metal servers. Refer [IBM Cloud documentation for available machine types](https://cloud.ibm.com/docs/vpc?topic=vpc-bare-metal-servers-profile&interface=ui#bare-metal-profile-availability-by-region).",
674674
"virtual": true,
675675
"options": [
@@ -997,7 +997,7 @@
997997
"reference_version": true
998998
}
999999
],
1000-
"version": "v3.78.7"
1000+
"version": "v3.80.3"
10011001
}
10021002
],
10031003
"dependency_version_2": true,

main.tf

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,20 @@ locals {
109109
binaries_path = "/tmp"
110110
}
111111

112-
resource "time_sleep" "wait_for_subscription" {
113-
depends_on = [helm_release.subscription]
112+
resource "terraform_data" "check_hyperconverged_status" {
113+
depends_on = [helm_release.subscription, terraform_data.install_required_binaries]
114114

115-
create_duration = "240s"
115+
provisioner "local-exec" {
116+
command = "${path.module}/scripts/check_hyperconverged_status.sh ${local.binaries_path}"
117+
interpreter = ["/bin/bash", "-c"]
118+
environment = {
119+
KUBECONFIG = data.ibm_container_cluster_config.cluster_config.config_file_path
120+
}
121+
}
116122
}
117123

118124
resource "helm_release" "operator" {
119-
depends_on = [time_sleep.wait_for_subscription]
125+
depends_on = [terraform_data.check_hyperconverged_status]
120126
name = "${data.ibm_container_vpc_cluster.cluster.name}-operator"
121127
chart = local.operator_chart_location
122128
namespace = local.namespace
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# The binaries downloaded by the install-binaries script are located in the /tmp directory.
6+
export PATH=$PATH:${1:-"/tmp"}
7+
8+
NAMESPACE="openshift-cnv"
9+
COUNTER=0
10+
MAX_ATTEMPTS=60 # 60 attempts * 10 seconds = 10 minutes max wait
11+
SLEEP_INTERVAL=10
12+
13+
echo "========================================="
14+
echo "Checking HyperConverged CRD installation status..."
15+
echo "========================================="
16+
17+
# Function to check if CRD exists
18+
check_crd_exists() {
19+
kubectl get crd hyperconvergeds.hco.kubevirt.io &>/dev/null
20+
}
21+
22+
# Function to check if CSV (ClusterServiceVersion) is succeeded
23+
check_csv_status() {
24+
local csv_status
25+
csv_status=$(kubectl get csv -n "$NAMESPACE" -l operators.coreos.com/kubevirt-hyperconverged."$NAMESPACE" -o jsonpath='{.items[0].status.phase}' 2>/dev/null || echo "NotFound")
26+
27+
if [[ "$csv_status" == "Succeeded" ]]; then
28+
return 0
29+
else
30+
echo "CSV status: $csv_status"
31+
return 1
32+
fi
33+
}
34+
35+
# Wait for CRD to be created
36+
echo "Step 1: Waiting for HyperConverged CRD to be created..."
37+
while [[ $COUNTER -lt $MAX_ATTEMPTS ]]; do
38+
if check_crd_exists; then
39+
echo "✓ HyperConverged CRD is now available."
40+
break
41+
fi
42+
43+
COUNTER=$((COUNTER + 1))
44+
echo "Attempt $COUNTER/$MAX_ATTEMPTS: HyperConverged CRD not found, retrying in ${SLEEP_INTERVAL}s..."
45+
sleep $SLEEP_INTERVAL
46+
done
47+
48+
if [[ $COUNTER -eq $MAX_ATTEMPTS ]]; then
49+
echo "ERROR: HyperConverged CRD did not become available within $((MAX_ATTEMPTS * SLEEP_INTERVAL)) seconds."
50+
echo "Available CRDs:"
51+
kubectl get crd | grep -i hyperconverged || echo "No HyperConverged CRDs found"
52+
exit 1
53+
fi
54+
55+
# Reset counter for CSV check
56+
COUNTER=0
57+
58+
# Wait for CSV to be in Succeeded state
59+
echo ""
60+
echo "Step 2: Waiting for ClusterServiceVersion to reach 'Succeeded' state..."
61+
while [[ $COUNTER -lt $MAX_ATTEMPTS ]]; do
62+
if check_csv_status; then
63+
echo "✓ ClusterServiceVersion is in 'Succeeded' state."
64+
break
65+
fi
66+
67+
COUNTER=$((COUNTER + 1))
68+
echo "Attempt $COUNTER/$MAX_ATTEMPTS: CSV not ready, retrying in ${SLEEP_INTERVAL}s..."
69+
sleep $SLEEP_INTERVAL
70+
done
71+
72+
if [[ $COUNTER -eq $MAX_ATTEMPTS ]]; then
73+
echo "ERROR: ClusterServiceVersion did not reach 'Succeeded' state within $((MAX_ATTEMPTS * SLEEP_INTERVAL)) seconds."
74+
echo "Current CSV status:"
75+
kubectl get csv -n "$NAMESPACE" -l operators.coreos.com/kubevirt-hyperconverged."$NAMESPACE" || echo "No CSV found"
76+
exit 1
77+
fi
78+
79+
# Reset counter for operator pods check
80+
COUNTER=0
81+
82+
# Wait for operator pods to be ready
83+
echo ""
84+
echo "Step 3: Waiting for HyperConverged operator pods to be ready..."
85+
while [[ $COUNTER -lt $MAX_ATTEMPTS ]]; do
86+
# Check if all pods with kubevirt-hyperconverged label are running and ready
87+
TOTAL_PODS=$(kubectl get pods -n "$NAMESPACE" -l name=hyperconverged-cluster-operator --no-headers 2>/dev/null | wc -l | tr -d ' ')
88+
89+
if [[ $TOTAL_PODS -gt 0 ]]; then
90+
# Count pods that are NOT ready
91+
NOT_READY=$(kubectl get pods -n "$NAMESPACE" -l name=hyperconverged-cluster-operator -o jsonpath='{.items[*].status.conditions[?(@.type=="Ready")].status}' 2>/dev/null | grep -o "False" | wc -l | tr -d ' ')
92+
93+
if [[ $NOT_READY -eq 0 ]]; then
94+
echo "✓ All HyperConverged operator pods are ready ($TOTAL_PODS pods)."
95+
break
96+
else
97+
COUNTER=$((COUNTER + 1))
98+
echo "Attempt $COUNTER/$MAX_ATTEMPTS: Operator pods not all ready (Total: $TOTAL_PODS, Not Ready: $NOT_READY), retrying in ${SLEEP_INTERVAL}s..."
99+
fi
100+
else
101+
COUNTER=$((COUNTER + 1))
102+
echo "Attempt $COUNTER/$MAX_ATTEMPTS: No operator pods found yet, retrying in ${SLEEP_INTERVAL}s..."
103+
fi
104+
105+
sleep $SLEEP_INTERVAL
106+
done
107+
108+
if [[ $COUNTER -eq $MAX_ATTEMPTS ]]; then
109+
echo "ERROR: HyperConverged operator pods did not become ready within $((MAX_ATTEMPTS * SLEEP_INTERVAL)) seconds."
110+
echo "Current pod status:"
111+
kubectl get pods -n "$NAMESPACE" -l name=hyperconverged-cluster-operator || echo "No operator pods found"
112+
exit 1
113+
fi
114+
115+
echo ""
116+
echo "========================================="
117+
echo "✓ HyperConverged CRD is successfully installed and operator is running!"
118+
echo "========================================="

tests/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/IBM/go-sdk-core/v5 v5.21.2
77
github.com/gruntwork-io/terratest v0.55.0
88
github.com/stretchr/testify v1.11.1
9-
github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper v1.68.1
9+
github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper v1.68.2
1010
)
1111

1212
require (

tests/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
297297
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
298298
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
299299
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
300-
github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper v1.68.1 h1:FYS4Bxw6cXyKuCz4+IyN8GzaONJtlzHfOxty8DZsAbI=
301-
github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper v1.68.1/go.mod h1:1v2TpsR28LMR9EMNhGKh+8fnToAUbJ+2pqe7ihoJTeA=
300+
github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper v1.68.2 h1:0ZpuC1NVlEMXQYbO+IB5mVxCCzAl36LmTozInMkB44Q=
301+
github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper v1.68.2/go.mod h1:1v2TpsR28LMR9EMNhGKh+8fnToAUbJ+2pqe7ihoJTeA=
302302
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
303303
github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw=
304304
github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk=

tests/pr_test.go

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import (
99
"os/exec"
1010
"strings"
1111
"testing"
12+
"time"
1213

1314
"github.com/IBM/go-sdk-core/v5/core"
15+
"github.com/google/uuid"
1416
"github.com/gruntwork-io/terratest/modules/files"
1517
"github.com/gruntwork-io/terratest/modules/logger"
1618
"github.com/gruntwork-io/terratest/modules/random"
@@ -156,28 +158,41 @@ func validateEnvVariable(t *testing.T, varName string) string {
156158
return val
157159
}
158160

161+
func generateUniqueResourceGroupName(baseName string) string {
162+
id := uuid.New().String()[:8]
163+
return fmt.Sprintf("%s-%s", baseName, id)
164+
}
165+
159166
func setupTerraform(t *testing.T, prefix, realTerraformDir string) *terraform.Options {
160167
tempTerraformDir, err := files.CopyTerraformFolderToTemp(realTerraformDir, prefix)
161168
require.NoError(t, err, "Failed to create temporary Terraform folder")
162169
apiKey := validateEnvVariable(t, "TF_VAR_ibmcloud_api_key") // pragma: allowlist secret
163170
region, err := testhelper.GetBestVpcRegion(apiKey, "../common-dev-assets/common-go-assets/cloudinfo-region-vpc-gen2-prefs.yaml", "eu-de")
164171
require.NoError(t, err, "Failed to get best VPC region")
165172

173+
uniqueResourceGroup := generateUniqueResourceGroupName(prefix)
174+
166175
existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
167176
TerraformDir: tempTerraformDir,
168177
Vars: map[string]interface{}{
169-
"prefix": prefix,
170-
"region": region,
178+
"prefix": prefix,
179+
"region": region,
180+
"resource_group": uniqueResourceGroup,
171181
},
172182
// Set Upgrade to true to ensure latest version of providers and modules are used by terratest.
173183
// This is the same as setting the -upgrade=true flag with terraform.
174184
Upgrade: true,
175185
})
176186

177-
terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix)
178-
_, err = terraform.InitAndApplyE(t, existingTerraformOptions)
179-
require.NoError(t, err, "Init and Apply of temp existing resource failed")
180-
187+
err = sharedInfoSvc.WithNewResourceGroup(uniqueResourceGroup, func() error {
188+
// Temp workaround for https://github.com/terraform-ibm-modules/terraform-ibm-base-ocp-vpc?tab=readme-ov-file#the-specified-api-key-could-not-be-found
189+
createContainersApikey(t, region, uniqueResourceGroup)
190+
time.Sleep(5 * time.Second)
191+
terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix)
192+
_, err := terraform.InitAndApplyE(t, existingTerraformOptions)
193+
return err
194+
})
195+
require.NoError(t, err, "Failed to initialize and apply Terraform")
181196
return existingTerraformOptions
182197
}
183198

@@ -231,25 +246,31 @@ func TestRunUpgradeFullyConfigurable(t *testing.T) {
231246

232247
// Provision existing resources first
233248
prefix := fmt.Sprintf("ocp-existing-%s", strings.ToLower(random.UniqueId()))
234-
existingTerraformOptions := setupTerraform(t, prefix, "./resources")
235-
236-
options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{
237-
Testing: t,
238-
Prefix: "fc-upg",
239-
TarIncludePatterns: tarIncludePatterns,
240-
TemplateFolder: fullyConfigurableTerraformDir,
241-
Tags: []string{"test-schematic"},
242-
DeleteWorkspaceOnFail: false,
243-
})
244-
245-
options.TerraformVars = []testschematic.TestSchematicTerraformVar{
246-
{Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true},
247-
{Name: "cluster_id", Value: terraform.Output(t, existingTerraformOptions, "workload_cluster_id"), DataType: "string"},
248-
{Name: "cluster_resource_group_id", Value: terraform.Output(t, existingTerraformOptions, "cluster_resource_group_id"), DataType: "string"},
249+
skip, err := testhelper.ShouldSkipUpgradeTest(t)
250+
if err != nil {
251+
t.Fatal(err)
252+
}
253+
if !skip {
254+
existingTerraformOptions := setupTerraform(t, prefix, "./resources")
255+
256+
options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{
257+
Testing: t,
258+
Prefix: "fc-upg",
259+
TarIncludePatterns: tarIncludePatterns,
260+
TemplateFolder: fullyConfigurableTerraformDir,
261+
Tags: []string{"test-schematic"},
262+
DeleteWorkspaceOnFail: false,
263+
})
264+
265+
options.TerraformVars = []testschematic.TestSchematicTerraformVar{
266+
{Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true},
267+
{Name: "cluster_id", Value: terraform.Output(t, existingTerraformOptions, "workload_cluster_id"), DataType: "string"},
268+
{Name: "cluster_resource_group_id", Value: terraform.Output(t, existingTerraformOptions, "cluster_resource_group_id"), DataType: "string"},
269+
}
270+
271+
require.NoError(t, options.RunSchematicUpgradeTest(), "This should not have errored")
272+
cleanupTerraform(t, existingTerraformOptions, prefix)
249273
}
250-
251-
require.NoError(t, options.RunSchematicUpgradeTest(), "This should not have errored")
252-
cleanupTerraform(t, existingTerraformOptions, prefix)
253274
}
254275

255276
func TestAddonConfigurations(t *testing.T) {

version.tf

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,5 @@ terraform {
1414
source = "hashicorp/kubernetes"
1515
version = ">= 3.0.0, < 4.0.0"
1616
}
17-
time = {
18-
source = "hashicorp/time"
19-
version = ">= 0.9.1, < 1.0.0"
20-
}
2117
}
2218
}

0 commit comments

Comments
 (0)