Skip to content

Commit 441cb68

Browse files
committed
change how we ensure clean state
1 parent 2195113 commit 441cb68

File tree

3 files changed

+191
-60
lines changed

3 files changed

+191
-60
lines changed

internal/controller/test_helper.go

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package controller
5+
6+
import (
7+
"context"
8+
"time"
9+
10+
. "github.com/onsi/ginkgo/v2" // nolint: staticcheck
11+
. "github.com/onsi/gomega" // nolint: staticcheck
12+
"sigs.k8s.io/controller-runtime/pkg/client"
13+
14+
metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
15+
)
16+
17+
// EnsureCleanState ensures that all ServerClaims and cluster scoped objects are removed from the API server.
18+
// This function properly deletes resources in dependency order and waits for finalizers to complete.
19+
func EnsureCleanState() {
20+
GinkgoHelper()
21+
22+
ctx := context.Background()
23+
24+
// Step 1: Delete all dependent resources first (in reverse dependency order)
25+
// This ensures proper cleanup without orphaned resources
26+
27+
// Delete ServerClaims first (they reference Servers)
28+
claimList := &metalv1alpha1.ServerClaimList{}
29+
Expect(k8sClient.List(ctx, claimList)).To(Succeed())
30+
for i := range claimList.Items {
31+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &claimList.Items[i]))).To(Succeed())
32+
}
33+
34+
// Delete BIOS settings BEFORE maintenance (they may create maintenance)
35+
biosSettingsList := &metalv1alpha1.BIOSSettingsList{}
36+
Expect(k8sClient.List(ctx, biosSettingsList)).To(Succeed())
37+
for i := range biosSettingsList.Items {
38+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &biosSettingsList.Items[i]))).To(Succeed())
39+
}
40+
41+
biosSettingsSetList := &metalv1alpha1.BIOSSettingsSetList{}
42+
Expect(k8sClient.List(ctx, biosSettingsSetList)).To(Succeed())
43+
for i := range biosSettingsSetList.Items {
44+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &biosSettingsSetList.Items[i]))).To(Succeed())
45+
}
46+
47+
// Wait for BIOS settings to be deleted before proceeding
48+
Eventually(func() int {
49+
biosList := &metalv1alpha1.BIOSSettingsList{}
50+
_ = k8sClient.List(ctx, biosList)
51+
return len(biosList.Items)
52+
}).WithTimeout(30 * time.Second).WithPolling(500 * time.Millisecond).Should(Equal(0))
53+
54+
// Delete maintenance resources (they block Server deletion via finalizers)
55+
maintenanceList := &metalv1alpha1.ServerMaintenanceList{}
56+
Expect(k8sClient.List(ctx, maintenanceList)).To(Succeed())
57+
for i := range maintenanceList.Items {
58+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &maintenanceList.Items[i]))).To(Succeed())
59+
}
60+
61+
// Wait for maintenance to be fully deleted before deleting Servers
62+
Eventually(func() int {
63+
mList := &metalv1alpha1.ServerMaintenanceList{}
64+
_ = k8sClient.List(ctx, mList)
65+
return len(mList.Items)
66+
}).WithTimeout(30 * time.Second).WithPolling(500 * time.Millisecond).Should(Equal(0))
67+
68+
// Delete BMC version resources
69+
bmcVersionList := &metalv1alpha1.BMCVersionList{}
70+
Expect(k8sClient.List(ctx, bmcVersionList)).To(Succeed())
71+
for i := range bmcVersionList.Items {
72+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &bmcVersionList.Items[i]))).To(Succeed())
73+
}
74+
75+
bmcVersionSetList := &metalv1alpha1.BMCVersionSetList{}
76+
Expect(k8sClient.List(ctx, bmcVersionSetList)).To(Succeed())
77+
for i := range bmcVersionSetList.Items {
78+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &bmcVersionSetList.Items[i]))).To(Succeed())
79+
}
80+
81+
// Delete BMC settings
82+
bmcSettingsList := &metalv1alpha1.BMCSettingsList{}
83+
Expect(k8sClient.List(ctx, bmcSettingsList)).To(Succeed())
84+
for i := range bmcSettingsList.Items {
85+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &bmcSettingsList.Items[i]))).To(Succeed())
86+
}
87+
88+
// Delete Servers (they reference BMCs and BMCSecrets)
89+
serverList := &metalv1alpha1.ServerList{}
90+
Expect(k8sClient.List(ctx, serverList)).To(Succeed())
91+
for i := range serverList.Items {
92+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &serverList.Items[i]))).To(Succeed())
93+
}
94+
95+
// Delete BMCs
96+
bmcList := &metalv1alpha1.BMCList{}
97+
Expect(k8sClient.List(ctx, bmcList)).To(Succeed())
98+
for i := range bmcList.Items {
99+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &bmcList.Items[i]))).To(Succeed())
100+
}
101+
102+
// Delete BMCSecrets
103+
bmcSecretList := &metalv1alpha1.BMCSecretList{}
104+
Expect(k8sClient.List(ctx, bmcSecretList)).To(Succeed())
105+
for i := range bmcSecretList.Items {
106+
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, &bmcSecretList.Items[i]))).To(Succeed())
107+
}
108+
109+
// Step 2: Wait for all resources to be fully deleted (finalizers completed)
110+
// Use a single Eventually with proper assertions (no nested Eventually)
111+
112+
Eventually(func(g Gomega) {
113+
// Verify all ServerClaims are gone
114+
claims := &metalv1alpha1.ServerClaimList{}
115+
g.Expect(k8sClient.List(ctx, claims)).To(Succeed())
116+
g.Expect(claims.Items).To(BeEmpty(), "ServerClaims should be deleted")
117+
118+
// Verify all maintenance resources are gone
119+
maintenance := &metalv1alpha1.ServerMaintenanceList{}
120+
g.Expect(k8sClient.List(ctx, maintenance)).To(Succeed())
121+
g.Expect(maintenance.Items).To(BeEmpty(), "ServerMaintenance should be deleted")
122+
123+
// Verify all BIOS settings are gone
124+
biosSettings := &metalv1alpha1.BIOSSettingsList{}
125+
g.Expect(k8sClient.List(ctx, biosSettings)).To(Succeed())
126+
g.Expect(biosSettings.Items).To(BeEmpty(), "BIOSSettings should be deleted")
127+
128+
biosSettingsSets := &metalv1alpha1.BIOSSettingsSetList{}
129+
g.Expect(k8sClient.List(ctx, biosSettingsSets)).To(Succeed())
130+
g.Expect(biosSettingsSets.Items).To(BeEmpty(), "BIOSSettingsSets should be deleted")
131+
132+
// Verify all BMC versions are gone
133+
bmcVersions := &metalv1alpha1.BMCVersionList{}
134+
g.Expect(k8sClient.List(ctx, bmcVersions)).To(Succeed())
135+
g.Expect(bmcVersions.Items).To(BeEmpty(), "BMCVersions should be deleted")
136+
137+
bmcVersionSets := &metalv1alpha1.BMCVersionSetList{}
138+
g.Expect(k8sClient.List(ctx, bmcVersionSets)).To(Succeed())
139+
g.Expect(bmcVersionSets.Items).To(BeEmpty(), "BMCVersionSets should be deleted")
140+
141+
// Verify all BMC settings are gone
142+
bmcSettings := &metalv1alpha1.BMCSettingsList{}
143+
g.Expect(k8sClient.List(ctx, bmcSettings)).To(Succeed())
144+
g.Expect(bmcSettings.Items).To(BeEmpty(), "BMCSettings should be deleted")
145+
146+
// Verify all Servers are gone - with better error message
147+
servers := &metalv1alpha1.ServerList{}
148+
g.Expect(k8sClient.List(ctx, servers)).To(Succeed())
149+
if len(servers.Items) > 0 {
150+
// Provide detailed info about stuck servers
151+
for _, srv := range servers.Items {
152+
GinkgoWriter.Printf("Server %s stuck: DeletionTimestamp=%v, Finalizers=%v, MaintenanceRef=%v\n",
153+
srv.Name, srv.DeletionTimestamp, srv.Finalizers, srv.Spec.ServerMaintenanceRef)
154+
}
155+
}
156+
g.Expect(servers.Items).To(BeEmpty(), "Servers should be deleted")
157+
158+
// Verify all BMCs are gone
159+
bmcs := &metalv1alpha1.BMCList{}
160+
g.Expect(k8sClient.List(ctx, bmcs)).To(Succeed())
161+
g.Expect(bmcs.Items).To(BeEmpty(), "BMCs should be deleted")
162+
163+
// Verify all BMCSecrets are gone
164+
bmcSecrets := &metalv1alpha1.BMCSecretList{}
165+
g.Expect(k8sClient.List(ctx, bmcSecrets)).To(Succeed())
166+
g.Expect(bmcSecrets.Items).To(BeEmpty(), "BMCSecrets should be deleted")
167+
}).WithTimeout(3 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())
168+
}

