Skip to content

Commit 7e5e34e

Browse files
authored
fallback to ready condition observed generation (#312)
* fallback to ready condition observed generation * fix build tool management
1 parent d87d3c6 commit 7e5e34e

File tree

2 files changed

+178
-99
lines changed

2 files changed

+178
-99
lines changed

pkg/status/analyzer.go

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
batchv1 "k8s.io/api/batch/v1"
1616
corev1 "k8s.io/api/core/v1"
1717
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
18+
"k8s.io/apimachinery/pkg/runtime"
1819
"k8s.io/apimachinery/pkg/runtime/schema"
1920
kstatus "sigs.k8s.io/cli-utils/pkg/kstatus/status"
2021

@@ -43,6 +44,30 @@ func NewStatusAnalyzer(reconcilerName string) StatusAnalyzer {
4344

4445
// Implement the StatusAnalyzer interface.
4546
func (s *statusAnalyzer) ComputeStatus(object *unstructured.Unstructured) (Status, error) {
47+
type ObjectCondition struct {
48+
Type string `json:"type"`
49+
Status corev1.ConditionStatus `json:"status"`
50+
ObservedGeneration *int64 `json:"observedGeneration"`
51+
}
52+
type ObjectStatus struct {
53+
ObservedGeneration *int64 `json:"observedGeneration"`
54+
Conditions []ObjectCondition
55+
}
56+
type Object struct {
57+
Status ObjectStatus `json:"status"`
58+
}
59+
60+
obj := &Object{}
61+
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.Object, obj); err != nil {
62+
return UnknownStatus, err
63+
}
64+
var readyCondition *ObjectCondition
65+
for i, condition := range obj.Status.Conditions {
66+
if condition.Type == conditionTypeReady {
67+
readyCondition = &obj.Status.Conditions[i]
68+
}
69+
}
70+
4671
var extraConditions []string
4772

4873
// parse hints from annotations
@@ -60,50 +85,39 @@ func (s *statusAnalyzer) ComputeStatus(object *unstructured.Unstructured) (Statu
6085
}
6186
switch strcase.ToKebab(key) {
6287
case types.StatusHintHasObservedGeneration:
63-
// add an impossible status.observedGeneration if there is none, but the hint says there will be one
6488
if hasValue {
6589
return UnknownStatus, fmt.Errorf("status hint %s does not take a value", types.StatusHintHasObservedGeneration)
6690
}
67-
_, found, err := unstructured.NestedInt64(object.Object, "status", "observedGeneration")
68-
if err != nil {
69-
return UnknownStatus, err
70-
}
71-
if !found {
72-
if err := unstructured.SetNestedField(object.Object, int64(-1), "status", "observedGeneration"); err != nil {
73-
return UnknownStatus, err
91+
if obj.Status.ObservedGeneration == nil {
92+
if readyCondition != nil && readyCondition.ObservedGeneration != nil {
93+
// add the ready condition's observed generation (if present) as observed generation if there is none, but the hint says there will be one
94+
if err := unstructured.SetNestedField(object.Object, *readyCondition.ObservedGeneration, "status", "observedGeneration"); err != nil {
95+
return UnknownStatus, err
96+
}
97+
} else {
98+
// otherwise add an impossible observed generation if there is none, but the hint says there will be one
99+
if err := unstructured.SetNestedField(object.Object, int64(-1), "status", "observedGeneration"); err != nil {
100+
return UnknownStatus, err
101+
}
74102
}
75103
}
76104
case types.StatusHintHasReadyCondition:
77-
// add an Unknown Ready condition if there is none, but the hint says there will be one
78105
if hasValue {
79106
return UnknownStatus, fmt.Errorf("status hint %s does not take a value", types.StatusHintHasReadyCondition)
80107
}
81-
foundReadyCondition := false
82-
conditions, found, err := unstructured.NestedSlice(object.Object, "status", "conditions")
83-
if err != nil {
84-
return UnknownStatus, err
85-
}
86-
if !found {
87-
conditions = make([]any, 0)
88-
}
89-
for _, condition := range conditions {
90-
if condition, ok := condition.(map[string]any); ok {
91-
condType, found, err := unstructured.NestedString(condition, "type")
92-
if err != nil {
93-
return UnknownStatus, err
94-
}
95-
if found && condType == conditionTypeReady {
96-
foundReadyCondition = true
97-
break
98-
}
108+
if readyCondition == nil {
109+
// add a ready condition with status 'Unknown' if there is none, but the hint says there will be one
110+
conditions, _, err := unstructured.NestedSlice(object.Object, "status", "conditions")
111+
if err != nil {
112+
// TODO: this error should never occur because it was verified above that status.conditions has the right type
113+
return UnknownStatus, err
99114
}
100-
}
101-
if !foundReadyCondition {
102115
conditions = append(conditions, map[string]any{
103116
"type": conditionTypeReady,
104117
"status": string(corev1.ConditionUnknown),
105118
})
106119
if err := unstructured.SetNestedSlice(object.Object, conditions, "status", "conditions"); err != nil {
120+
// TODO: this error should never occur because it was verified above that status.conditions can be digged
107121
return UnknownStatus, err
108122
}
109123
}
@@ -135,13 +149,9 @@ func (s *statusAnalyzer) ComputeStatus(object *unstructured.Unstructured) (Statu
135149

136150
// check extra conditions
137151
if status == CurrentStatus && len(extraConditions) > 0 {
138-
objc, err := kstatus.GetObjectWithConditions(object.UnstructuredContent())
139-
if err != nil {
140-
return UnknownStatus, err
141-
}
142152
for _, condition := range extraConditions {
143153
found := false
144-
for _, cond := range objc.Status.Conditions {
154+
for _, cond := range obj.Status.Conditions {
145155
if cond.Type == condition {
146156
found = true
147157
if cond.Status != corev1.ConditionTrue {
@@ -161,11 +171,7 @@ func (s *statusAnalyzer) ComputeStatus(object *unstructured.Unstructured) (Statu
161171
// other than kstatus we want to consider jobs as InProgress if its pods are still running, resp. did not (yet) finish successfully
162172
if status == CurrentStatus {
163173
done := false
164-
objc, err := kstatus.GetObjectWithConditions(object.UnstructuredContent())
165-
if err != nil {
166-
return UnknownStatus, err
167-
}
168-
for _, cond := range objc.Status.Conditions {
174+
for _, cond := range obj.Status.Conditions {
169175
if cond.Type == string(batchv1.JobComplete) && cond.Status == corev1.ConditionTrue {
170176
done = true
171177
break

0 commit comments

Comments
 (0)