Skip to content

Commit 473f6d1

Browse files
committed
Merge CI stability improvements from pr-225
- Extended test timeout from 30m to 60m - Added 90-minute job timeouts to GitHub Actions - Enhanced CloudStack simulator setup with better logging - Added retry logic for data center deployment - Improved error handling and diagnostics This addresses the 21 failing CI checks in PR #225.
2 parents d95c5a6 + dd20ff8 commit 473f6d1

File tree

4 files changed

+83
-12
lines changed

4 files changed

+83
-12
lines changed

.github/actions/setup-cloudstack/action.yml

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,30 @@ runs:
4343
run: |
4444
echo "Starting Cloudstack health check"
4545
T=0
46-
until [ $T -gt 40 ] || curl -sfL http://localhost:8080 --output /dev/null
46+
MAX_WAIT=40
47+
SLEEP_INTERVAL=30
48+
49+
echo "Will wait up to $((MAX_WAIT * SLEEP_INTERVAL / 60)) minutes for CloudStack to be ready"
50+
51+
until [ $T -gt $MAX_WAIT ] || curl -sfL http://localhost:8080 --output /dev/null
4752
do
48-
echo "Waiting for Cloudstack to be ready..."
53+
echo "Waiting for Cloudstack to be ready... (attempt $((T+1))/$((MAX_WAIT+1)), elapsed: $((T * SLEEP_INTERVAL / 60))m $((T * SLEEP_INTERVAL % 60))s)"
4954
((T+=1))
50-
sleep 30
55+
sleep $SLEEP_INTERVAL
5156
done
5257
5358
# After loop, check if Cloudstack is up
5459
if ! curl -sfSL http://localhost:8080 --output /dev/null; then
55-
echo "Cloudstack did not become ready in time"
60+
echo "Cloudstack did not become ready in time after $((MAX_WAIT * SLEEP_INTERVAL / 60)) minutes"
61+
echo "Checking CloudStack container status:"
62+
docker ps -a | grep cloudstack || echo "No CloudStack containers found"
63+
echo "Checking CloudStack logs:"
64+
docker logs $(docker ps -q --filter "ancestor=apache/cloudstack-simulator") --tail 50 || echo "Could not retrieve logs"
65+
echo "Testing connectivity:"
5666
curl -v http://localhost:8080 || true
5767
exit 22
68+
else
69+
echo "CloudStack is ready after $((T * SLEEP_INTERVAL / 60))m $((T * SLEEP_INTERVAL % 60))s"
5870
fi
5971
- name: Setting up Cloudstack
6072
id: setup-cloudstack
@@ -64,8 +76,23 @@ runs:
6476
set -euo pipefail
6577
6678
echo "Deploying Data Center..."
67-
docker exec $(docker container ls --format=json -l | jq -r .ID) \
68-
python /root/tools/marvin/marvin/deployDataCenter.py -i /root/setup/dev/advanced.cfg
79+
# Retry data center deployment up to 3 times
80+
for attempt in 1 2 3; do
81+
echo "Data center deployment attempt $attempt/3"
82+
if docker exec $(docker container ls --format=json -l | jq -r .ID) \
83+
python /root/tools/marvin/marvin/deployDataCenter.py -i /root/setup/dev/advanced.cfg; then
84+
echo "Data center deployment successful on attempt $attempt"
85+
break
86+
else
87+
echo "Data center deployment failed on attempt $attempt"
88+
if [ $attempt -eq 3 ]; then
89+
echo "All data center deployment attempts failed"
90+
exit 1
91+
fi
92+
echo "Waiting 30 seconds before retry..."
93+
sleep 30
94+
fi
95+
done
6996
7097
# Get the container ID of the running simulator
7198
CONTAINER_ID=$(docker ps --filter "ancestor=apache/cloudstack-simulator:${{ matrix.cloudstack-version }}" --format "{{.ID}}" | head -n1)

.github/workflows/acceptance.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ jobs:
4747
name: Terraform ${{ matrix.terraform-version }} with Cloudstack ${{ matrix.cloudstack-version }}
4848
needs: [prepare-matrix]
4949
runs-on: ubuntu-latest
50+
timeout-minutes: 90
5051
steps:
5152
- uses: actions/checkout@v4
5253
- name: Set up Go
@@ -86,6 +87,7 @@ jobs:
8687
name: OpenTofu ${{ matrix.opentofu-version }} with Cloudstack ${{ matrix.cloudstack-version }}
8788
needs: [prepare-matrix]
8889
runs-on: ubuntu-latest
90+
timeout-minutes: 90
8991
steps:
9092
- uses: actions/checkout@v4
9193
- name: Set up Go

GNUmakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ test: fmtcheck
3131
xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4
3232

3333
testacc: fmtcheck
34-
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 30m
34+
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 60m
3535

3636
vet:
3737
@echo "go vet ."

cloudstack/resource_cloudstack_egress_firewall.go

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,12 @@ func createEgressFirewallRule(d *schema.ResourceData, meta interface{}, rule map
331331
// by not setting startport and endport parameters
332332
r, err := cs.Firewall.CreateEgressFirewallRule(p)
333333
if err != nil {
334-
return err
334+
return fmt.Errorf("failed to create all-ports egress firewall rule: %w", err)
335335
}
336336
uuids["all"] = r.Id
337337
rule["uuids"] = uuids
338+
// Remove the ports field since we're creating an all-ports rule
339+
delete(rule, "ports")
338340
}
339341
}
340342

@@ -501,10 +503,50 @@ func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta interface
501503
// Update the values
502504
rule["protocol"] = r.Protocol
503505
rule["cidr_list"] = cidrs
506+
// Remove ports field for all-ports rules
507+
delete(rule, "ports")
504508
rules.Add(rule)
505509
}
506510
}
507511

512+
// Fallback: Check if any remaining rules in ruleMap match our expected all-ports pattern
513+
// This handles cases where CloudStack might return all-ports rules in unexpected formats
514+
if rule["protocol"].(string) != "icmp" && strings.ToLower(rule["protocol"].(string)) != "all" {
515+
// Look for any remaining rules that might be our all-ports rule
516+
for ruleID, r := range ruleMap {
517+
// Get local CIDR set for comparison
518+
localCidrSet, ok := rule["cidr_list"].(*schema.Set)
519+
if !ok {
520+
continue
521+
}
522+
523+
if isAllPortsTCPUDP(r.Protocol, r.Startport, r.Endport) &&
524+
strings.EqualFold(r.Protocol, rule["protocol"].(string)) &&
525+
cidrSetsEqual(r.Cidrlist, localCidrSet) {
526+
// This looks like our all-ports rule, add it to state
527+
cidrs := &schema.Set{F: schema.HashString}
528+
if r.Cidrlist != "" {
529+
for _, cidr := range strings.Split(r.Cidrlist, ",") {
530+
cidr = strings.TrimSpace(cidr)
531+
if cidr != "" {
532+
cidrs.Add(cidr)
533+
}
534+
}
535+
}
536+
537+
rule["protocol"] = r.Protocol
538+
rule["cidr_list"] = cidrs
539+
// Remove ports field for all-ports rules
540+
delete(rule, "ports")
541+
rules.Add(rule)
542+
543+
// Remove from ruleMap so it's not processed again
544+
delete(ruleMap, ruleID)
545+
break
546+
}
547+
}
548+
}
549+
508550
if strings.ToLower(rule["protocol"].(string)) == "all" {
509551
id, ok := uuids["all"]
510552
if !ok {
@@ -715,7 +757,7 @@ func verifyEgressFirewallParams(d *schema.ResourceData) error {
715757

716758
if !rules && !managed {
717759
return fmt.Errorf(
718-
"You must supply at least one 'rule' when not using the 'managed' firewall feature")
760+
"you must supply at least one 'rule' when not using the 'managed' firewall feature")
719761
}
720762

721763
return nil
@@ -731,11 +773,11 @@ func verifyEgressFirewallRuleParams(d *schema.ResourceData, rule map[string]inte
731773
if protocol == "icmp" {
732774
if _, ok := rule["icmp_type"]; !ok {
733775
return fmt.Errorf(
734-
"Parameter icmp_type is a required parameter when using protocol 'icmp'")
776+
"parameter icmp_type is a required parameter when using protocol 'icmp'")
735777
}
736778
if _, ok := rule["icmp_code"]; !ok {
737779
return fmt.Errorf(
738-
"Parameter icmp_code is a required parameter when using protocol 'icmp'")
780+
"parameter icmp_code is a required parameter when using protocol 'icmp'")
739781
}
740782
} else if strings.ToLower(protocol) != "all" {
741783
if ports, ok := rule["ports"].(*schema.Set); ok {
@@ -752,7 +794,7 @@ func verifyEgressFirewallRuleParams(d *schema.ResourceData, rule map[string]inte
752794
} else if strings.ToLower(protocol) == "all" {
753795
if ports, _ := rule["ports"].(*schema.Set); ports.Len() > 0 {
754796
return fmt.Errorf(
755-
"Parameter ports is not required when using protocol 'ALL'")
797+
"parameter ports is not required when using protocol 'ALL'")
756798
}
757799
}
758800

0 commit comments

Comments
 (0)