Skip to content

Commit 7da7ea0

Browse files
restore topologicalOrder in status
1 parent aca0bde commit 7da7ea0

File tree

10 files changed

+52
-11
lines changed

10 files changed

+52
-11
lines changed

pkg/controller/resourcegraphdefinition/controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ func (r *ResourceGraphDefinitionReconciler) Reconcile(
169169
return ctrl.Result{}, err
170170
}
171171

172-
resourcesInformation, reconcileErr := r.reconcileResourceGraphDefinition(ctx, o)
172+
topologicalOrder, resourcesInformation, reconcileErr := r.reconcileResourceGraphDefinition(ctx, o)
173173

174-
if err := r.updateStatus(ctx, o, resourcesInformation); err != nil {
174+
if err := r.updateStatus(ctx, o, topologicalOrder, resourcesInformation); err != nil {
175175
reconcileErr = errors.Join(reconcileErr, err)
176176
}
177177

pkg/controller/resourcegraphdefinition/controller_reconcile.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import (
3838
func (r *ResourceGraphDefinitionReconciler) reconcileResourceGraphDefinition(
3939
ctx context.Context,
4040
rgd *v1alpha1.ResourceGraphDefinition,
41-
) ([]v1alpha1.ResourceInformation, error) {
41+
) ([]string, []v1alpha1.ResourceInformation, error) {
4242
log := ctrl.LoggerFrom(ctx)
4343
mark := NewConditionsMarkerFor(rgd)
4444

@@ -47,15 +47,15 @@ func (r *ResourceGraphDefinitionReconciler) reconcileResourceGraphDefinition(
4747
processedRGD, resourcesInfo, err := r.reconcileResourceGraphDefinitionGraph(ctx, rgd)
4848
if err != nil {
4949
mark.ResourceGraphInvalid(err.Error())
50-
return nil, err
50+
return nil, nil, err
5151
}
5252
mark.ResourceGraphValid()
5353

5454
// Setup metadata labeling
5555
graphExecLabeler, err := r.setupLabeler(rgd)
5656
if err != nil {
5757
mark.FailedLabelerSetup(err.Error())
58-
return nil, fmt.Errorf("failed to setup labeler: %w", err)
58+
return nil, nil, fmt.Errorf("failed to setup labeler: %w", err)
5959
}
6060

6161
crd := processedRGD.Instance.GetCRD()
@@ -65,7 +65,7 @@ func (r *ResourceGraphDefinitionReconciler) reconcileResourceGraphDefinition(
6565
log.V(1).Info("reconciling resource graph definition CRD")
6666
if err := r.reconcileResourceGraphDefinitionCRD(ctx, crd); err != nil {
6767
mark.KindUnready(err.Error())
68-
return resourcesInfo, err
68+
return processedRGD.TopologicalOrder, resourcesInfo, err
6969
}
7070
if crd, err = r.crdManager.Get(ctx, crd.Name); err != nil {
7171
mark.KindUnready(err.Error())
@@ -78,11 +78,11 @@ func (r *ResourceGraphDefinitionReconciler) reconcileResourceGraphDefinition(
7878
// rather than have it ignore this context and use the background context.
7979
if err := r.reconcileResourceGraphDefinitionMicroController(ctx, processedRGD, graphExecLabeler); err != nil {
8080
mark.ControllerFailedToStart(err.Error())
81-
return resourcesInfo, err
81+
return processedRGD.TopologicalOrder, resourcesInfo, err
8282
}
8383
mark.ControllerRunning()
8484

85-
return resourcesInfo, nil
85+
return processedRGD.TopologicalOrder, resourcesInfo, nil
8686
}
8787

8888
func (r *ResourceGraphDefinitionReconciler) getResourceGVRsToWatchForRGD(processedRGD *graph.Graph) []schema.GroupVersionResource {

pkg/controller/resourcegraphdefinition/controller_status.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
func (r *ResourceGraphDefinitionReconciler) updateStatus(
3535
ctx context.Context,
3636
o *v1alpha1.ResourceGraphDefinition,
37+
topologicalOrder []string,
3738
resources []v1alpha1.ResourceInformation,
3839
) error {
3940
log, _ := logr.FromContext(ctx)
@@ -58,6 +59,7 @@ func (r *ResourceGraphDefinitionReconciler) updateStatus(
5859
dc.Status.Conditions = o.Status.Conditions
5960
dc.Status.State = o.Status.State
6061
dc.Status.Resources = resources
62+
dc.Status.TopologicalOrder = topologicalOrder
6163

6264
log.V(1).Info("updating resource graph definition status",
6365
"state", dc.Status.State,

pkg/graph/builder.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,20 @@ func (b *Builder) NewResourceGraphDefinition(originalCR *v1alpha1.ResourceGraphD
224224
return nil, fmt.Errorf("failed to build dependency graph: %w", err)
225225
}
226226

227+
// Compute the topological levels of the graph and ensure it is acyclic.
228+
levels, err := dag.TopologicalSortLevels()
229+
if err != nil {
230+
return nil, fmt.Errorf("failed to compute topological levels: %w", err)
231+
}
232+
233+
// Flatten the levels into a single topological order slice.
234+
// Within each level, sort resources stably to maintain deterministic ordering.
235+
var topologicalOrder []string
236+
for _, level := range levels {
237+
slices.Sort(level)
238+
topologicalOrder = append(topologicalOrder, level...)
239+
}
240+
227241
// Now that we know all resources are properly declared and dependencies are valid,
228242
// we can perform type checking on the CEL expressions.
229243

@@ -250,9 +264,10 @@ func (b *Builder) NewResourceGraphDefinition(originalCR *v1alpha1.ResourceGraphD
250264
}
251265

252266
resourceGraphDefinition := &Graph{
253-
DAG: dag,
254-
Instance: instance,
255-
Resources: resources,
267+
DAG: dag,
268+
TopologicalOrder: topologicalOrder,
269+
Instance: instance,
270+
Resources: resources,
256271
}
257272
return resourceGraphDefinition, nil
258273
}

pkg/graph/graph.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ type Graph struct {
3131
Instance *Resource
3232
// Resources is a map of the processed resources in the resource graph definition.
3333
Resources map[string]*Resource
34+
// TopologicalOrder is the topological order of the resources in the resource graph definition.
35+
TopologicalOrder []string
3436
}
3537

3638
// NewGraphRuntime creates a new runtime resource graph definition from the resource graph definition instance.

test/integration/suites/core/dependency_readiness_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ var _ = Describe("Dependency Readiness", func() {
154154

155155
// Verify ResourceGraphDefinition is created and becomes ready
156156
createdRGD := &krov1alpha1.ResourceGraphDefinition{}
157+
158+
//nolint:dupl
157159
Eventually(func(g Gomega, ctx SpecContext) {
158160
err := env.Client.Get(ctx, types.NamespacedName{
159161
Name: rgd.Name,

test/integration/suites/core/include_when_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ var _ = Describe("Conditions", func() {
211211

212212
// Verify ResourceGraphDefinition is created and becomes ready
213213
createdRGD := &krov1alpha1.ResourceGraphDefinition{}
214+
215+
//nolint:dupl
214216
Eventually(func(g Gomega, ctx SpecContext) {
215217
err := env.Client.Get(ctx, types.NamespacedName{
216218
Name: rgd.Name,

test/integration/suites/core/readiness_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ var _ = Describe("Readiness", func() {
141141

142142
// Verify ResourceGraphDefinition is created and becomes ready
143143
createdRGD := &krov1alpha1.ResourceGraphDefinition{}
144+
145+
//nolint:dupl
144146
Eventually(func(g Gomega, ctx SpecContext) {
145147
err := env.Client.Get(ctx, types.NamespacedName{
146148
Name: rgd.Name,

test/integration/suites/core/unknown_fields_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
// Copyright 2025 The Kube Resource Orchestrator Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
115
package core_test
216

317
import (

test/integration/suites/core/validation_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ var _ = Describe("Validation", func() {
167167
})
168168

169169
Context("Kubernetes Object Structure", func() {
170+
//nolint:dupl
170171
It("should validate correct kubernetes object structure", func(ctx SpecContext) {
171172
rgd := generator.NewResourceGraphDefinition("test-k8s-valid",
172173
generator.WithSchema(
@@ -318,6 +319,7 @@ var _ = Describe("Validation", func() {
318319
})
319320

320321
Context("Proper Cleanup", func() {
322+
//nolint:dupl
321323
It("should not panic when deleting an inactive ResourceGraphDefinition", func(ctx SpecContext) {
322324
rgd := generator.NewResourceGraphDefinition("test-cleanup",
323325
generator.WithSchema(

0 commit comments

Comments
 (0)