Skip to content

Commit 7c8ef2f

Browse files
feat: unified RecordStatuses and RecordErrorConditions (#56)
* feat: unified RecordStatuses and RecordErrorConditions * remove useless test println
1 parent 684598b commit 7c8ef2f

File tree

6 files changed

+49
-43
lines changed

6 files changed

+49
-43
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
customized controller can be realized easily, and offering the ability of following
44
[**PodOpsLifecycle**](https://kusionstack.io/docs/operating/concepts/podopslifecycle) for controllers.
55

6-
The only thing users need to do to realize a customized controller is writing an adapter implementing
7-
[ReconcileAdapter](https://github.com/KusionStack/resourceconsist/blob/main/pkg/frame/controller/types.go#L93).
6+
The only thing users need to do to realize a customized controller is writing an adapter implementing
7+
[ReconcileAdapter](https://github.com/KusionStack/resourceconsist/blob/main/pkg/frame/controller/types.go#L100).
88
For controllers following **PodOpsLifecycle**,
99
[WebhookAdapter](https://github.com/KusionStack/resourceconsist/blob/main/pkg/frame/webhook/types.go#L26) is
1010
also necessary to be implemented.
@@ -30,7 +30,7 @@ is an adapter handles resources by itself, while [SlbControllerAdapter](https://
3030
is an adapter handles resources cooperate with CCM controller.
3131

3232
With **ResourceConsist**, you can build a bridge between existing controllers and PodOpsLifecycle, just like what
33-
SlbControllerAdapter](https://github.com/KusionStack/resourceconsist/tree/main/pkg/adapters/alibabacloudslb/alibabacloudslb_controller.go#L35) did.
33+
[SlbControllerAdapter](https://github.com/KusionStack/resourceconsist/tree/main/pkg/adapters/alibabacloudslb/alibabacloudslb_controller.go#L35) did.
3434

3535
Please visit [tutorial](https://github.com/KusionStack/resourceconsist/tree/main/docs/tutorial.md) to start a controller.
3636
## ☎️ Contact us

docs/keyconcepts.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ type ExpectedFinalizerRecordOptions interface {
8585

8686
// StatusRecordOptions defines methods of record something for adapters
8787
type StatusRecordOptions interface {
88+
// RecordStatuses records statuses of employer and employees, called at the end of reconcile.
89+
// cudEmployerResults and cudEmployeeResults are the results of create/update/delete operations on employer and employees
90+
// err indicates if reconcile failed, if err is not nil, error condition will be recorded, otherwise status will be recorded
8891
RecordStatuses(ctx context.Context, employer client.Object,
89-
cudEmployerResults CUDEmployerResults, cudEmployeeResults CUDEmployeeResults) error
92+
cudEmployerResults CUDEmployerResults, cudEmployeeResults CUDEmployeeResults, err error) error
9093
}
9194

9295
// ReconcileLifecycleOptions defines whether PodOpsLifecycle followed

docs/tutorial.md

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
The frame, ```kusionstack.io/resourceconsist/pkg/frame```, is used for adapters starting a controller, which handles
55
Reconcile and Employer/Employees' spec&status. If you wrote an adapter in your own repo, you can import
6-
```kusionstack.io/resourceconsist/pkg/frame/controller``` and ```kusionstack.io/resourceconsist/pkg/frame/webhook```,
7-
]and call AddToMgr to start a controller.
6+
```kusionstack.io/resourceconsist/pkg/frame/controller``` and ```kusionstack.io/resourceconsist/pkg/frame/webhook```,
7+
and call AddToMgr to start a controller.
88

99
>webhookAdapter is only necessary to be implemented for controllers following PodOpsLifecycle.
1010
```Go
@@ -93,7 +93,7 @@ type DemoControllerAdapter struct {
9393
}
9494
```
9595
Declaring that the DemoControllerAdapter implemented ```ReconcileAdapter``` and ```ReconcileLifecycleOptions```.
96-
Implementing ```RconcileAdapter``` is a must action, while ```ReconcileLifecycleOptions``` isn't, check the remarks
96+
Implementing ```ReconcileAdapter``` is a must action, while ```ReconcileLifecycleOptions``` isn't, check the remarks
9797
for ```ReconcileLifecycleOptions``` in ```kusionstack.io/resourceconsist/pkg/frame/controller/types.go``` to find why.
9898
```Go
9999
var _ ReconcileAdapter = &DemoControllerAdapter{}
@@ -116,13 +116,15 @@ employee.
116116
type IEmployer interface {
117117
GetEmployerId() string
118118
GetEmployerStatuses() interface{}
119+
SetEmployerStatuses(employerStatuses interface{})
119120
EmployerEqual(employer IEmployer) (bool, error)
120121
}
121122

122123
type IEmployee interface {
123124
GetEmployeeId() string
124125
GetEmployeeName() string
125126
GetEmployeeStatuses() interface{}
127+
SetEmployeeStatuses(employeeStatuses interface{})
126128
EmployeeEqual(employee IEmployee) (bool, error)
127129
}
128130

@@ -208,13 +210,13 @@ related backend provider. Here in the demo adapter, ```CreateEmployer/UpdateEmpl
208210
```demoResourceVipStatusInProvider```.
209211
```Go
210212
func (r *DemoControllerAdapter) CreateEmployer(ctx context.Context, employer client.Object, toCreates []IEmployer) ([]IEmployer, []IEmployer, error) {
211-
if toCreates == nil || len(toCreates) == 0 {
213+
if len(toCreates) == 0 {
212214
return toCreates, nil, nil
213215
}
214216

215-
toCreateDemoServiceStatus := make([]DemoServiceStatus, len(toCreates))
217+
toCreateDemoServiceStatus := make([]*DemoServiceStatus, len(toCreates))
216218
for idx, create := range toCreates {
217-
createDemoServiceStatus, ok := create.(DemoServiceStatus)
219+
createDemoServiceStatus, ok := create.(*DemoServiceStatus)
218220
if !ok {
219221
return nil, toCreates, fmt.Errorf("toCreates employer is not DemoServiceStatus")
220222
}
@@ -231,13 +233,13 @@ func (r *DemoControllerAdapter) CreateEmployer(ctx context.Context, employer cli
231233
}
232234

233235
func (r *DemoControllerAdapter) UpdateEmployer(ctx context.Context, employer client.Object, toUpdates []IEmployer) ([]IEmployer, []IEmployer, error) {
234-
if toUpdates == nil || len(toUpdates) == 0 {
236+
if len(toUpdates) == 0 {
235237
return toUpdates, nil, nil
236238
}
237239

238-
toUpdateDemoServiceStatus := make([]DemoServiceStatus, len(toUpdates))
240+
toUpdateDemoServiceStatus := make([]*DemoServiceStatus, len(toUpdates))
239241
for idx, update := range toUpdates {
240-
updateDemoServiceStatus, ok := update.(DemoServiceStatus)
242+
updateDemoServiceStatus, ok := update.(*DemoServiceStatus)
241243
if !ok {
242244
return nil, toUpdates, fmt.Errorf("toUpdates employer is not DemoServiceStatus")
243245
}
@@ -254,13 +256,13 @@ func (r *DemoControllerAdapter) UpdateEmployer(ctx context.Context, employer cli
254256
}
255257

256258
func (r *DemoControllerAdapter) DeleteEmployer(ctx context.Context, employer client.Object, toDeletes []IEmployer) ([]IEmployer, []IEmployer, error) {
257-
if toDeletes == nil || len(toDeletes) == 0 {
259+
if len(toDeletes) == 0 {
258260
return toDeletes, nil, nil
259261
}
260262

261-
toDeleteDemoServiceStatus := make([]DemoServiceStatus, len(toDeletes))
263+
toDeleteDemoServiceStatus := make([]*DemoServiceStatus, len(toDeletes))
262264
for idx, update := range toDeletes {
263-
deleteDemoServiceStatus, ok := update.(DemoServiceStatus)
265+
deleteDemoServiceStatus, ok := update.(*DemoServiceStatus)
264266
if !ok {
265267
return nil, toDeletes, fmt.Errorf("toDeletes employer is not DemoServiceStatus")
266268
}
@@ -351,13 +353,13 @@ on related backend provider. Here in the demo adapter, ```CreateEmployees/Update
351353
handles ```demoResourceRsStatusInProvider```.
352354
```Go
353355
func (r *DemoControllerAdapter) CreateEmployees(ctx context.Context, employer client.Object, toCreates []IEmployee) ([]IEmployee, []IEmployee, error) {
354-
if toCreates == nil || len(toCreates) == 0 {
356+
if len(toCreates) == 0 {
355357
return toCreates, nil, nil
356358
}
357-
toCreateDemoPodStatuses := make([]DemoPodStatus, len(toCreates))
359+
toCreateDemoPodStatuses := make([]*DemoPodStatus, len(toCreates))
358360

359361
for idx, toCreate := range toCreates {
360-
podStatus, ok := toCreate.(DemoPodStatus)
362+
podStatus, ok := toCreate.(*DemoPodStatus)
361363
if !ok {
362364
return nil, toCreates, fmt.Errorf("toCreate is not DemoPodStatus")
363365
}
@@ -375,14 +377,14 @@ func (r *DemoControllerAdapter) CreateEmployees(ctx context.Context, employer cl
375377
}
376378

377379
func (r *DemoControllerAdapter) UpdateEmployees(ctx context.Context, employer client.Object, toUpdates []IEmployee) ([]IEmployee, []IEmployee, error) {
378-
if toUpdates == nil || len(toUpdates) == 0 {
380+
if len(toUpdates) == 0 {
379381
return toUpdates, nil, nil
380382
}
381383

382-
toUpdateDemoPodStatuses := make([]DemoPodStatus, len(toUpdates))
384+
toUpdateDemoPodStatuses := make([]*DemoPodStatus, len(toUpdates))
383385

384386
for idx, toUpdate := range toUpdates {
385-
podStatus, ok := toUpdate.(DemoPodStatus)
387+
podStatus, ok := toUpdate.(*DemoPodStatus)
386388
if !ok {
387389
return nil, toUpdates, fmt.Errorf("toUpdate is not DemoPodStatus")
388390
}
@@ -400,14 +402,14 @@ func (r *DemoControllerAdapter) UpdateEmployees(ctx context.Context, employer cl
400402
}
401403

402404
func (r *DemoControllerAdapter) DeleteEmployees(ctx context.Context, employer client.Object, toDeletes []IEmployee) ([]IEmployee, []IEmployee, error) {
403-
if toDeletes == nil || len(toDeletes) == 0 {
405+
if len(toDeletes) == 0 {
404406
return toDeletes, nil, nil
405407
}
406408

407-
toDeleteDemoPodStatuses := make([]DemoPodStatus, len(toDeletes))
409+
toDeleteDemoPodStatuses := make([]*DemoPodStatus, len(toDeletes))
408410

409411
for idx, toDelete := range toDeletes {
410-
podStatus, ok := toDelete.(DemoPodStatus)
412+
podStatus, ok := toDelete.(*DemoPodStatus)
411413
if !ok {
412414
return nil, toDeletes, fmt.Errorf("toDelete is not DemoPodStatus")
413415
}

pkg/frame/controller/resourceconsist_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func (r *Consist) Reconcile(ctx context.Context, request reconcile.Request) (rec
162162
defer func() {
163163
if err != nil {
164164
if recordOptions, ok := r.adapter.(StatusRecordOptions); ok {
165-
err = recordOptions.RecordErrorConditions(ctx, employer, err)
165+
err = recordOptions.RecordStatuses(ctx, employer, CUDEmployerResults{}, CUDEmployeeResults{}, err)
166166
if err != nil {
167167
logger.Error(err, "record error conditions failed")
168168
r.recorder.Eventf(employer, corev1.EventTypeWarning, RecordErrorConditionsFailed,
@@ -255,7 +255,7 @@ func (r *Consist) Reconcile(ctx context.Context, request reconcile.Request) (rec
255255
}
256256

257257
if recordOptions, ok := r.adapter.(StatusRecordOptions); ok {
258-
err = recordOptions.RecordStatuses(ctx, employer, cudEmployerResults, cudEmployeeResults)
258+
err = recordOptions.RecordStatuses(ctx, employer, cudEmployerResults, cudEmployeeResults, err)
259259
if err != nil {
260260
logger.Error(err, "record status failed")
261261
r.recorder.Eventf(employer, corev1.EventTypeWarning, RecordStatusesFailed,

pkg/frame/controller/resourceconsist_controller_suite_test.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,24 @@ func NewDemoReconcileAdapter(c client.Client, rc *DemoResourceProviderClient) Re
4747
}
4848

4949
func (r *DemoControllerAdapter) RecordStatuses(ctx context.Context, employer client.Object,
50-
cudEmployerResults CUDEmployerResults, cudEmployeeResults CUDEmployeeResults) error {
51-
if employer.GetAnnotations()["resource-consist.kusionstack.io/demo-condition"] != "" {
52-
employer.GetAnnotations()["resource-consist.kusionstack.io/demo-condition"] = ""
53-
return r.Update(ctx, employer)
54-
}
55-
return nil
56-
}
57-
58-
func (r *DemoControllerAdapter) RecordErrorConditions(ctx context.Context, employer client.Object, err error) error {
50+
cudEmployerResults CUDEmployerResults, cudEmployeeResults CUDEmployeeResults, err error) error {
5951
annos := employer.GetAnnotations()
6052
if annos == nil {
6153
annos = make(map[string]string)
6254
}
63-
annos["resource-consist.kusionstack.io/demo-condition"] = err.Error()
55+
56+
if err != nil {
57+
// Record error condition
58+
annos["resource-consist.kusionstack.io/demo-condition"] = err.Error()
59+
} else {
60+
// Clear error condition if present
61+
if annos["resource-consist.kusionstack.io/demo-condition"] != "" {
62+
annos["resource-consist.kusionstack.io/demo-condition"] = ""
63+
} else {
64+
return nil
65+
}
66+
}
67+
6468
employer.SetAnnotations(annos)
6569
return r.Update(ctx, employer)
6670
}

pkg/frame/controller/types.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,11 @@ type ExpectedFinalizerRecordOptions interface {
6868

6969
// StatusRecordOptions defines methods of record something for adapters
7070
type StatusRecordOptions interface {
71-
// RecordStatuses records statuses of employer and employees, called at the end of successful reconcile.
71+
// RecordStatuses records statuses of employer and employees, called at the end of reconcile.
7272
// cudEmployerResults and cudEmployeeResults are the results of create/update/delete operations on employer and employees
73+
// err indicates if reconcile failed, if err is not nil, error condition will be recorded, otherwise status will be recorded
7374
RecordStatuses(ctx context.Context, employer client.Object,
74-
cudEmployerResults CUDEmployerResults, cudEmployeeResults CUDEmployeeResults) error
75-
76-
// RecordErrorConditions records error conditions, called at the end of failed reconcile.
77-
// usually, something recorded in RecordErrorConditions should be erased in RecordStatuses.
78-
RecordErrorConditions(ctx context.Context, employer client.Object, err error) error
75+
cudEmployerResults CUDEmployerResults, cudEmployeeResults CUDEmployeeResults, err error) error
7976
}
8077

8178
// ReconcileLifecycleOptions defines whether PodOpsLifecycle followed

0 commit comments

Comments
 (0)