@@ -2,6 +2,7 @@ package cluster
22
33import (
44 "context"
5+ "fmt"
56 "time"
67
78 "github.com/onsi/ginkgo/v2"
@@ -13,8 +14,8 @@ import (
1314 "github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/labels"
1415)
1516
16- var _ = ginkgo .Describe ("Cluster Resource Type Lifecycle" ,
17- ginkgo .Label (labels .Tier0 , "baseline" ),
17+ var _ = ginkgo .Describe ("[Suite: cluster][baseline] Cluster Resource Type Lifecycle" ,
18+ ginkgo .Label (labels .Tier0 ),
1819 func () {
1920 var h * helper.Helper
2021 var clusterID string
@@ -158,6 +159,20 @@ var _ = ginkgo.Describe("Cluster Resource Type Lifecycle",
158159 "cluster condition %s should have observed_generation=1 for new creation request" , condition .Type )
159160 }
160161 }
162+
163+ // Validate adapter-specific conditions in cluster status
164+ // Each required adapter should report its own condition type (e.g., ClNamespaceSuccessful, ClJobSuccessful)
165+ for _ , adapterName := range h .Cfg .Adapters .Cluster {
166+ expectedCondType := h .AdapterNameToClusterConditionType (adapterName )
167+ hasAdapterCondition := h .HasResourceCondition (
168+ finalCluster .Status .Conditions ,
169+ expectedCondType ,
170+ openapi .ResourceConditionStatusTrue ,
171+ )
172+ Expect (hasAdapterCondition ).To (BeTrue (),
173+ "cluster should have %s=True condition for adapter %s" ,
174+ expectedCondType , adapterName )
175+ }
161176 })
162177 })
163178
@@ -211,8 +226,7 @@ var _ = ginkgo.Describe("Cluster Resource Type Lifecycle",
211226 for _ , adapterName := range h .Cfg .Adapters .Cluster {
212227 verifier , exists := adapterResourceVerifiers [adapterName ]
213228 if ! exists {
214- ginkgo .GinkgoWriter .Printf ("Warning: no K8s resource verifier defined for adapter %s, skipping\n " , adapterName )
215- continue
229+ ginkgo .Fail (fmt .Sprintf ("No K8s resource verifier defined for adapter %s - test configuration error" , adapterName ))
216230 }
217231
218232 ginkgo .By ("Verifying Kubernetes resource for adapter: " + adapterName )
@@ -226,138 +240,139 @@ var _ = ginkgo.Describe("Cluster Resource Type Lifecycle",
226240 })
227241
228242 ginkgo .Describe ("Adapter Dependency Relationships Workflow Validation" , func () {
229- // This test validates adapter dependency relationships:
230- // 1. During cl-job execution: cl-deployment Applied=False and Available=Unknown (never False)
231- // 2. After cl-job completes: cl-deployment can proceed (no validation on Available during execution)
232- // 3. Eventually: cl-deployment Available becomes True (success)
233- ginkgo .It ("should validate cl-deployment dependency on cl-job with comprehensive condition checks" ,
234- func (ctx context.Context ) {
235- pollingInterval := "1s"
236-
237- ginkgo .By ("Verify cl-deployment initial state and dependency waiting behavior" )
238- // Capture cl-deployment's initial waiting state
239- // Poll until cl-deployment appears in the statuses
240- var foundInitialState bool
241- Eventually (func (g Gomega ) {
243+ // This test validates adapter dependency relationships:
244+ // 1. During cl-job execution: cl-deployment Applied=False and Available=Unknown (never False)
245+ // 2. After cl-job completes: cl-deployment can proceed (no validation on Available during execution)
246+ // 3. Eventually: cl-deployment Available becomes True (success)
247+ ginkgo .It ("should validate cl-deployment dependency on cl-job with comprehensive condition checks" ,
248+ func (ctx context.Context ) {
249+ pollingInterval := "1s"
250+
251+ ginkgo .By ("Verify cl-deployment initial state and dependency waiting behavior" )
252+ // Capture cl-deployment's initial waiting state
253+ // Poll until cl-deployment appears in the statuses
254+ var foundInitialState bool
255+ Eventually (func (g Gomega ) {
256+ foundInitialState = false
257+ statuses , err := h .Client .GetClusterStatuses (ctx , clusterID )
258+ g .Expect (err ).NotTo (HaveOccurred (), "failed to get cluster statuses" )
259+
260+ // Find cl-deployment adapter
261+ for _ , adapter := range statuses .Items {
262+ if adapter .Adapter == "cl-deployment" {
263+ foundInitialState = true
264+
265+ // Verify initial waiting state
266+ hasAppliedFalse := h .HasAdapterCondition (
267+ adapter .Conditions ,
268+ client .ConditionTypeApplied ,
269+ openapi .AdapterConditionStatusFalse ,
270+ )
271+ g .Expect (hasAppliedFalse ).To (BeTrue (),
272+ "cl-deployment Applied condition should be False initially (waiting for cl-job)" )
273+
274+ hasAvailableUnknown := h .HasAdapterCondition (
275+ adapter .Conditions ,
276+ client .ConditionTypeAvailable ,
277+ openapi .AdapterConditionStatusUnknown ,
278+ )
279+ g .Expect (hasAvailableUnknown ).To (BeTrue (),
280+ "cl-deployment Available condition should be Unknown initially (waiting for cl-job)" )
281+
282+ hasHealthTrue := h .HasAdapterCondition (
283+ adapter .Conditions ,
284+ client .ConditionTypeHealth ,
285+ openapi .AdapterConditionStatusTrue ,
286+ )
287+ g .Expect (hasHealthTrue ).To (BeTrue (),
288+ "cl-deployment Health condition should be True (adapter is healthy, just waiting)" )
289+
290+ return
291+ }
292+ }
293+ g .Expect (foundInitialState ).To (BeTrue (), "cl-deployment adapter should appear in statuses" )
294+ }, h .Cfg .Timeouts .Adapter .Processing , pollingInterval ).Should (Succeed ())
295+
296+ ginkgo .By ("Verify dependency: cl-deployment Applied=False and Available=Unknown during cl-job execution" )
297+ // Poll continuously until cl-deployment Available becomes True:
298+ // - Before cl-job Available=True: verify cl-deployment Applied=False and Available!=False
299+ // - After cl-job Available=True: only wait for cl-deployment Available=True
300+ // - Exit when cl-deployment Available=True
301+ timeout := time .After (h .Cfg .Timeouts .Adapter .Processing )
302+ ticker := time .NewTicker (1 * time .Second )
303+ defer ticker .Stop ()
304+
305+ var jobAvailableReachedTrue bool
306+
307+ pollLoop:
308+ for {
309+ select {
310+ case <- timeout :
311+ ginkgo .Fail ("Timed out waiting for cl-deployment Available condition to become True" )
312+ case <- ticker .C :
242313 statuses , err := h .Client .GetClusterStatuses (ctx , clusterID )
243- g .Expect (err ).NotTo (HaveOccurred (), "failed to get cluster statuses" )
314+ Expect (err ).NotTo (HaveOccurred (), "failed to get cluster statuses" )
315+
316+ var jobAvailableTrue bool
317+ var deploymentAppliedTrue bool
318+ var deploymentAvailableTrue bool
319+ var deploymentAvailableFalse bool
244320
245- // Find cl-deployment adapter
246321 for _ , adapter := range statuses .Items {
322+ if adapter .Adapter == "cl-job" {
323+ jobAvailableTrue = h .HasAdapterCondition (
324+ adapter .Conditions ,
325+ client .ConditionTypeAvailable ,
326+ openapi .AdapterConditionStatusTrue ,
327+ )
328+ }
247329 if adapter .Adapter == "cl-deployment" {
248- foundInitialState = true
249-
250- // Verify initial waiting state
251- hasAppliedFalse := h .HasAdapterCondition (
330+ deploymentAppliedTrue = h .HasAdapterCondition (
252331 adapter .Conditions ,
253332 client .ConditionTypeApplied ,
254- openapi .AdapterConditionStatusFalse ,
333+ openapi .AdapterConditionStatusTrue ,
255334 )
256- g .Expect (hasAppliedFalse ).To (BeTrue (),
257- "cl-deployment Applied condition should be False initially (waiting for cl-job)" )
258-
259- hasAvailableUnknown := h .HasAdapterCondition (
335+ deploymentAvailableTrue = h .HasAdapterCondition (
260336 adapter .Conditions ,
261337 client .ConditionTypeAvailable ,
262- openapi .AdapterConditionStatusUnknown ,
338+ openapi .AdapterConditionStatusTrue ,
263339 )
264- g .Expect (hasAvailableUnknown ).To (BeTrue (),
265- "cl-deployment Available condition should be Unknown initially (waiting for cl-job)" )
266-
267- hasHealthTrue := h .HasAdapterCondition (
340+ deploymentAvailableFalse = h .HasAdapterCondition (
268341 adapter .Conditions ,
269- client .ConditionTypeHealth ,
270- openapi .AdapterConditionStatusTrue ,
342+ client .ConditionTypeAvailable ,
343+ openapi .AdapterConditionStatusFalse ,
271344 )
272- g .Expect (hasHealthTrue ).To (BeTrue (),
273- "cl-deployment Health condition should be True (adapter is healthy, just waiting)" )
274-
275- return
276345 }
277346 }
278- g .Expect (foundInitialState ).To (BeTrue (), "cl-deployment adapter should appear in statuses" )
279- }, h .Cfg .Timeouts .Adapter .Processing , pollingInterval ).Should (Succeed ())
280-
281- ginkgo .By ("Verify dependency: cl-deployment Applied=False and Available=Unknown during cl-job execution" )
282- // Poll continuously until cl-deployment Available becomes True:
283- // - Before cl-job Available=True: verify cl-deployment Applied=False and Available!=False
284- // - After cl-job Available=True: only wait for cl-deployment Available=True
285- // - Exit when cl-deployment Available=True
286- timeout := time .After (h .Cfg .Timeouts .Adapter .Processing )
287- ticker := time .NewTicker (1 * time .Second )
288- defer ticker .Stop ()
289-
290- var jobAvailableReachedTrue bool
291-
292- pollLoop:
293- for {
294- select {
295- case <- timeout :
296- ginkgo .Fail ("Timed out waiting for cl-deployment Available condition to become True" )
297- case <- ticker .C :
298- statuses , err := h .Client .GetClusterStatuses (ctx , clusterID )
299- Expect (err ).NotTo (HaveOccurred (), "failed to get cluster statuses" )
300-
301- var jobAvailableTrue bool
302- var deploymentAppliedTrue bool
303- var deploymentAvailableTrue bool
304- var deploymentAvailableFalse bool
305-
306- for _ , adapter := range statuses .Items {
307- if adapter .Adapter == "cl-job" {
308- jobAvailableTrue = h .HasAdapterCondition (
309- adapter .Conditions ,
310- client .ConditionTypeAvailable ,
311- openapi .AdapterConditionStatusTrue ,
312- )
313- }
314- if adapter .Adapter == "cl-deployment" {
315- deploymentAppliedTrue = h .HasAdapterCondition (
316- adapter .Conditions ,
317- client .ConditionTypeApplied ,
318- openapi .AdapterConditionStatusTrue ,
319- )
320- deploymentAvailableTrue = h .HasAdapterCondition (
321- adapter .Conditions ,
322- client .ConditionTypeAvailable ,
323- openapi .AdapterConditionStatusTrue ,
324- )
325- deploymentAvailableFalse = h .HasAdapterCondition (
326- adapter .Conditions ,
327- client .ConditionTypeAvailable ,
328- openapi .AdapterConditionStatusFalse ,
329- )
330- }
331- }
332347
333- // Track when cl-job Available first becomes True
334- if jobAvailableTrue && ! jobAvailableReachedTrue {
335- jobAvailableReachedTrue = true
336- ginkgo .GinkgoWriter .Printf ("cl-job Available=True reached, cl-deployment can now proceed\n " )
337- }
348+ // Track when cl-job Available first becomes True
349+ if jobAvailableTrue && ! jobAvailableReachedTrue {
350+ jobAvailableReachedTrue = true
351+ ginkgo .GinkgoWriter .Printf ("cl-job Available=True reached, cl-deployment can now proceed\n " )
352+ }
338353
339- // Validate dependency enforcement: only check while cl-job is still executing
340- if ! jobAvailableReachedTrue {
341- // cl-deployment should not start applying resources until cl-job completes
342- Expect (deploymentAppliedTrue ).To (BeFalse (),
343- "cl-deployment Applied should remain False while cl-job Available is not True yet" )
354+ // Validate dependency enforcement: only check while cl-job is still executing
355+ if ! jobAvailableReachedTrue {
356+ // cl-deployment should not start applying resources until cl-job completes
357+ Expect (deploymentAppliedTrue ).To (BeFalse (),
358+ "cl-deployment Applied should remain False while cl-job Available is not True yet" )
344359
345- // cl-deployment Available should stay Unknown (not False) while waiting for cl-job
346- Expect (deploymentAvailableFalse ).To (BeFalse (),
347- "cl-deployment Available must be Unknown (not False) during cl-job execution" )
348- }
360+ // cl-deployment Available should stay Unknown (not False) while waiting for cl-job
361+ Expect (deploymentAvailableFalse ).To (BeFalse (),
362+ "cl-deployment Available must be Unknown (not False) during cl-job execution" )
363+ }
349364
350- // Exit when cl-deployment Available becomes True (workflow complete)
351- if deploymentAvailableTrue {
352- ginkgo .GinkgoWriter .Printf ("cl-deployment Available=True reached, dependency validation successful\n " )
353- break pollLoop
354- }
365+ // Exit when cl-deployment Available becomes True (workflow complete)
366+ if deploymentAvailableTrue {
367+ ginkgo .GinkgoWriter .Printf ("cl-deployment Available=True reached, dependency validation successful\n " )
368+ break pollLoop
355369 }
356370 }
371+ }
357372
358- ginkgo .GinkgoWriter .Printf ("Successfully validated cl-deployment dependency on cl-job with correct condition transitions\n " )
359- })
360- })
373+ ginkgo .GinkgoWriter .Printf ("Successfully validated cl-deployment dependency on cl-job with correct condition transitions\n " )
374+ })
375+ })
361376
362377 ginkgo .AfterEach (func (ctx context.Context ) {
363378 // Skip cleanup if helper not initialized or no cluster created
0 commit comments