Skip to content

Commit 3ede182

Browse files
committed
Fix e2e test for dockermachinePool
Signed-off-by: serngawy <[email protected]>
1 parent 1089feb commit 3ede182

File tree

3 files changed

+59
-51
lines changed

3 files changed

+59
-51
lines changed

test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"fmt"
2323
"sort"
24+
"time"
2425

2526
"github.com/pkg/errors"
2627
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -136,8 +137,12 @@ func (r *DockerMachinePoolReconciler) Reconcile(ctx context.Context, req ctrl.Re
136137
}()
137138

138139
// Handle deleted machines
139-
if !dockerMachinePool.ObjectMeta.DeletionTimestamp.IsZero() {
140-
return ctrl.Result{}, r.reconcileDelete(ctx, cluster, machinePool, dockerMachinePool)
140+
if !dockerMachinePool.DeletionTimestamp.IsZero() {
141+
// perform dockerMachinePool delete and requeue in 30s giving time for containers to be deleted.
142+
if err = r.reconcileDelete(ctx, cluster, machinePool, dockerMachinePool); err != nil {
143+
return ctrl.Result{}, err
144+
}
145+
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
141146
}
142147

143148
// Add finalizer and the InfrastructureMachineKind if they aren't already present, and requeue if either were added.

test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller_phases.go

+49-46
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ import (
4646
// reconcileDockerContainers manages the Docker containers for a MachinePool such that it
4747
// - Ensures the number of up-to-date Docker containers is equal to the MachinePool's desired replica count.
4848
// - Does not delete any containers as that must be triggered in reconcileDockerMachines to ensure node cordon/drain.
49+
// - Create the DockerMachine CR after creating the container.
4950
//
5051
// Providers should similarly create their infrastructure instances and reconcile any additional logic.
5152
func (r *DockerMachinePoolReconciler) reconcileDockerContainers(ctx context.Context, cluster *clusterv1.Cluster, machinePool *expv1.MachinePool, dockerMachinePool *infraexpv1.DockerMachinePool) error {
5253
log := ctrl.LoggerFrom(ctx)
53-
54-
log.V(2).Info("Reconciling Docker containers", "DockerMachinePool", klog.KObj(dockerMachinePool))
54+
log.Info("Reconciling Docker containers", "DockerMachinePool", klog.KObj(dockerMachinePool))
5555

5656
labelFilters := map[string]string{dockerMachinePoolLabel: dockerMachinePool.Name}
5757

@@ -63,8 +63,15 @@ func (r *DockerMachinePoolReconciler) reconcileDockerContainers(ctx context.Cont
6363
matchingMachineCount := len(machinesMatchingInfrastructureSpec(ctx, machines, machinePool, dockerMachinePool))
6464
numToCreate := int(*machinePool.Spec.Replicas) - matchingMachineCount
6565
for range numToCreate {
66-
log.V(2).Info("Creating a new Docker container for machinePool", "MachinePool", klog.KObj(machinePool))
6766
name := fmt.Sprintf("worker-%s", util.RandomString(6))
67+
68+
log.Info("Creating a new DockerMachine for dockerMachinePool", "DockerMachinePool", klog.KObj(dockerMachinePool))
69+
dockerMachine := computeDesiredDockerMachine(name, cluster, machinePool, dockerMachinePool, nil)
70+
if err := ssa.Patch(ctx, r.Client, dockerMachinePoolControllerName, dockerMachine); err != nil {
71+
return errors.Wrap(err, "failed to create a new docker machine")
72+
}
73+
74+
log.Info("Creating a new Docker container for machinePool", "MachinePool", klog.KObj(machinePool))
6875
if err := createDockerContainer(ctx, name, cluster, machinePool, dockerMachinePool); err != nil {
6976
return errors.Wrap(err, "failed to create a new docker machine")
7077
}
@@ -107,15 +114,15 @@ func createDockerContainer(ctx context.Context, name string, cluster *clusterv1.
107114

108115
// reconcileDockerMachines creates and deletes DockerMachines to match the MachinePool's desired number of replicas and infrastructure spec.
109116
// It is responsible for
110-
// - Ensuring each Docker container has an associated DockerMachine by creating one if it doesn't already exist.
111-
// - Ensuring that deletion for Docker container happens by calling delete on the associated Machine so that the node is cordoned/drained and the infrastructure is cleaned up.
117+
// - Update DockerMachine owner references
118+
// - Create Docker containers for its corresponding DockerMachine if not exist.
112119
// - Deleting DockerMachines referencing a container whose Kubernetes version or custom image no longer matches the spec.
113120
// - Deleting DockerMachines that correspond to a deleted/non-existent Docker container.
114121
// - Deleting DockerMachines when scaling down such that DockerMachines whose owner Machine has the clusterv1.DeleteMachineAnnotation is given priority.
115122
func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Context, cluster *clusterv1.Cluster, machinePool *expv1.MachinePool, dockerMachinePool *infraexpv1.DockerMachinePool) error {
116123
log := ctrl.LoggerFrom(ctx)
117124

118-
log.V(2).Info("Reconciling DockerMachines", "DockerMachinePool", klog.KObj(dockerMachinePool))
125+
log.Info("Reconciling DockerMachines", "DockerMachinePool", klog.KObj(dockerMachinePool))
119126

120127
dockerMachineList, err := getDockerMachines(ctx, r.Client, *cluster, *machinePool, *dockerMachinePool)
121128
if err != nil {
@@ -127,58 +134,37 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
127134
dockerMachineMap[dockerMachine.Name] = dockerMachine
128135
}
129136

130-
// List the Docker containers. This corresponds to a InfraMachinePool instance for providers.
137+
// Get the Docker containers. This corresponds to a InfraMachinePool instance for providers.
131138
labelFilters := map[string]string{dockerMachinePoolLabel: dockerMachinePool.Name}
132-
externalMachines, err := docker.ListMachinesByCluster(ctx, cluster, labelFilters)
139+
externalMachineMap, err := getExternalMachinesMap(ctx, cluster, labelFilters)
133140
if err != nil {
134141
return errors.Wrapf(err, "failed to list all machines in the cluster")
135142
}
136143

137-
externalMachineMap := make(map[string]*docker.Machine)
138-
for _, externalMachine := range externalMachines {
139-
externalMachineMap[externalMachine.Name()] = externalMachine
140-
}
141-
142144
// Step 1:
143-
// Create a DockerMachine for each Docker container so we surface the information to the user. Use the same name as the Docker container for the Docker Machine for ease of lookup.
144-
// Providers should iterate through their infrastructure instances and ensure that each instance has a corresponding InfraMachine.
145-
for _, machine := range externalMachines {
146-
if existingMachine, ok := dockerMachineMap[machine.Name()]; ok {
147-
log.V(2).Info("Patching existing DockerMachine", "DockerMachine", klog.KObj(&existingMachine))
145+
// Update the DockerMachine to set its owner reference
146+
// Create Dockercontainer for DockerMachine if not exist.
147+
for _, existingMachine := range dockerMachineMap {
148+
if machine, ok := externalMachineMap[existingMachine.Name]; ok {
149+
log.Info("Patching existing DockerMachine", "DockerMachine", klog.KObj(&existingMachine))
148150
desiredMachine := computeDesiredDockerMachine(machine.Name(), cluster, machinePool, dockerMachinePool, &existingMachine)
149151
if err := ssa.Patch(ctx, r.Client, dockerMachinePoolControllerName, desiredMachine, ssa.WithCachingProxy{Cache: r.ssaCache, Original: &existingMachine}); err != nil {
150152
return errors.Wrapf(err, "failed to update DockerMachine %q", klog.KObj(desiredMachine))
151153
}
152-
153-
dockerMachineMap[desiredMachine.Name] = *desiredMachine
154154
} else {
155-
log.V(2).Info("Creating a new DockerMachine for Docker container", "container", machine.Name())
156-
desiredMachine := computeDesiredDockerMachine(machine.Name(), cluster, machinePool, dockerMachinePool, nil)
157-
if err := ssa.Patch(ctx, r.Client, dockerMachinePoolControllerName, desiredMachine); err != nil {
158-
return errors.Wrap(err, "failed to create a new docker machine")
155+
log.Info("Creating a new Docker container for DockerMachine", "DockerMachine", klog.KObj(&existingMachine))
156+
if err := createDockerContainer(ctx, existingMachine.Name, cluster, machinePool, dockerMachinePool); err != nil {
157+
return errors.Wrap(err, "failed to create a new docker container")
159158
}
160-
161-
dockerMachineMap[desiredMachine.Name] = *desiredMachine
162159
}
163160
}
164-
165-
// Step 2:
166-
// Delete any DockerMachines that correspond to a deleted Docker container.
167-
// Providers should iterate through the InfraMachines to ensure each one still corresponds to an existing infrastructure instance.
168-
// This allows the InfraMachine (and owner Machine) to be deleted and avoid hanging resources when a user deletes an instance out-of-band.
169-
for _, dockerMachine := range dockerMachineMap {
170-
if _, ok := externalMachineMap[dockerMachine.Name]; !ok {
171-
dockerMachine := dockerMachine
172-
log.V(2).Info("Deleting DockerMachine with no underlying infrastructure", "DockerMachine", klog.KObj(&dockerMachine))
173-
if err := r.deleteMachinePoolMachine(ctx, dockerMachine); err != nil {
174-
return err
175-
}
176-
177-
delete(dockerMachineMap, dockerMachine.Name)
178-
}
161+
// Get the Docker containers after creating missing containers.
162+
externalMachineMap, err = getExternalMachinesMap(ctx, cluster, labelFilters)
163+
if err != nil {
164+
return errors.Wrapf(err, "failed to list all machines in the cluster")
179165
}
180166

181-
// Step 3:
167+
// Step 2:
182168
// This handles the scale down/excess replicas case and the case where a rolling upgrade is needed.
183169
// If there are more ready DockerMachines than desired replicas, start to delete the excess DockerMachines such that
184170
// - DockerMachines with an outdated Kubernetes version or custom image are deleted first (i.e. the rolling upgrade).
@@ -218,7 +204,7 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
218204
for _, dockerMachine := range outdatedMachines {
219205
if overProvisionCount > 0 {
220206
dockerMachine := dockerMachine
221-
log.V(2).Info("Deleting DockerMachine because it is outdated", "DockerMachine", klog.KObj(&dockerMachine))
207+
log.Info("Deleting DockerMachine because it is outdated", "DockerMachine", klog.KObj(&dockerMachine))
222208
if err := r.deleteMachinePoolMachine(ctx, dockerMachine); err != nil {
223209
return err
224210
}
@@ -231,7 +217,7 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
231217
for _, dockerMachine := range readyMachines {
232218
if overProvisionCount > 0 {
233219
dockerMachine := dockerMachine
234-
log.V(2).Info("Deleting DockerMachine because it is an excess replica", "DockerMachine", klog.KObj(&dockerMachine))
220+
log.Info("Deleting DockerMachine because it is an excess replica", "DockerMachine", klog.KObj(&dockerMachine))
235221
if err := r.deleteMachinePoolMachine(ctx, dockerMachine); err != nil {
236222
return err
237223
}
@@ -243,6 +229,21 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
243229
return nil
244230
}
245231

232+
// getExternalMachinesMap will return a map of docker.Machines (containers) that belong to the give cluster and filter. Docker machine name as key and docker.Machine as value.
233+
func getExternalMachinesMap(ctx context.Context, cluster *clusterv1.Cluster, labels map[string]string) (map[string]*docker.Machine, error) {
234+
externalMachines, err := docker.ListMachinesByCluster(ctx, cluster, labels)
235+
if err != nil {
236+
return nil, errors.Wrapf(err, "failed to list all machines in the cluster")
237+
}
238+
239+
externalMachineMap := make(map[string]*docker.Machine)
240+
for _, externalMachine := range externalMachines {
241+
externalMachineMap[externalMachine.Name()] = externalMachine
242+
}
243+
244+
return externalMachineMap, nil
245+
}
246+
246247
// computeDesiredDockerMachine creates a DockerMachine to represent a Docker container in a DockerMachinePool.
247248
// These DockerMachines have the clusterv1.ClusterNameLabel and clusterv1.MachinePoolNameLabel to support MachinePool Machines.
248249
func computeDesiredDockerMachine(name string, cluster *clusterv1.Cluster, machinePool *expv1.MachinePool, dockerMachinePool *infraexpv1.DockerMachinePool, existingDockerMachine *infrav1.DockerMachine) *infrav1.DockerMachine {
@@ -272,6 +273,7 @@ func computeDesiredDockerMachine(name string, cluster *clusterv1.Cluster, machin
272273
Name: dockerMachinePool.Name,
273274
UID: dockerMachinePool.UID,
274275
}))
276+
275277
dockerMachine.Labels[clusterv1.ClusterNameLabel] = cluster.Name
276278
dockerMachine.Labels[clusterv1.MachinePoolNameLabel] = format.MustFormatValue(machinePool.Name)
277279

@@ -288,7 +290,7 @@ func (r *DockerMachinePoolReconciler) deleteMachinePoolMachine(ctx context.Conte
288290
}
289291
// util.GetOwnerMachine() returns a nil Machine without error if there is no Machine kind in the ownerRefs, so we must verify that machine is not nil.
290292
if machine == nil {
291-
log.V(2).Info("No owner Machine exists for DockerMachine", "dockerMachine", klog.KObj(&dockerMachine))
293+
log.Info("No owner Machine exists for DockerMachine", "dockerMachine", klog.KObj(&dockerMachine))
292294

293295
// If the DockerMachine does not have an owner Machine, do not attempt to delete the DockerMachine as the MachinePool controller will create the
294296
// Machine and we want to let it catch up. If we are too hasty to delete, that introduces a race condition where the DockerMachine could be deleted
@@ -297,7 +299,8 @@ func (r *DockerMachinePoolReconciler) deleteMachinePoolMachine(ctx context.Conte
297299
// In the case where the MachinePool is being deleted and the Machine will never come online, the DockerMachine will be deleted via its ownerRef to the
298300
// DockerMachinePool, so that is covered as well.
299301

300-
return nil
302+
// Returning error as we need the dockerMachine not to proceed.
303+
return errors.New("No owner Machine exists for DockerMachine")
301304
}
302305

303306
log.Info("Deleting Machine for DockerMachine", "Machine", klog.KObj(machine), "DockerMachine", klog.KObj(&dockerMachine))

test/infrastructure/docker/internal/controllers/dockermachine_controller.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func (r *DockerMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques
183183
}
184184

185185
// Handle deleted machines
186-
if !dockerMachine.ObjectMeta.DeletionTimestamp.IsZero() {
186+
if !dockerMachine.DeletionTimestamp.IsZero() {
187187
return ctrl.Result{}, r.reconcileDelete(ctx, cluster, dockerCluster, machine, dockerMachine, externalMachine, externalLoadBalancer)
188188
}
189189

@@ -464,11 +464,11 @@ func (r *DockerMachineReconciler) reconcileDelete(ctx context.Context, cluster *
464464

465465
// delete the machine
466466
if err := externalMachine.Delete(ctx); err != nil {
467-
return errors.Wrap(err, "failed to delete DockerMachine")
467+
return errors.Wrap(err, "failed to delete external DockerMachine")
468468
}
469469

470470
// if the deleted machine is a control-plane node, remove it from the load balancer configuration;
471-
if util.IsControlPlaneMachine(machine) {
471+
if machine != nil && util.IsControlPlaneMachine(machine) {
472472
if err := r.reconcileLoadBalancerConfiguration(ctx, cluster, dockerCluster, externalLoadBalancer); err != nil {
473473
return err
474474
}

0 commit comments

Comments
 (0)