@@ -25,66 +25,70 @@ import (
25
25
26
26
appsv1 "k8s.io/api/apps/v1"
27
27
corev1 "k8s.io/api/core/v1"
28
+ "k8s.io/apimachinery/pkg/runtime"
29
+ "k8s.io/apimachinery/pkg/runtime/schema"
30
+ "k8s.io/apimachinery/pkg/types"
28
31
"sigs.k8s.io/controller-runtime/pkg/client"
29
32
"sigs.k8s.io/controller-runtime/pkg/log"
30
33
31
34
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative"
32
- "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
33
35
)
34
36
35
37
const successfulDeployment = appsv1 .DeploymentAvailable
36
38
37
39
// NewAggregator provides an implementation of declarative.Reconciled that
38
40
// aggregates the status of deployed objects to configure the 'Healthy'
39
41
// field on an addon that derives from CommonStatus
40
- func NewAggregator (client client.Client ) * aggregator {
41
- return & aggregator {client }
42
+ //
43
+ // TODO: Create a version that doesn't require the unused client arg
44
+ func NewAggregator (_ client.Client ) * aggregator {
45
+ return & aggregator {}
42
46
}
43
47
44
48
type aggregator struct {
45
- client client.Client
46
49
}
47
50
48
- func (a * aggregator ) Reconciled (ctx context.Context , src declarative.DeclarativeObject , objs * manifest. Objects , reconcileErr error ) error {
51
+ func (a * aggregator ) BuildStatus (ctx context.Context , info * declarative.StatusInfo ) error {
49
52
log := log .FromContext (ctx )
50
53
51
54
statusHealthy := true
52
55
statusErrors := []string {}
53
56
54
- if reconcileErr != nil {
57
+ shouldComputeHealthFromObjects := info .Manifest != nil && info .LiveObjects != nil
58
+ if info .Err != nil {
55
59
statusHealthy = false
60
+ shouldComputeHealthFromObjects = false
56
61
}
57
62
58
- for _ , o := range objs .GetItems () {
59
- gk := o .Group + "/" + o .Kind
60
- healthy := true
61
- objKey := client.ObjectKey {
62
- Name : o .GetName (),
63
- Namespace : o .GetNamespace (),
64
- }
65
- // If the namespace isn't set on the object, we would want to use the namespace of src
66
- if objKey .Namespace == "" {
67
- objKey .Namespace = src .GetNamespace ()
68
- }
69
- var err error
70
- switch gk {
71
- case "/Service" :
72
- healthy , err = a .service (ctx , objKey )
73
- case "extensions/Deployment" , "apps/Deployment" :
74
- healthy , err = a .deployment (ctx , objKey )
75
- default :
76
- log .WithValues ("type" , gk ).V (2 ).Info ("type not implemented for status aggregation, skipping" )
77
- }
78
-
79
- statusHealthy = statusHealthy && healthy
80
- if err != nil {
81
- statusErrors = append (statusErrors , fmt .Sprintf ("%v" , err ))
63
+ if shouldComputeHealthFromObjects {
64
+ for _ , o := range info .Manifest .GetItems () {
65
+ gvk := o .GroupVersionKind ()
66
+ nn := o .NamespacedName ()
67
+
68
+ log := log .WithValues ("kind" , gvk .Kind ).WithValues ("name" , nn .Name ).WithValues ("namespace" , nn .Namespace )
69
+
70
+ healthy := true
71
+
72
+ var err error
73
+ switch gvk .Group + "/" + gvk .Kind {
74
+ case "/Service" :
75
+ healthy , err = a .serviceIsHealthy (ctx , info .LiveObjects , gvk , nn )
76
+ case "extensions/Deployment" , "apps/Deployment" :
77
+ healthy , err = a .deploymentIsHealthy (ctx , info .LiveObjects , gvk , nn )
78
+ default :
79
+ log .V (4 ).Info ("type not implemented for status aggregation, skipping" )
80
+ }
81
+
82
+ statusHealthy = statusHealthy && healthy
83
+ if err != nil {
84
+ statusErrors = append (statusErrors , fmt .Sprintf ("%v" , err ))
85
+ }
82
86
}
83
87
}
84
88
85
- log .WithValues ("object" , src ). WithValues ( " status" , statusHealthy ).V (2 ).Info ("built status" )
89
+ log .WithValues ("status" , statusHealthy ).V (2 ).Info ("built status" )
86
90
87
- currentStatus , err := utils .GetCommonStatus (src )
91
+ currentStatus , err := utils .GetCommonStatus (info . Subject )
88
92
if err != nil {
89
93
return err
90
94
}
@@ -94,27 +98,24 @@ func (a *aggregator) Reconciled(ctx context.Context, src declarative.Declarative
94
98
status .Errors = statusErrors
95
99
96
100
if ! reflect .DeepEqual (status , currentStatus ) {
97
- err := utils .SetCommonStatus (src , status )
101
+ err := utils .SetCommonStatus (info . Subject , status )
98
102
if err != nil {
99
103
return err
100
104
}
101
-
102
- log .WithValues ("name" , src .GetName ()).WithValues ("status" , status ).Info ("updating status" )
103
- err = a .client .Status ().Update (ctx , src )
104
- if err != nil {
105
- log .Error (err , "updating status" )
106
- return err
107
- }
108
105
}
109
106
110
107
return nil
111
108
}
112
109
113
- func (a * aggregator ) deployment (ctx context.Context , key client.ObjectKey ) (bool , error ) {
114
- dep := & appsv1.Deployment {}
110
+ func (a * aggregator ) deploymentIsHealthy (ctx context.Context , liveObjects declarative.LiveObjectReader , gvk schema.GroupVersionKind , nn types.NamespacedName ) (bool , error ) {
111
+ u , err := liveObjects (ctx , gvk , nn )
112
+ if err != nil {
113
+ return false , fmt .Errorf ("error reading deployment: %w" , err )
114
+ }
115
115
116
- if err := a .client .Get (ctx , key , dep ); err != nil {
117
- return false , fmt .Errorf ("error reading deployment (%s): %v" , key , err )
116
+ dep := & appsv1.Deployment {}
117
+ if err := runtime .DefaultUnstructuredConverter .FromUnstructured (u .Object , dep ); err != nil {
118
+ return false , fmt .Errorf ("error converting deployment from unstructured: %w" , err )
118
119
}
119
120
120
121
for _ , cond := range dep .Status .Conditions {
@@ -123,14 +124,13 @@ func (a *aggregator) deployment(ctx context.Context, key client.ObjectKey) (bool
123
124
}
124
125
}
125
126
126
- return false , fmt .Errorf ("deployment (%s) does not meet condition: %s" , key , successfulDeployment )
127
+ return false , fmt .Errorf ("deployment does not meet condition: %s" , successfulDeployment )
127
128
}
128
129
129
- func (a * aggregator ) service (ctx context.Context , key client.ObjectKey ) (bool , error ) {
130
- svc := & corev1.Service {}
131
- err := a .client .Get (ctx , key , svc )
130
+ func (a * aggregator ) serviceIsHealthy (ctx context.Context , liveObjects declarative.LiveObjectReader , gvk schema.GroupVersionKind , nn types.NamespacedName ) (bool , error ) {
131
+ _ , err := liveObjects (ctx , gvk , nn )
132
132
if err != nil {
133
- return false , fmt .Errorf ("error reading service (%s) : %v" , key , err )
133
+ return false , fmt .Errorf ("error reading service: %w" , err )
134
134
}
135
135
136
136
return true , nil
0 commit comments