Skip to content

Commit 9f28abc

Browse files
committed
Improve error output of ValidateResourceVersionStable
Signed-off-by: Stefan Büringer [email protected]
1 parent 085480a commit 9f28abc

File tree

1 file changed

+68
-7
lines changed

1 file changed

+68
-7
lines changed

test/framework/resourceversion_helpers.go

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ package framework
1919
import (
2020
"context"
2121
"fmt"
22+
"strings"
2223
"time"
2324

25+
"github.com/google/go-cmp/cmp"
2426
. "github.com/onsi/gomega"
2527
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/util/sets"
2629
"sigs.k8s.io/controller-runtime/pkg/client"
30+
"sigs.k8s.io/yaml"
2731

2832
clusterctlcluster "sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster"
2933
)
@@ -33,13 +37,15 @@ func ValidateResourceVersionStable(ctx context.Context, proxy ClusterProxy, name
3337
// Wait until resource versions are stable for a bit.
3438
byf("Check Resource versions are stable")
3539
var previousResourceVersions map[string]string
40+
var previousObjects map[string]client.Object
3641
Eventually(func(g Gomega) {
37-
objectsWithResourceVersion, err := getObjectsWithResourceVersion(ctx, proxy, namespace, ownerGraphFilterFunction)
42+
objectsWithResourceVersion, objects, err := getObjectsWithResourceVersion(ctx, proxy, namespace, ownerGraphFilterFunction)
3843
g.Expect(err).ToNot(HaveOccurred())
3944

4045
defer func() {
4146
// Set current resource versions as previous resource versions for the next try.
4247
previousResourceVersions = objectsWithResourceVersion
48+
previousObjects = objects
4349
}()
4450
// This is intentionally failing on the first run.
4551
g.Expect(objectsWithResourceVersion).To(BeComparableTo(previousResourceVersions))
@@ -48,19 +54,73 @@ func ValidateResourceVersionStable(ctx context.Context, proxy ClusterProxy, name
4854
// Verify resource versions are stable for a while.
4955
byf("Check Resource versions remain stable")
5056
Consistently(func(g Gomega) {
51-
objectsWithResourceVersion, err := getObjectsWithResourceVersion(ctx, proxy, namespace, ownerGraphFilterFunction)
57+
objectsWithResourceVersion, objects, err := getObjectsWithResourceVersion(ctx, proxy, namespace, ownerGraphFilterFunction)
5258
g.Expect(err).ToNot(HaveOccurred())
53-
g.Expect(objectsWithResourceVersion).To(BeComparableTo(previousResourceVersions))
59+
g.Expect(objectsWithResourceVersion).To(BeComparableTo(previousResourceVersions), printObjectDiff(previousObjects, objects))
5460
}, 2*time.Minute, 15*time.Second).Should(Succeed(), "Resource versions didn't stay stable")
5561
}
5662

57-
func getObjectsWithResourceVersion(ctx context.Context, proxy ClusterProxy, namespace string, ownerGraphFilterFunction clusterctlcluster.GetOwnerGraphFilterFunction) (map[string]string, error) {
63+
func printObjectDiff(previousObjects, newObjects map[string]client.Object) func() string {
64+
return func() string {
65+
createdObjects := objectIDs(newObjects).Difference(objectIDs(previousObjects))
66+
deletedObjects := objectIDs(previousObjects).Difference(objectIDs(newObjects))
67+
preservedObjects := objectIDs(previousObjects).Intersection(objectIDs(newObjects))
68+
69+
var output strings.Builder
70+
71+
if len(createdObjects) > 0 {
72+
output.WriteString("\nDetected new objects\n")
73+
for objID := range createdObjects {
74+
obj := newObjects[objID]
75+
resourceYAML, _ := yaml.Marshal(obj)
76+
output.WriteString(fmt.Sprintf("\nNew object %s:\n%s\n", objID, resourceYAML))
77+
}
78+
}
79+
if len(deletedObjects) > 0 {
80+
output.WriteString("\nDetected deleted objects\n")
81+
for objID := range deletedObjects {
82+
obj := previousObjects[objID]
83+
resourceYAML, _ := yaml.Marshal(obj)
84+
output.WriteString(fmt.Sprintf("\nDeleted object %s:\n%s\n", objID, resourceYAML))
85+
}
86+
}
87+
88+
if len(preservedObjects) > 0 {
89+
output.WriteString("\nDetected objects with changed resourceVersion\n")
90+
for objID := range preservedObjects {
91+
previousObj := previousObjects[objID]
92+
newObj := newObjects[objID]
93+
94+
if previousObj.GetResourceVersion() == newObj.GetResourceVersion() {
95+
continue
96+
}
97+
98+
previousResourceYAML, _ := yaml.Marshal(previousObj)
99+
newResourceYAML, _ := yaml.Marshal(newObj)
100+
output.WriteString(fmt.Sprintf("\nObject with changed resourceVersion %s:\n%s\n", objID, cmp.Diff(string(previousResourceYAML), string(newResourceYAML))))
101+
}
102+
}
103+
104+
return output.String()
105+
}
106+
}
107+
108+
func objectIDs(objs map[string]client.Object) sets.Set[string] {
109+
ret := sets.Set[string]{}
110+
for id := range objs {
111+
ret.Insert(id)
112+
}
113+
return ret
114+
}
115+
116+
func getObjectsWithResourceVersion(ctx context.Context, proxy ClusterProxy, namespace string, ownerGraphFilterFunction clusterctlcluster.GetOwnerGraphFilterFunction) (map[string]string, map[string]client.Object, error) {
58117
graph, err := clusterctlcluster.GetOwnerGraph(ctx, namespace, proxy.GetKubeconfigPath(), ownerGraphFilterFunction)
59118
if err != nil {
60-
return nil, err
119+
return nil, nil, err
61120
}
62121

63122
objectsWithResourceVersion := map[string]string{}
123+
objects := map[string]client.Object{}
64124
for _, node := range graph {
65125
nodeNamespacedName := client.ObjectKey{Namespace: node.Object.Namespace, Name: node.Object.Name}
66126
obj := &metav1.PartialObjectMetadata{
@@ -70,9 +130,10 @@ func getObjectsWithResourceVersion(ctx context.Context, proxy ClusterProxy, name
70130
},
71131
}
72132
if err := proxy.GetClient().Get(ctx, nodeNamespacedName, obj); err != nil {
73-
return nil, err
133+
return nil, nil, err
74134
}
75135
objectsWithResourceVersion[fmt.Sprintf("%s/%s/%s", node.Object.Kind, node.Object.Namespace, node.Object.Name)] = obj.ResourceVersion
136+
objects[fmt.Sprintf("%s/%s/%s", node.Object.Kind, node.Object.Namespace, node.Object.Name)] = obj
76137
}
77-
return objectsWithResourceVersion, nil
138+
return objectsWithResourceVersion, objects, nil
78139
}

0 commit comments

Comments
 (0)