11package framework
22
33import (
4+ "context"
45 "fmt"
6+ "time"
57
68 . "github.com/onsi/ginkgo/v2"
79 . "github.com/onsi/gomega"
810 corev1 "k8s.io/api/core/v1"
911 apierrors "k8s.io/apimachinery/pkg/api/errors"
1012 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+ "k8s.io/apimachinery/pkg/runtime/schema"
14+ "k8s.io/apimachinery/pkg/util/wait"
15+ "k8s.io/client-go/discovery"
16+ "k8s.io/client-go/dynamic"
17+ "k8s.io/client-go/rest"
18+ "k8s.io/client-go/scale"
19+ "k8s.io/klog"
1120 "k8s.io/utils/pointer"
1221 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
1322 "sigs.k8s.io/controller-runtime/pkg/client"
23+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
24+ "sigs.k8s.io/controller-runtime/pkg/client/config"
1425)
1526
1627type machineSetParams struct {
@@ -171,7 +182,9 @@ func GetMachineSet(cl client.Client, name string) (*clusterv1.MachineSet, error)
171182 machineSet := & clusterv1.MachineSet {}
172183 key := client.ObjectKey {Namespace : CAPINamespace , Name : name }
173184
174- Expect (cl .Get (ctx , key , machineSet )).To (Succeed ())
185+ if err := cl .Get (ctx , key , machineSet ); err != nil {
186+ return nil , fmt .Errorf ("error querying api for machineSet object: %w" , err )
187+ }
175188
176189 return machineSet , nil
177190}
@@ -190,3 +203,106 @@ func GetMachinesFromMachineSet(cl client.Client, machineSet *clusterv1.MachineSe
190203 }
191204 return machinesForSet , nil
192205}
206+
207+ // GetLatestMachineFromMachineSet returns the new created machine by a given machineSet.
208+ func GetLatestMachineFromMachineSet (cl client.Client , machineSet * clusterv1.MachineSet ) (* clusterv1.Machine , error ) {
209+ machines , err := GetMachinesFromMachineSet (cl , machineSet )
210+ if err != nil {
211+ return nil , fmt .Errorf ("error getting machines: %w" , err )
212+ }
213+
214+ var machine * clusterv1.Machine
215+
216+ newest := time .Date (2020 , 0 , 1 , 12 , 0 , 0 , 0 , time .UTC )
217+
218+ for key := range machines {
219+ time := machines [key ].CreationTimestamp .Time
220+ if time .After (newest ) {
221+ newest = time
222+ machine = machines [key ]
223+ }
224+ }
225+
226+ return machine , nil
227+ }
228+
229+ // DeleteMachines deletes the specified machines and returns an error on failure.
230+ func DeleteMachines (cl client.Client , machines ... * clusterv1.Machine ) error {
231+ return wait .PollUntilContextTimeout (ctx , RetryShort , time .Minute , true , func (ctx context.Context ) (bool , error ) {
232+ for _ , machine := range machines {
233+ if err := cl .Delete (ctx , machine ); err != nil {
234+ klog .Errorf ("Error querying api for machine object %q: %v, retrying..." , machine .Name , err )
235+ return false , err
236+ }
237+ }
238+
239+ return true , nil
240+ })
241+ }
242+
243+ // WaitForMachinesDeleted polls until the given Machines are not found.
244+ func WaitForMachinesDeleted (cl client.Client , machines ... * clusterv1.Machine ) {
245+ Eventually (func () bool {
246+ for _ , m := range machines {
247+ if err := cl .Get (context .Background (), client.ObjectKey {
248+ Name : m .GetName (),
249+ Namespace : m .GetNamespace (),
250+ }, & clusterv1.Machine {}); ! apierrors .IsNotFound (err ) {
251+ return false // Not deleted, or other error.
252+ }
253+ }
254+
255+ return true // Everything was deleted.
256+ }, WaitLong , RetryMedium ).Should (BeTrue (), "error encountered while waiting for Machines to be deleted." )
257+ }
258+
259+ // ScaleMachineSet scales a machineSet with a given name to the given number of replicas.
260+ func ScaleMachineSet (name string , replicas int ) error {
261+ scaleClient , err := getScaleClient ()
262+ if err != nil {
263+ return fmt .Errorf ("error calling getScaleClient %w" , err )
264+ }
265+
266+ scale , err := scaleClient .Scales (CAPINamespace ).Get (ctx , schema.GroupResource {Group : "cluster.x-k8s.io" , Resource : "MachineSet" }, name , metav1.GetOptions {})
267+ if err != nil {
268+ return fmt .Errorf ("error calling scaleClient.Scales get: %w" , err )
269+ }
270+
271+ scaleUpdate := scale .DeepCopy ()
272+ scaleUpdate .Spec .Replicas = int32 (replicas )
273+
274+ _ , err = scaleClient .Scales (CAPINamespace ).Update (ctx , schema.GroupResource {Group : "cluster.x-k8s.io" , Resource : "MachineSet" }, scaleUpdate , metav1.UpdateOptions {})
275+ if err != nil {
276+ return fmt .Errorf ("error calling scaleClient.Scales update: %w" , err )
277+ }
278+
279+ return nil
280+ }
281+
282+ // getScaleClient returns a ScalesGetter object to manipulate scale subresources.
283+ func getScaleClient () (scale.ScalesGetter , error ) {
284+ cfg , err := config .GetConfig ()
285+ if err != nil {
286+ return nil , fmt .Errorf ("error getting config %w" , err )
287+ }
288+
289+ httpClient , err := rest .HTTPClientFor (cfg )
290+ if err != nil {
291+ return nil , fmt .Errorf ("error calling rest.HTTPClientFor %w" , err )
292+ }
293+
294+ mapper , err := apiutil .NewDynamicRESTMapper (cfg , httpClient )
295+ if err != nil {
296+ return nil , fmt .Errorf ("error calling NewDiscoveryRESTMapper %w" , err )
297+ }
298+
299+ discovery := discovery .NewDiscoveryClientForConfigOrDie (cfg )
300+ scaleKindResolver := scale .NewDiscoveryScaleKindResolver (discovery )
301+
302+ scaleClient , err := scale .NewForConfig (cfg , mapper , dynamic .LegacyAPIPathResolverFunc , scaleKindResolver )
303+ if err != nil {
304+ return nil , fmt .Errorf ("error calling building scale client %w" , err )
305+ }
306+
307+ return scaleClient , nil
308+ }
0 commit comments