@@ -2,13 +2,15 @@ package controller
2
2
3
3
import (
4
4
"context"
5
+ "strings"
5
6
6
7
"github.com/go-logr/logr"
7
8
logr2 "github.com/jortel/go-utils/logr"
8
- api "github.com/konveyor/tackle2-hub/k8s/api/tackle/v1alpha2 "
9
+ api "github.com/konveyor/tackle2-hub/k8s/api/tackle/v1alpha1 "
9
10
"github.com/konveyor/tackle2-hub/settings"
10
11
"gorm.io/gorm"
11
12
k8serr "k8s.io/apimachinery/pkg/api/errors"
13
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
14
"k8s.io/apiserver/pkg/storage/names"
13
15
"k8s.io/client-go/tools/record"
14
16
k8s "sigs.k8s.io/controller-runtime/pkg/client"
@@ -32,9 +34,10 @@ var Settings = &settings.Settings
32
34
// Add the controller.
33
35
func Add (mgr manager.Manager , db * gorm.DB ) error {
34
36
reconciler := & Reconciler {
35
- Client : mgr .GetClient (),
36
- Log : log ,
37
- DB : db ,
37
+ history : make (map [string ]byte ),
38
+ Client : mgr .GetClient (),
39
+ Log : log ,
40
+ DB : db ,
38
41
}
39
42
cnt , err := controller .New (
40
43
Name ,
@@ -59,15 +62,18 @@ func Add(mgr manager.Manager, db *gorm.DB) error {
59
62
}
60
63
61
64
// Reconciler reconciles addon CRs.
65
+ // The history is used to ensure resources are reconciled
66
+ // at least once at startup.
62
67
type Reconciler struct {
63
68
record.EventRecorder
64
69
k8s.Client
65
- DB * gorm.DB
66
- Log logr.Logger
70
+ DB * gorm.DB
71
+ Log logr.Logger
72
+ history map [string ]byte
67
73
}
68
74
69
75
// Reconcile a Addon CR.
70
- // Note: Must not a pointer receiver to ensure that the
76
+ // Note: Must not be a pointer receiver to ensure that the
71
77
// logger and other state is not shared.
72
78
func (r Reconciler ) Reconcile (ctx context.Context , request reconcile.Request ) (result reconcile.Result , err error ) {
73
79
r .Log = logr2 .WithName (
@@ -86,18 +92,23 @@ func (r Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (r
86
92
}
87
93
return
88
94
}
89
- // migrate
90
- migrated , err := r .alpha2Migration (addon )
91
- if migrated || err != nil {
95
+ _ , found := r .history [addon .Name ]
96
+ if found && addon .Reconciled () {
92
97
return
93
98
}
94
- // changed.
95
- err = r .addonChanged (addon )
96
- if err != nil {
99
+ r .history [addon .Name ] = 1
100
+ addon .Status .Conditions = nil
101
+ addon .Status .ObservedGeneration = addon .Generation
102
+ // Changed
103
+ migrated , err := r .addonChanged (addon )
104
+ if migrated || err != nil {
97
105
return
98
106
}
107
+ // Ready condition.
108
+ addon .Status .Conditions = append (
109
+ addon .Status .Conditions ,
110
+ r .ready (addon ))
99
111
// Apply changes.
100
- addon .Status .ObservedGeneration = addon .Generation
101
112
err = r .Status ().Update (context .TODO (), addon )
102
113
if err != nil {
103
114
return
@@ -106,47 +117,50 @@ func (r Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (r
106
117
return
107
118
}
108
119
109
- // addonChanged an addon has been created/updated.
110
- func (r * Reconciler ) addonChanged (addon * api.Addon ) (err error ) {
111
- return
112
- }
113
-
114
- // addonDeleted an addon has been deleted.
115
- func (r * Reconciler ) addonDeleted (name string ) (err error ) {
116
- return
117
- }
118
-
119
- // alpha2Migration migrates to alpha2.
120
- func (r * Reconciler ) alpha2Migration (addon * api.Addon ) (migrated bool , err error ) {
121
- if addon .Spec .Image != nil {
122
- if addon .Spec .Container .Image == "" {
123
- addon .Spec .Container .Image = * addon .Spec .Image
120
+ // ready returns the ready condition.
121
+ func (r * Reconciler ) ready (addon * api.Addon ) (ready v1.Condition ) {
122
+ ready = api .Ready
123
+ ready .LastTransitionTime = v1 .Now ()
124
+ ready .ObservedGeneration = addon .Status .ObservedGeneration
125
+ err := make ([]string , 0 )
126
+ for i := range addon .Status .Conditions {
127
+ cnd := & addon .Status .Conditions [i ]
128
+ if cnd .Type == api .ValidationError {
129
+ err = append (err , cnd .Message )
124
130
}
125
- addon .Spec .Image = nil
126
- migrated = true
127
131
}
128
- if addon .Spec .Resources != nil {
129
- if len (addon .Spec .Container .Resources .Limits ) == 0 {
130
- addon .Spec .Container .Resources .Limits = (* addon .Spec .Resources ).Limits
131
- }
132
- if len (addon .Spec .Container .Resources .Requests ) == 0 {
133
- addon .Spec .Container .Resources .Requests = (* addon .Spec .Resources ).Requests
134
- }
135
- addon .Spec .Resources = nil
136
- migrated = true
137
- }
138
- if addon .Spec .ImagePullPolicy != nil {
139
- if addon .Spec .Container .ImagePullPolicy == "" {
140
- addon .Spec .Container .ImagePullPolicy = * addon .Spec .ImagePullPolicy
141
- }
142
- addon .Spec .ImagePullPolicy = nil
143
- migrated = true
132
+ if len (err ) == 0 {
133
+ ready .Status = v1 .ConditionTrue
134
+ ready .Reason = api .Validated
135
+ ready .Message = strings .Join (err , ";" )
136
+ } else {
137
+ ready .Status = v1 .ConditionFalse
138
+ ready .Reason = api .ValidationError
144
139
}
140
+ return
141
+ }
142
+
143
+ // addonChanged an addon has been created/updated.
144
+ func (r * Reconciler ) addonChanged (addon * api.Addon ) (migrated bool , err error ) {
145
+ migrated = addon .Migrate ()
145
146
if migrated {
146
147
err = r .Update (context .TODO (), addon )
147
148
if err != nil {
148
149
return
149
150
}
150
151
}
152
+ if addon .Spec .Container .Image == "" {
153
+ cnd := api .ImageNotDefined
154
+ cnd .LastTransitionTime = v1 .Now ()
155
+ cnd .ObservedGeneration = addon .Status .ObservedGeneration
156
+ addon .Status .Conditions = append (
157
+ addon .Status .Conditions ,
158
+ cnd )
159
+ }
160
+ return
161
+ }
162
+
163
+ // addonDeleted an addon has been deleted.
164
+ func (r * Reconciler ) addonDeleted (name string ) (err error ) {
151
165
return
152
166
}
0 commit comments