Skip to content

Commit 9927511

Browse files
committed
Prevent Machine rollout on provider upgrade
Signed-off-by: Andrea Mazzotti <[email protected]>
1 parent b4a8a0f commit 9927511

File tree

4 files changed

+102
-3
lines changed

4 files changed

+102
-3
lines changed

bootstrap/config/default/manager_pull_policy.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ spec:
88
spec:
99
containers:
1010
- name: manager
11-
imagePullPolicy: Always
11+
imagePullPolicy: IfNotPresent

controlplane/config/default/manager_pull_policy.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ spec:
88
spec:
99
containers:
1010
- name: manager
11-
imagePullPolicy: Always
11+
imagePullPolicy: IfNotPresent

test/e2e/e2e_upgrade_test.go

+39-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import (
3636
"sigs.k8s.io/controller-runtime/pkg/client"
3737
)
3838

39-
var _ = Describe("Workload cluster creation", func() {
39+
var _ = FDescribe("Workload cluster creation", func() {
4040
var (
4141
specName = "create-workload-cluster"
4242
namespace *corev1.Namespace
@@ -114,6 +114,24 @@ var _ = Describe("Workload cluster creation", func() {
114114
ControlPlane: client.ObjectKeyFromObject(result.ControlPlane),
115115
}, e2eConfig.GetIntervals(specName, "wait-control-plane")...)
116116

117+
WaitForClusterReady(ctx, WaitForClusterReadyInput{
118+
Getter: bootstrapClusterProxy.GetClient(),
119+
Name: result.Cluster.Name,
120+
Namespace: result.Cluster.Namespace,
121+
}, e2eConfig.GetIntervals(specName, "wait-cluster")...)
122+
123+
By("Fetching all Machines")
124+
machineList := GetMachinesByCluster(ctx, GetMachinesByClusterInput{
125+
Lister: bootstrapClusterProxy.GetClient(),
126+
ClusterName: result.Cluster.Name,
127+
Namespace: result.Cluster.Namespace,
128+
})
129+
Expect(machineList.Items).ShouldNot(BeEmpty(), "There must be at least one Machine")
130+
machinesNames := []string{}
131+
for _, machine := range machineList.Items {
132+
machinesNames = append(machinesNames, machine.Name)
133+
}
134+
117135
By("Upgrading to next boostrap/controlplane provider version")
118136
UpgradeManagementCluster(ctx, clusterctl.UpgradeManagementClusterAndWaitInput{
119137
ClusterProxy: bootstrapClusterProxy,
@@ -128,6 +146,26 @@ var _ = Describe("Workload cluster creation", func() {
128146
ControlPlane: client.ObjectKeyFromObject(result.ControlPlane),
129147
}, e2eConfig.GetIntervals(specName, "wait-control-plane")...)
130148

149+
WaitForClusterReady(ctx, WaitForClusterReadyInput{
150+
Getter: bootstrapClusterProxy.GetClient(),
151+
Name: result.Cluster.Name,
152+
Namespace: result.Cluster.Namespace,
153+
}, e2eConfig.GetIntervals(specName, "wait-cluster"))
154+
155+
By("Verifying machine rollout did not happen")
156+
updatedMachineList := GetMachinesByCluster(ctx, GetMachinesByClusterInput{
157+
Lister: bootstrapClusterProxy.GetClient(),
158+
ClusterName: result.Cluster.Name,
159+
Namespace: result.Cluster.Namespace,
160+
})
161+
Expect(updatedMachineList.Items).ShouldNot(BeEmpty(), "There must be at least one Machine after provider upgrade")
162+
updatedMachinesNames := []string{}
163+
for _, machine := range updatedMachineList.Items {
164+
updatedMachinesNames = append(updatedMachinesNames, machine.Name)
165+
}
166+
Expect(updatedMachinesNames).Should(ContainElements(machinesNames), "Machines should not have been rolled out after provider upgrade")
167+
Expect(len(updatedMachinesNames)).Should(Equal(len(machinesNames)), "Number of Machines should match after provider upgrade")
168+
131169
By("Scaling down control plane to 2 and workers up to 2")
132170
ApplyClusterTemplateAndWait(ctx, ApplyClusterTemplateAndWaitInput{
133171
ClusterProxy: bootstrapClusterProxy,

test/e2e/helpers.go

+61
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636

3737
pkgerrors "github.com/pkg/errors"
3838
controlplanev1 "github.com/rancher/cluster-api-provider-rke2/controlplane/api/v1beta1"
39+
corev1 "k8s.io/api/core/v1"
3940
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
4041
"sigs.k8s.io/cluster-api/test/framework"
4142
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
@@ -302,6 +303,30 @@ func GetRKE2ControlPlaneByCluster(ctx context.Context, input GetRKE2ControlPlane
302303
return nil
303304
}
304305

306+
// GetMachinesByClusterInput is the input for GetRKE2ControlPlaneByCluster.
307+
type GetMachinesByClusterInput struct {
308+
Lister framework.Lister
309+
ClusterName string
310+
Namespace string
311+
}
312+
313+
// GetMachinesByCluster returns the Machine objects for a cluster.
314+
func GetMachinesByCluster(ctx context.Context, input GetMachinesByClusterInput) *clusterv1.MachineList {
315+
opts := []client.ListOption{
316+
client.InNamespace(input.Namespace),
317+
client.MatchingLabels{
318+
clusterv1.ClusterNameLabel: input.ClusterName,
319+
},
320+
}
321+
322+
machineList := &clusterv1.MachineList{}
323+
Eventually(func() error {
324+
return input.Lister.List(ctx, machineList, opts...)
325+
}, retryableOperationTimeout, retryableOperationInterval).Should(Succeed(), "Failed to list Machine objects for Cluster %s", klog.KRef(input.Namespace, input.ClusterName))
326+
327+
return machineList
328+
}
329+
305330
// WaitForControlPlaneAndMachinesReadyInput is the input type for WaitForControlPlaneAndMachinesReady.
306331
type WaitForControlPlaneAndMachinesReadyInput struct {
307332
GetLister framework.GetLister
@@ -488,6 +513,42 @@ func WaitForClusterToUpgrade(ctx context.Context, input WaitForClusterToUpgradeI
488513
}, intervals...).Should(Succeed())
489514
}
490515

516+
// WaitForClusterReadyInput is the input type for WaitForClusterReady.
517+
type WaitForClusterReadyInput struct {
518+
Getter framework.Getter
519+
Name string
520+
Namespace string
521+
}
522+
523+
// WaitForClusterReady will wait for a Cluster to be Ready.
524+
func WaitForClusterReady(ctx context.Context, input WaitForClusterReadyInput, intervals ...interface{}) {
525+
By("Waiting for Cluster to be Ready")
526+
527+
Eventually(func() error {
528+
cluster := &clusterv1.Cluster{}
529+
key := types.NamespacedName{Name: input.Name, Namespace: input.Namespace}
530+
531+
if err := input.Getter.Get(ctx, key, cluster); err != nil {
532+
return fmt.Errorf("getting Cluster %s/%s: %w", input.Namespace, input.Name, err)
533+
}
534+
535+
readyCondition := conditions.Get(cluster, clusterv1.ReadyCondition)
536+
if readyCondition == nil {
537+
return fmt.Errorf("Cluster Ready condition is not found")
538+
}
539+
540+
switch readyCondition.Status {
541+
case corev1.ConditionTrue:
542+
//Cluster is ready
543+
return nil
544+
case corev1.ConditionFalse:
545+
return fmt.Errorf("Cluster is not Ready")
546+
default:
547+
return fmt.Errorf("Cluster Ready condition is unknown")
548+
}
549+
}, intervals...).Should(Succeed())
550+
}
551+
491552
// setDefaults sets the default values for ApplyCustomClusterTemplateAndWaitInput if not set.
492553
// Currently, we set the default ControlPlaneWaiters here, which are implemented for RKE2ControlPlane.
493554
func setDefaults(input *ApplyCustomClusterTemplateAndWaitInput) {

0 commit comments

Comments
 (0)