internal/probe/probe.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,39 +45,53 @@ func (a *Agent) Init(ctx context.Context) error {
4545
}
4646
systeminfo, err := collectSystemInfoData()
4747
if err != nil {
48-
return err
48+
a.log.Info("System info collection skipped (DMI/SMBIOS not accessible)", "error", err.Error())
49+
// Continue without system info - use empty struct
50+
systeminfo = registry.DMI{}
4951
}
5052

5153
cpuInfos, err := collectCPUInfoData()
5254
if err != nil {
53-
return err
55+
a.log.Info("CPU info collection skipped", "error", err.Error())
56+
// Continue without CPU info
57+
cpuInfos = []registry.CPUInfo{}
5458
}
5559

5660
LLDPInfo, err := collectLLDPInfo(ctx, a.LLDPSyncInterval, a.LLDPSyncDuration)
5761
if err != nil {
58-
a.log.Error(err, "failed to collect LLDP info")
59-
return err
62+
a.log.Info("LLDP info collection skipped (lldpctl not available or failed)", "error", err.Error())
63+
// Continue without LLDP info - it's optional
64+
LLDPInfo = registry.LLDP{}
65+
} else {
66+
a.log.Info("Collected LLDP info", "interfaces", len(LLDPInfo.Interfaces))
6067
}
61-
a.log.Info("Collected LLDP info", "interfaces", len(LLDPInfo.Interfaces))
6268

6369
blockDevices, err := collectStorageInfoData()
6470
if err != nil {
65-
return err
71+
a.log.Info("Storage info collection skipped", "error", err.Error())
72+
// Continue without storage info
73+
blockDevices = []registry.BlockDevice{}
6674
}
6775

6876
memoryDevices, err := collectMemoryInfoData()
6977
if err != nil {
70-
return err
78+
a.log.Info("Memory info collection skipped", "error", err.Error())
79+
// Continue without memory info
80+
memoryDevices = []registry.MemoryDevice{}
7181
}
7282

7383
nics, err := collectNICInfoData()
7484
if err != nil {
75-
return err
85+
a.log.Info("NIC info collection skipped", "error", err.Error())
86+
// Continue without NIC info
87+
nics = []registry.NIC{}
7688
}
7789

7890
pciDevices, err := collectPCIDevicesInfoData()
7991
if err != nil {
80-
return err
92+
a.log.Info("PCI devices info collection skipped", "error", err.Error())
93+
// Continue without PCI device info
94+
pciDevices = []registry.PCIDevice{}
8195
}
8296

8397
a.Server = &registry.Server{

0 commit comments

Comments
 (0)