@@ -18,6 +18,7 @@ package machinedeployment
18
18
19
19
import (
20
20
"context"
21
+ "fmt"
21
22
"reflect"
22
23
23
24
"github.com/golang/glog"
@@ -26,7 +27,8 @@ import (
26
27
"k8s.io/apimachinery/pkg/labels"
27
28
"k8s.io/apimachinery/pkg/runtime"
28
29
"k8s.io/apimachinery/pkg/types"
29
- clusterv1alpha1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
30
+ "sigs.k8s.io/cluster-api/pkg/apis/cluster/common"
31
+ "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
30
32
"sigs.k8s.io/controller-runtime/pkg/client"
31
33
"sigs.k8s.io/controller-runtime/pkg/controller"
32
34
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -36,35 +38,50 @@ import (
36
38
)
37
39
38
40
// controllerKind contains the schema.GroupVersionKind for this controller type.
39
- var controllerKind = clusterv1alpha1 .SchemeGroupVersion .WithKind ("MachineDeployment" )
41
+ var controllerKind = v1alpha1 .SchemeGroupVersion .WithKind ("MachineDeployment" )
40
42
41
- // Add creates a new MachineDeployment Controller and adds it to the Manager with default RBAC.
42
- func Add (mgr manager.Manager ) error {
43
- return add (mgr , newReconciler (mgr ))
43
+ // ReconcileMachineDeployment reconciles a MachineDeployment object
44
+ type ReconcileMachineDeployment struct {
45
+ client.Client
46
+ scheme * runtime.Scheme
44
47
}
45
48
46
49
// newReconciler returns a new reconcile.Reconciler
47
- func newReconciler (mgr manager.Manager ) reconcile. Reconciler {
50
+ func newReconciler (mgr manager.Manager ) * ReconcileMachineDeployment {
48
51
return & ReconcileMachineDeployment {Client : mgr .GetClient (), scheme : mgr .GetScheme ()}
49
52
}
50
53
54
+ // Add creates a new MachineDeployment Controller and adds it to the Manager with default RBAC.
55
+ func Add (mgr manager.Manager ) error {
56
+ r := newReconciler (mgr )
57
+ return add (mgr , newReconciler (mgr ), r .MachineSetToDeployments )
58
+ }
59
+
51
60
// add adds a new Controller to mgr with r as the reconcile.Reconciler
52
- func add (mgr manager.Manager , r reconcile.Reconciler ) error {
61
+ func add (mgr manager.Manager , r reconcile.Reconciler , mapFn handler. ToRequestsFunc ) error {
53
62
// Create a new controller
54
63
c , err := controller .New ("machinedeployment-controller" , mgr , controller.Options {Reconciler : r })
55
64
if err != nil {
56
65
return err
57
66
}
58
67
59
68
// Watch for changes to MachineDeployment
60
- err = c .Watch (& source.Kind {Type : & clusterv1alpha1 .MachineDeployment {}}, & handler.EnqueueRequestForObject {})
69
+ err = c .Watch (& source.Kind {Type : & v1alpha1 .MachineDeployment {}}, & handler.EnqueueRequestForObject {})
61
70
if err != nil {
62
71
return err
63
72
}
64
73
65
74
// Watch for changes to MachineSet and reconcile the owner MachineDeployment
66
- err = c .Watch (& source.Kind {Type : & clusterv1alpha1.MachineSet {}},
67
- & handler.EnqueueRequestForOwner {OwnerType : & clusterv1alpha1.MachineDeployment {}, IsController : true })
75
+ err = c .Watch (& source.Kind {Type : & v1alpha1.MachineSet {}},
76
+ & handler.EnqueueRequestForOwner {OwnerType : & v1alpha1.MachineDeployment {}, IsController : true })
77
+ if err != nil {
78
+ return err
79
+ }
80
+
81
+ // Map MachineSet changes to MachineDeployment
82
+ err = c .Watch (
83
+ & source.Kind {Type : & v1alpha1.MachineSet {}},
84
+ & handler.EnqueueRequestsFromMapFunc {ToRequests : mapFn })
68
85
if err != nil {
69
86
return err
70
87
}
@@ -74,18 +91,49 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
74
91
75
92
var _ reconcile.Reconciler = & ReconcileMachineDeployment {}
76
93
77
- // ReconcileMachineDeployment reconciles a MachineDeployment object
78
- type ReconcileMachineDeployment struct {
79
- client.Client
80
- scheme * runtime.Scheme
94
+ func (r * ReconcileMachineDeployment ) getMachineSetsForDeployment (d * v1alpha1.MachineDeployment ) ([]* v1alpha1.MachineSet , error ) {
95
+ // List all MachineSets to find those we own but that no longer match our
96
+ // selector.
97
+ machineSets := & v1alpha1.MachineSetList {}
98
+ err := r .List (context .Background (), client .InNamespace (d .Namespace ), machineSets )
99
+ if err != nil {
100
+ return nil , err
101
+ }
102
+
103
+ // TODO: flush out machine set adoption.
104
+
105
+ var filteredMS []* v1alpha1.MachineSet
106
+ for idx , _ := range machineSets .Items {
107
+ ms := & machineSets .Items [idx ]
108
+ if metav1 .GetControllerOf (ms ) == nil || (metav1 .GetControllerOf (ms ) != nil && ! metav1 .IsControlledBy (ms , d )) {
109
+ glog .V (4 ).Infof ("%s not controlled by %v" , ms .Name , d .Name )
110
+ continue
111
+ }
112
+ selector , err := metav1 .LabelSelectorAsSelector (& d .Spec .Selector )
113
+ if err != nil {
114
+ glog .Errorf ("Skipping machineset %v, failed to get label selector from spec selector." , ms .Name )
115
+ continue
116
+ }
117
+ // If a deployment with a nil or empty selector creeps in, it should match nothing, not everything.
118
+ if selector .Empty () {
119
+ glog .Warningf ("Skipping machineset %v as the selector is empty." , ms .Name )
120
+ continue
121
+ }
122
+ if ! selector .Matches (labels .Set (ms .Labels )) {
123
+ glog .V (4 ).Infof ("Skipping machineset %v, label mismatch." , ms .Name )
124
+ continue
125
+ }
126
+ filteredMS = append (filteredMS , ms )
127
+ }
128
+ return filteredMS , nil
81
129
}
82
130
83
131
// Reconcile reads that state of the cluster for a MachineDeployment object and makes changes based on the state read
84
132
// and what is in the MachineDeployment.Spec
85
133
// +kubebuilder:rbac:groups=cluster.k8s.io,resources=machinedeployments,verbs=get;list;watch;create;update;patch;delete
86
134
func (r * ReconcileMachineDeployment ) Reconcile (request reconcile.Request ) (reconcile.Result , error ) {
87
135
// Fetch the MachineDeployment instance
88
- d := & clusterv1alpha1 .MachineDeployment {}
136
+ d := & v1alpha1 .MachineDeployment {}
89
137
err := r .Get (context .TODO (), request .NamespacedName , d )
90
138
if err != nil {
91
139
if errors .IsNotFound (err ) {
@@ -96,6 +144,7 @@ func (r *ReconcileMachineDeployment) Reconcile(request reconcile.Request) (recon
96
144
// Error reading the object - requeue the request.
97
145
return reconcile.Result {}, err
98
146
}
147
+
99
148
everything := metav1.LabelSelector {}
100
149
if reflect .DeepEqual (d .Spec .Selector , & everything ) {
101
150
if d .Status .ObservedGeneration < d .Generation {
@@ -126,55 +175,50 @@ func (r *ReconcileMachineDeployment) Reconcile(request reconcile.Request) (recon
126
175
return reconcile.Result {}, r .sync (d , msList , machineMap )
127
176
}
128
177
129
- return reconcile.Result {}, nil
178
+ switch d .Spec .Strategy .Type {
179
+ case common .RollingUpdateMachineDeploymentStrategyType :
180
+ return reconcile.Result {}, r .rolloutRolling (d , msList , machineMap )
181
+ }
182
+
183
+ return reconcile.Result {}, fmt .Errorf ("unexpected deployment strategy type: %s" , d .Spec .Strategy .Type )
130
184
}
131
185
132
- func (r * ReconcileMachineDeployment ) getMachineSetsForDeployment (d * clusterv1alpha1.MachineDeployment ) ([]* clusterv1alpha1.MachineSet , error ) {
133
- // List all MachineSets to find those we own but that no longer match our
134
- // selector.
135
- machineSets := & clusterv1alpha1.MachineSetList {}
136
- err := r .List (context .Background (),
137
- // TODO(droot): check if we need to specify labels for fetching
138
- // everything ?
139
- // client.InNamespace(d.Namespace).MatchingLabels(labels.Everything()),
140
- client .InNamespace (d .Namespace ), machineSets )
141
- if err != nil {
142
- return nil , err
186
+ // getMachineDeploymentsForMachineSet returns a list of Deployments that potentially
187
+ // match a MachineSet.
188
+ func (r * ReconcileMachineDeployment ) getMachineDeploymentsForMachineSet (ms * v1alpha1.MachineSet ) []* v1alpha1.MachineDeployment {
189
+ if len (ms .Labels ) == 0 {
190
+ glog .Warningf ("no machine deployments found for MachineSet %v because it has no labels" , ms .Name )
191
+ return nil
143
192
}
144
193
145
- // TODO: flush out machine set adoption.
194
+ dList := & v1alpha1.MachineDeploymentList {}
195
+ err := r .Client .List (context .Background (), client .InNamespace (ms .Namespace ), dList )
196
+ if err != nil {
197
+ glog .Warningf ("failed to list machine deployments, %v" , err )
198
+ return nil
199
+ }
146
200
147
- var filteredMS []* clusterv1alpha1.MachineSet
148
- for idx := range machineSets .Items {
149
- ms := & machineSets .Items [idx ]
150
- if metav1 .GetControllerOf (ms ) == nil || (metav1 .GetControllerOf (ms ) != nil && ! metav1 .IsControlledBy (ms , d )) {
151
- glog .V (4 ).Infof ("%s not controlled by %v" , ms .Name , d .Name )
152
- continue
153
- }
201
+ var deployments []* v1alpha1.MachineDeployment
202
+ for idx , d := range dList .Items {
154
203
selector , err := metav1 .LabelSelectorAsSelector (& d .Spec .Selector )
155
204
if err != nil {
156
- glog .Errorf ("Skipping machineset %v, failed to get label selector from spec selector." , ms .Name )
157
205
continue
158
206
}
159
207
// If a deployment with a nil or empty selector creeps in, it should match nothing, not everything.
160
- if selector .Empty () {
161
- glog .Warningf ("Skipping machineset %v as the selector is empty." , ms .Name )
162
- continue
163
- }
164
- if ! selector .Matches (labels .Set (ms .Labels )) {
165
- glog .V (4 ).Infof ("Skipping machineset %v, label mismatch." , ms .Name )
208
+ if selector .Empty () || ! selector .Matches (labels .Set (ms .Labels )) {
166
209
continue
167
210
}
168
- filteredMS = append (filteredMS , ms )
211
+ deployments = append (deployments , & dList . Items [ idx ] )
169
212
}
170
- return filteredMS , nil
213
+
214
+ return deployments
171
215
}
172
216
173
217
// getMachineMapForDeployment returns the Machines managed by a Deployment.
174
218
//
175
219
// It returns a map from MachineSet UID to a list of Machines controlled by that MS,
176
220
// according to the Machine's ControllerRef.
177
- func (r * ReconcileMachineDeployment ) getMachineMapForDeployment (d * clusterv1alpha1 .MachineDeployment , msList []* clusterv1alpha1 .MachineSet ) (map [types.UID ]* clusterv1alpha1 .MachineList , error ) {
221
+ func (r * ReconcileMachineDeployment ) getMachineMapForDeployment (d * v1alpha1 .MachineDeployment , msList []* v1alpha1 .MachineSet ) (map [types.UID ]* v1alpha1 .MachineList , error ) {
178
222
// TODO(droot): double check if previous selector maps correctly to new one.
179
223
// _, err := metav1.LabelSelectorAsSelector(&d.Spec.Selector)
180
224
@@ -183,15 +227,15 @@ func (r *ReconcileMachineDeployment) getMachineMapForDeployment(d *clusterv1alph
183
227
if err != nil {
184
228
return nil , err
185
229
}
186
- machines := & clusterv1alpha1 .MachineList {}
230
+ machines := & v1alpha1 .MachineList {}
187
231
err = r .List (context .Background (), client .InNamespace (d .Namespace ).MatchingLabels (selector ), machines )
188
232
if err != nil {
189
233
return nil , err
190
234
}
191
235
// Group Machines by their controller (if it's in msList).
192
- machineMap := make (map [types.UID ]* clusterv1alpha1 .MachineList , len (msList ))
236
+ machineMap := make (map [types.UID ]* v1alpha1 .MachineList , len (msList ))
193
237
for _ , ms := range msList {
194
- machineMap [ms .UID ] = & clusterv1alpha1 .MachineList {}
238
+ machineMap [ms .UID ] = & v1alpha1 .MachineList {}
195
239
}
196
240
for idx := range machines .Items {
197
241
machine := & machines .Items [idx ]
@@ -208,3 +252,33 @@ func (r *ReconcileMachineDeployment) getMachineMapForDeployment(d *clusterv1alph
208
252
}
209
253
return machineMap , nil
210
254
}
255
+
256
+ func (r * ReconcileMachineDeployment ) MachineSetToDeployments (o handler.MapObject ) []reconcile.Request {
257
+ result := []reconcile.Request {}
258
+ ms := & v1alpha1.MachineSet {}
259
+ key := client.ObjectKey {Namespace : o .Meta .GetNamespace (), Name : o .Meta .GetNamespace ()}
260
+ err := r .Client .Get (context .Background (), key , ms )
261
+ if err != nil {
262
+ glog .Errorf ("Unable to retrieve Machineset %v from store: %v" , key , err )
263
+ return nil
264
+ }
265
+
266
+ for _ , ref := range ms .ObjectMeta .OwnerReferences {
267
+ if ref .Controller != nil && * ref .Controller {
268
+ return result
269
+ }
270
+ }
271
+
272
+ mds := r .getMachineDeploymentsForMachineSet (ms )
273
+ if len (mds ) == 0 {
274
+ glog .V (4 ).Infof ("Found no machine set for machine: %v" , ms .Name )
275
+ return nil
276
+ }
277
+
278
+ for _ , md := range mds {
279
+ result = append (result , reconcile.Request {
280
+ NamespacedName : client.ObjectKey {Namespace : md .Namespace , Name : md .Name }})
281
+ }
282
+
283
+ return result
284
+ }
0 commit comments