Skip to content

Commit 3a06b48

Browse files
committed
delete bootstrapRef when create infraRef failed
1 parent 879617d commit 3a06b48

File tree

2 files changed

+156
-2
lines changed

2 files changed

+156
-2
lines changed

internal/controllers/machineset/machineset_controller.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,10 +541,17 @@ func (r *Reconciler) syncReplicas(ctx context.Context, cluster *clusterv1.Cluste
541541
},
542542
})
543543
if err != nil {
544+
var deleteErr error
545+
if bootstrapRef != nil {
546+
// Cleanup the bootstrap resource if we can't create the InfraMachine; or we might risk to leak it.
547+
if err := r.Client.Delete(ctx, util.ObjectReferenceToUnstructured(*bootstrapRef)); err != nil && !apierrors.IsNotFound(err) {
548+
deleteErr = errors.Wrapf(err, "failed to cleanup %s %s after %s creation failed", bootstrapRef.Kind, klog.KRef(bootstrapRef.Namespace, bootstrapRef.Name), (&ms.Spec.Template.Spec.InfrastructureRef).Kind)
549+
}
550+
}
544551
conditions.MarkFalse(ms, clusterv1.MachinesCreatedCondition, clusterv1.InfrastructureTemplateCloningFailedReason, clusterv1.ConditionSeverityError, err.Error())
545-
return ctrl.Result{}, errors.Wrapf(err, "failed to clone infrastructure machine from %s %s while creating a machine",
552+
return ctrl.Result{}, kerrors.NewAggregate([]error{errors.Wrapf(err, "failed to clone infrastructure machine from %s %s while creating a machine",
546553
ms.Spec.Template.Spec.InfrastructureRef.Kind,
547-
klog.KRef(ms.Spec.Template.Spec.InfrastructureRef.Namespace, ms.Spec.Template.Spec.InfrastructureRef.Name))
554+
klog.KRef(ms.Spec.Template.Spec.InfrastructureRef.Namespace, ms.Spec.Template.Spec.InfrastructureRef.Name)), deleteErr})
548555
}
549556
log = log.WithValues(infraRef.Kind, klog.KRef(infraRef.Namespace, infraRef.Name))
550557
machine.Spec.InfrastructureRef = *infraRef

internal/controllers/machineset/machineset_controller_test.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ limitations under the License.
1717
package machineset
1818

1919
import (
20+
"context"
2021
"fmt"
22+
"k8s.io/apimachinery/pkg/runtime/schema"
23+
"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
24+
"strings"
2125
"testing"
2226
"time"
2327

@@ -1969,6 +1973,149 @@ func TestMachineSetReconciler_syncReplicas(t *testing.T) {
19691973
})
19701974
}
19711975

