Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 IP reuse: Fix M3d/IPClaim deletion bug #1255

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions baremetal/metal3data_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,7 @@ func fetchM3IPClaim(ctx context.Context, cl client.Client, mLog logr.Logger,
func (m *DataManager) fetchIPClaimsWithLabels(ctx context.Context, pool string) ([]ipamv1.IPClaim, error) {
allIPClaims := ipamv1.IPClaimList{}
opts := []client.ListOption{
&client.ListOptions{Namespace: m.Data.Namespace},
client.MatchingLabels{
DataLabelName: m.Data.Name,
PoolLabelName: pool,
Expand Down
163 changes: 163 additions & 0 deletions baremetal/metal3data_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,169 @@ var _ = Describe("Metal3Data manager", func() {
}),
)

type testCaseMultiReleaseAddressFromM3Pool struct {
m3d *infrav1.Metal3Data
poolRef corev1.TypedLocalObjectReference
ipClaims []ipamv1.IPClaim
}

DescribeTable("Test releaseAddressFromM3Pool with multiple namespaces",
func(tc testCaseMultiReleaseAddressFromM3Pool) {
objects := []client.Object{}
for i := range tc.ipClaims {
// To make the test entries a bit smaller, we add the
// .spec.pool here based on the labels.
tc.ipClaims[i].Spec.Pool.Name = tc.ipClaims[i].Labels[PoolLabelName]
objects = append(objects, &tc.ipClaims[i])
}
fake := fake.NewClientBuilder().WithScheme(setupScheme()).WithObjects(objects...).Build()
dataMgr, err := NewDataManager(fake, tc.m3d,
logr.Discard(),
)
Expect(err).NotTo(HaveOccurred())
err = dataMgr.releaseAddressFromM3Pool(
context.TODO(), tc.poolRef,
)
Expect(err).NotTo(HaveOccurred())

for i := range tc.ipClaims {
capm3IPClaim := &ipamv1.IPClaim{}
claimNamespacedName := types.NamespacedName{
Name: tc.ipClaims[i].Name,
Namespace: tc.ipClaims[i].Namespace,
}

err = dataMgr.client.Get(context.TODO(), claimNamespacedName, capm3IPClaim)
if tc.ipClaims[i].Namespace != dataMgr.Data.Namespace {
// We should not touch other namespaces!
Expect(err).To(BeNil())
} else if tc.ipClaims[i].Spec.Pool.Name != tc.poolRef.Name {
// We should not touch other pools!
Expect(err).To(BeNil())
} else {
Expect(err).To(HaveOccurred())
Expect(apierrors.IsNotFound(err)).To(BeTrue())
}
}
},
Entry("Singe IPClaim deleted", testCaseMultiReleaseAddressFromM3Pool{
m3d: &infrav1.Metal3Data{
ObjectMeta: testObjectMeta(metal3DataName, namespaceName, ""),
TypeMeta: metav1.TypeMeta{
Kind: "Metal3Data",
APIVersion: infrav1.GroupVersion.String(),
},
},
poolRef: corev1.TypedLocalObjectReference{Name: testPoolName},
ipClaims: []ipamv1.IPClaim{{
ObjectMeta: metav1.ObjectMeta{
Name: "host-0-" + testPoolName,
Namespace: namespaceName,
Labels: map[string]string{
DataLabelName: metal3DataName,
PoolLabelName: testPoolName,
},
},
}},
}),
Entry("Multiple IPClaims related to the same M3D", testCaseMultiReleaseAddressFromM3Pool{
m3d: &infrav1.Metal3Data{
ObjectMeta: testObjectMeta(metal3DataName, namespaceName, ""),
TypeMeta: metav1.TypeMeta{
Kind: "Metal3Data",
APIVersion: infrav1.GroupVersion.String(),
},
},
poolRef: corev1.TypedLocalObjectReference{Name: "first-pool"},
ipClaims: []ipamv1.IPClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "host-0-" + "first-pool",
Namespace: namespaceName,
Labels: map[string]string{
DataLabelName: metal3DataName,
PoolLabelName: "first-pool",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "host-0-" + "second-pool",
Namespace: namespaceName,
Labels: map[string]string{
DataLabelName: metal3DataName,
PoolLabelName: "second-pool",
},
},
},
},
}),
Entry("Multiple IPClaims in different namespaces exists with different labels", testCaseMultiReleaseAddressFromM3Pool{
m3d: &infrav1.Metal3Data{
ObjectMeta: testObjectMeta(metal3DataName, namespaceName, ""),
TypeMeta: metav1.TypeMeta{
Kind: "Metal3Data",
APIVersion: infrav1.GroupVersion.String(),
},
},
poolRef: corev1.TypedLocalObjectReference{Name: testPoolName},
ipClaims: []ipamv1.IPClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "host-0-" + testPoolName,
Namespace: namespaceName,
Labels: map[string]string{
DataLabelName: metal3DataName,
PoolLabelName: testPoolName,
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "host-1-" + testPoolName,
Namespace: "other-namespace",
Labels: map[string]string{
DataLabelName: "different-dataname",
PoolLabelName: testPoolName,
},
},
},
},
}),
Entry("Multiple IPClaims in different namespaces exists with same labels", testCaseMultiReleaseAddressFromM3Pool{
m3d: &infrav1.Metal3Data{
ObjectMeta: testObjectMeta(metal3DataName, namespaceName, ""),
TypeMeta: metav1.TypeMeta{
Kind: "Metal3Data",
APIVersion: infrav1.GroupVersion.String(),
},
},
poolRef: corev1.TypedLocalObjectReference{Name: testPoolName},
ipClaims: []ipamv1.IPClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "host-0-" + testPoolName,
Namespace: namespaceName,
Labels: map[string]string{
DataLabelName: metal3DataName,
PoolLabelName: testPoolName,
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "host-1-" + testPoolName,
Namespace: "other-namespace",
Labels: map[string]string{
DataLabelName: metal3DataName,
PoolLabelName: testPoolName,
},
},
},
},
}),
)

type testCaseEnsureClaim struct {
poolRef corev1.TypedLocalObjectReference
ipClaim *caipamv1.IPAddressClaim
Expand Down