1976+
func TestMachineSetReconciler_syncReplicas_WithErrors(t *testing.T) {
1977+
t.Run("should hold off on sync replicas when create Infrastructure of machine failed ", func(t *testing.T) {
1978+
g := NewWithT(t)
1979+
fakeClient := fake.NewClientBuilder().WithObjects().WithInterceptorFuncs(interceptor.Funcs{
1980+
Create: func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.CreateOption) error {
1981+
// simulate scenarios where infra object creation fails
1982+
if obj.GetObjectKind().GroupVersionKind().Kind == "GenericInfrastructureMachine" {
1983+
return fmt.Errorf("inject error for create machineInfrastructure")
1984+
}
1985+
return client.Create(ctx, obj, opts...)
1986+
},
1987+
}).Build()
1988+
1989+
r := &Reconciler{
1990+
Client: fakeClient,
1991+
}
1992+
testCluster := &clusterv1.Cluster{}
1993+
testCluster.Namespace = "default"
1994+
testCluster.Name = "test-cluster"
1995+
version := "v1.14.2"
1996+
duration10m := &metav1.Duration{Duration: 10 * time.Minute}
1997+
machineSet := &clusterv1.MachineSet{
1998+
ObjectMeta: metav1.ObjectMeta{
1999+
Name: "machineset1",
2000+
Namespace: metav1.NamespaceDefault,
2001+
Finalizers: []string{"block-deletion"},
2002+
},
2003+
Spec: clusterv1.MachineSetSpec{
2004+
Replicas: ptr.To[int32](1),
2005+
ClusterName: "test-cluster",
2006+
Template: clusterv1.MachineTemplateSpec{
2007+
Spec: clusterv1.MachineSpec{
2008+
ClusterName: testCluster.Name,
2009+
Version: &version,
2010+
Bootstrap: clusterv1.Bootstrap{
2011+
ConfigRef: &corev1.ObjectReference{
2012+
APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1",
2013+
Kind: "GenericBootstrapConfigTemplate",
2014+
Name: "ms-template",
2015+
},
2016+
},
2017+
InfrastructureRef: corev1.ObjectReference{
2018+
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
2019+
Kind: "GenericInfrastructureMachineTemplate",
2020+
Name: "ms-template",
2021+
},
2022+
NodeDrainTimeout: duration10m,
2023+
NodeDeletionTimeout: duration10m,
2024+
NodeVolumeDetachTimeout: duration10m,
2025+
},
2026+
},
2027+
},
2028+
}
2029+
2030+
// Create bootstrap template resource.
2031+
bootstrapResource := map[string]interface{}{
2032+
"kind": "GenericBootstrapConfig",
2033+
"apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1",
2034+
"metadata": map[string]interface{}{
2035+
"annotations": map[string]interface{}{
2036+
"precedence": "GenericBootstrapConfig",
2037+
},
2038+
},
2039+
}
2040+
bootstrapTmpl := &unstructured.Unstructured{
2041+
Object: map[string]interface{}{
2042+
"spec": map[string]interface{}{
2043+
"template": bootstrapResource,
2044+
},
2045+
},
2046+
}
2047+
bootstrapTmpl.SetKind("GenericBootstrapConfigTemplate")
2048+
bootstrapTmpl.SetAPIVersion("bootstrap.cluster.x-k8s.io/v1beta1")
2049+
bootstrapTmpl.SetName("ms-template")
2050+
bootstrapTmpl.SetNamespace(metav1.NamespaceDefault)
2051+
g.Expect(r.Client.Create(context.TODO(), bootstrapTmpl)).To(Succeed())
2052+
2053+
// Create infrastructure template resource.
2054+
infraResource := map[string]interface{}{
2055+
"kind": "GenericInfrastructureMachine",
2056+
"apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1",
2057+
"metadata": map[string]interface{}{
2058+
"annotations": map[string]interface{}{
2059+
"precedence": "GenericInfrastructureMachineTemplate",
2060+
},
2061+
},
2062+
"spec": map[string]interface{}{
2063+
"size": "3xlarge",
2064+
},
2065+
}
2066+
infraTmpl := &unstructured.Unstructured{
2067+
Object: map[string]interface{}{
2068+
"spec": map[string]interface{}{
2069+
"template": infraResource,
2070+
},
2071+
},
2072+
}
2073+
infraTmpl.SetKind("GenericInfrastructureMachineTemplate")
2074+
infraTmpl.SetAPIVersion("infrastructure.cluster.x-k8s.io/v1beta1")
2075+
infraTmpl.SetName("ms-template")
2076+
infraTmpl.SetNamespace(metav1.NamespaceDefault)
2077+
g.Expect(r.Client.Create(context.TODO(), infraTmpl)).To(Succeed())
2078+
2079+
_, err := r.syncReplicas(ctx, testCluster, machineSet, nil)
2080+
g.Expect(err).To(HaveOccurred())
2081+
2082+
// Verify the proper condition is set on the MachineSet.
2083+
condition := clusterv1.MachinesCreatedCondition
2084+
g.Expect(conditions.Has(machineSet, condition)).To(BeTrue(), "MachineSet should have the %s condition set", condition)
2085+
2086+
machinesCreatedCondition := conditions.Get(machineSet, condition)
2087+
g.Expect(machinesCreatedCondition.Status).
2088+
To(Equal(corev1.ConditionFalse), "%s condition status should be %s", condition, corev1.ConditionFalse)
2089+
g.Expect(machinesCreatedCondition.Reason).
2090+
To(Equal(clusterv1.InfrastructureTemplateCloningFailedReason), "%s condition reason should be %s", condition, clusterv1.InfrastructureTemplateCloningFailedReason)
2091+
2092+
// Verify no new Machines are created.
2093+
machineList := &clusterv1.MachineList{}
2094+
g.Expect(r.Client.List(ctx, machineList)).To(Succeed())
2095+
g.Expect(machineList.Items).To(BeEmpty(), "There should not be any machines")
2096+
2097+
// Verify no boostrap object created
2098+
bootstrapList := &unstructured.UnstructuredList{}
2099+
bootstrapList.SetGroupVersionKind(schema.GroupVersionKind{
2100+
Group: bootstrapTmpl.GetObjectKind().GroupVersionKind().Group,
2101+
Version: bootstrapTmpl.GetObjectKind().GroupVersionKind().Version,
2102+
Kind: strings.TrimSuffix(bootstrapTmpl.GetObjectKind().GroupVersionKind().Kind, clusterv1.TemplateSuffix),
2103+
})
2104+
g.Expect(r.Client.List(ctx, bootstrapList)).To(Succeed())
2105+
g.Expect(len(bootstrapList.Items)).To(BeEmpty(), "There should not be any bootstrap object")
2106+
2107+
// Verify no infra object created
2108+
infraList := &unstructured.UnstructuredList{}
2109+
infraList.SetGroupVersionKind(schema.GroupVersionKind{
2110+
Group: infraTmpl.GetObjectKind().GroupVersionKind().Group,
2111+
Version: infraTmpl.GetObjectKind().GroupVersionKind().Version,
2112+
Kind: strings.TrimSuffix(infraTmpl.GetObjectKind().GroupVersionKind().Kind, clusterv1.TemplateSuffix),
2113+
})
2114+
g.Expect(r.Client.List(ctx, infraList)).To(Succeed())
2115+
g.Expect(len(infraList.Items)).To(BeEmpty(), "There should not be any infra object")
2116+
})
2117+
}
2118+
19722119
func TestComputeDesiredMachine(t *testing.T) {
19732120
duration5s := &metav1.Duration{Duration: 5 * time.Second}
19742121
duration10s := &metav1.Duration{Duration: 10 * time.Second}

0 commit comments

Comments
 (0)