Skip to content

Commit 4ca0d89

Browse files
Update cluster paused detection
Clusters can be paused by annotation or by spec.paused. If either are true, skip claim reconcilliation that are associated to those claims. Co-authored-by: Tyler Schultz <[email protected]>
1 parent 157ecc2 commit 4ca0d89

File tree

2 files changed

+214
-49
lines changed

2 files changed

+214
-49
lines changed

internal/controllers/ipaddressclaim.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ func (r *IPAddressClaimReconciler) SetupWithManager(ctx context.Context, mgr ctr
9393
UpdateFunc: func(e event.UpdateEvent) bool {
9494
oldCluster := e.ObjectOld.(*clusterv1.Cluster)
9595
newCluster := e.ObjectNew.(*clusterv1.Cluster)
96-
return oldCluster.Spec.Paused && !newCluster.Spec.Paused
96+
return annotations.IsPaused(oldCluster, oldCluster) && !annotations.IsPaused(newCluster, newCluster)
9797
},
9898
CreateFunc: func(e event.CreateEvent) bool {
99-
return !annotations.HasPaused(e.Object)
99+
cluster := e.Object.(*clusterv1.Cluster)
100+
return !annotations.IsPaused(cluster, cluster)
100101
},
101102
}),
102103
).
@@ -188,7 +189,7 @@ func (r *IPAddressClaimReconciler) Reconcile(ctx context.Context, req ctrl.Reque
188189
return ctrl.Result{}, err
189190
}
190191

191-
if annotations.IsPaused(cluster, claim) {
192+
if annotations.IsPaused(cluster, cluster) {
192193
log.Info("IPAddressClaim linked to a cluster that is paused, skipping reconciliation")
193194
return ctrl.Result{}, nil
194195
}

internal/controllers/ipaddressclaim_test.go

+210-46
Original file line numberDiff line numberDiff line change
@@ -1641,9 +1641,10 @@ var _ = Describe("IPAddressClaimReconciler", func() {
16411641
})
16421642
})
16431643

1644-
Context("When the cluster is paused and the ipaddressclaim has the cluster-name label", func() {
1644+
Context("When the cluster is spec.paused true and the ipaddressclaim has the cluster-name label", func() {
16451645
const (
1646-
poolName = "test-pool"
1646+
clusterName = "test-cluster"
1647+
poolName = "test-pool"
16471648
)
16481649

16491650
var (
@@ -1667,33 +1668,109 @@ var _ = Describe("IPAddressClaimReconciler", func() {
16671668
})
16681669

16691670
Context("When the cluster can be retrieved", func() {
1670-
BeforeEach(func() {
1671+
AfterEach(func() {
1672+
deleteClaim("test", namespace)
1673+
deleteCluster(clusterName, namespace)
1674+
deleteNamespacedPool(poolName, namespace)
1675+
})
1676+
1677+
It("does not allocate an ipaddress upon creating a cluster when the cluster has paused annotation", func() {
1678+
claim := ipamv1.IPAddressClaim{
1679+
ObjectMeta: metav1.ObjectMeta{
1680+
Name: "test",
1681+
Namespace: namespace,
1682+
Labels: map[string]string{
1683+
clusterv1.ClusterNameLabel: clusterName,
1684+
},
1685+
},
1686+
Spec: ipamv1.IPAddressClaimSpec{
1687+
PoolRef: corev1.TypedLocalObjectReference{
1688+
APIGroup: pointer.String("ipam.cluster.x-k8s.io"),
1689+
Kind: "InClusterIPPool",
1690+
Name: poolName,
1691+
},
1692+
},
1693+
}
1694+
Expect(k8sClient.Create(context.Background(), &claim)).To(Succeed())
1695+
Eventually(Get(&claim)).Should(Succeed())
1696+
16711697
cluster = clusterv1.Cluster{
16721698
ObjectMeta: metav1.ObjectMeta{
1673-
GenerateName: "test-cluster",
1674-
Namespace: namespace,
1699+
Name: clusterName,
1700+
Namespace: namespace,
1701+
Annotations: map[string]string{
1702+
clusterv1.PausedAnnotation: "",
1703+
},
1704+
},
1705+
}
1706+
Expect(k8sClient.Create(context.Background(), &cluster)).To(Succeed())
1707+
Eventually(Get(&cluster)).Should(Succeed())
1708+
1709+
addresses := ipamv1.IPAddressList{}
1710+
Consistently(ObjectList(&addresses)).
1711+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1712+
HaveField("Items", HaveLen(0)))
1713+
})
1714+
1715+
It("does not allocate an ipaddress upon creating a cluster when the cluster has spec.Paused", func() {
1716+
claim := ipamv1.IPAddressClaim{
1717+
ObjectMeta: metav1.ObjectMeta{
1718+
Name: "test",
1719+
Namespace: namespace,
1720+
Labels: map[string]string{
1721+
clusterv1.ClusterNameLabel: clusterName,
1722+
},
1723+
},
1724+
Spec: ipamv1.IPAddressClaimSpec{
1725+
PoolRef: corev1.TypedLocalObjectReference{
1726+
APIGroup: pointer.String("ipam.cluster.x-k8s.io"),
1727+
Kind: "InClusterIPPool",
1728+
Name: poolName,
1729+
},
1730+
},
1731+
}
1732+
Expect(k8sClient.Create(context.Background(), &claim)).To(Succeed())
1733+
Eventually(Get(&claim)).Should(Succeed())
1734+
1735+
cluster = clusterv1.Cluster{
1736+
ObjectMeta: metav1.ObjectMeta{
1737+
Name: clusterName,
1738+
Namespace: namespace,
16751739
},
16761740
Spec: clusterv1.ClusterSpec{
16771741
Paused: true,
16781742
},
16791743
}
1744+
16801745
Expect(k8sClient.Create(context.Background(), &cluster)).To(Succeed())
16811746
Eventually(Get(&cluster)).Should(Succeed())
1682-
})
16831747

1684-
AfterEach(func() {
1685-
deleteClaim("test", namespace)
1686-
deleteCluster(cluster.GetName(), namespace)
1687-
deleteNamespacedPool(poolName, namespace)
1748+
addresses := ipamv1.IPAddressList{}
1749+
Consistently(ObjectList(&addresses)).
1750+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1751+
HaveField("Items", HaveLen(0)))
16881752
})
16891753

1690-
It("does not allocate an ipaddress for the claim until the cluster is unpaused", func() {
1754+
It("does not allocate an ipaddress upon updating a cluster when the cluster has spec.paused", func() {
1755+
cluster = clusterv1.Cluster{
1756+
ObjectMeta: metav1.ObjectMeta{
1757+
Name: clusterName,
1758+
Namespace: namespace,
1759+
},
1760+
Spec: clusterv1.ClusterSpec{
1761+
Paused: true,
1762+
},
1763+
}
1764+
1765+
Expect(k8sClient.Create(context.Background(), &cluster)).To(Succeed())
1766+
Eventually(Get(&cluster)).Should(Succeed())
1767+
16911768
claim := ipamv1.IPAddressClaim{
16921769
ObjectMeta: metav1.ObjectMeta{
16931770
Name: "test",
16941771
Namespace: namespace,
16951772
Labels: map[string]string{
1696-
clusterv1.ClusterNameLabel: cluster.GetName(),
1773+
clusterv1.ClusterNameLabel: clusterName,
16971774
},
16981775
},
16991776
Spec: ipamv1.IPAddressClaimSpec{
@@ -1707,64 +1784,151 @@ var _ = Describe("IPAddressClaimReconciler", func() {
17071784
Expect(k8sClient.Create(context.Background(), &claim)).To(Succeed())
17081785
Eventually(Get(&claim)).Should(Succeed())
17091786

1787+
// update the cluster
1788+
cluster.Annotations = map[string]string{"superficial": "change"}
1789+
Expect(k8sClient.Update(context.Background(), &cluster)).To(Succeed())
1790+
17101791
addresses := ipamv1.IPAddressList{}
17111792
Consistently(ObjectList(&addresses)).
17121793
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
17131794
HaveField("Items", HaveLen(0)))
1795+
})
17141796

1715-
// Unpause the cluster
1716-
cluster.Spec.Paused = false
1717-
Expect(k8sClient.Update(context.Background(), &cluster)).To(Succeed())
1797+
It("does not allocate an ipaddress upon updating a cluster when the cluster has paused annotation", func() {
1798+
cluster = clusterv1.Cluster{
1799+
ObjectMeta: metav1.ObjectMeta{
1800+
Name: clusterName,
1801+
Namespace: namespace,
1802+
Annotations: map[string]string{
1803+
clusterv1.PausedAnnotation: "",
1804+
},
1805+
},
1806+
}
17181807

1719-
expectedIPAddress := ipamv1.IPAddress{
1808+
Expect(k8sClient.Create(context.Background(), &cluster)).To(Succeed())
1809+
Eventually(Get(&cluster)).Should(Succeed())
1810+
1811+
claim := ipamv1.IPAddressClaim{
17201812
ObjectMeta: metav1.ObjectMeta{
1721-
Name: "test",
1722-
Namespace: namespace,
1723-
Finalizers: []string{ProtectAddressFinalizer},
1724-
OwnerReferences: []metav1.OwnerReference{
1725-
{
1726-
APIVersion: "ipam.cluster.x-k8s.io/v1alpha1",
1727-
BlockOwnerDeletion: pointer.Bool(true),
1728-
Controller: pointer.Bool(true),
1729-
Kind: "IPAddressClaim",
1730-
Name: "test",
1731-
},
1732-
{
1733-
APIVersion: "ipam.cluster.x-k8s.io/v1alpha2",
1734-
BlockOwnerDeletion: pointer.Bool(true),
1735-
Controller: pointer.Bool(false),
1736-
Kind: "InClusterIPPool",
1737-
Name: poolName,
1738-
},
1813+
Name: "test",
1814+
Namespace: namespace,
1815+
Labels: map[string]string{
1816+
clusterv1.ClusterNameLabel: clusterName,
17391817
},
17401818
},
1741-
Spec: ipamv1.IPAddressSpec{
1742-
ClaimRef: corev1.LocalObjectReference{
1743-
Name: "test",
1819+
Spec: ipamv1.IPAddressClaimSpec{
1820+
PoolRef: corev1.TypedLocalObjectReference{
1821+
APIGroup: pointer.String("ipam.cluster.x-k8s.io"),
1822+
Kind: "InClusterIPPool",
1823+
Name: poolName,
17441824
},
1825+
},
1826+
}
1827+
Expect(k8sClient.Create(context.Background(), &claim)).To(Succeed())
1828+
Eventually(Get(&claim)).Should(Succeed())
1829+
1830+
// update the cluster
1831+
cluster.Annotations["superficial"] = "change"
1832+
Expect(k8sClient.Update(context.Background(), &cluster)).To(Succeed())
1833+
1834+
addresses := ipamv1.IPAddressList{}
1835+
Consistently(ObjectList(&addresses)).
1836+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1837+
HaveField("Items", HaveLen(0)))
1838+
})
1839+
1840+
It("allocates an ipaddress upon updating a cluster when removing spec.paused", func() {
1841+
cluster = clusterv1.Cluster{
1842+
ObjectMeta: metav1.ObjectMeta{
1843+
Name: clusterName,
1844+
Namespace: namespace,
1845+
},
1846+
Spec: clusterv1.ClusterSpec{
1847+
Paused: true,
1848+
},
1849+
}
1850+
1851+
Expect(k8sClient.Create(context.Background(), &cluster)).To(Succeed())
1852+
Eventually(Get(&cluster)).Should(Succeed())
1853+
1854+
claim := ipamv1.IPAddressClaim{
1855+
ObjectMeta: metav1.ObjectMeta{
1856+
Name: "test",
1857+
Namespace: namespace,
1858+
Labels: map[string]string{
1859+
clusterv1.ClusterNameLabel: clusterName,
1860+
},
1861+
},
1862+
Spec: ipamv1.IPAddressClaimSpec{
17451863
PoolRef: corev1.TypedLocalObjectReference{
17461864
APIGroup: pointer.String("ipam.cluster.x-k8s.io"),
17471865
Kind: "InClusterIPPool",
17481866
Name: poolName,
17491867
},
1750-
Address: "10.0.0.1",
1751-
Prefix: 24,
1752-
Gateway: "10.0.0.2",
17531868
},
17541869
}
1870+
Expect(k8sClient.Create(context.Background(), &claim)).To(Succeed())
1871+
Eventually(Get(&claim)).Should(Succeed())
17551872

1756-
address := ipamv1.IPAddress{
1873+
addresses := ipamv1.IPAddressList{}
1874+
Consistently(ObjectList(&addresses)).
1875+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1876+
HaveField("Items", HaveLen(0)))
1877+
1878+
// update the cluster
1879+
cluster.Spec.Paused = false
1880+
Expect(k8sClient.Update(context.Background(), &cluster)).To(Succeed())
1881+
1882+
Eventually(ObjectList(&addresses)).
1883+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1884+
HaveField("Items", HaveLen(1)))
1885+
})
1886+
1887+
It("allocates an ipaddress upon updating a cluster when removing the paused annotation", func() {
1888+
cluster = clusterv1.Cluster{
1889+
ObjectMeta: metav1.ObjectMeta{
1890+
Name: clusterName,
1891+
Namespace: namespace,
1892+
Annotations: map[string]string{
1893+
clusterv1.PausedAnnotation: "",
1894+
},
1895+
},
1896+
}
1897+
1898+
Expect(k8sClient.Create(context.Background(), &cluster)).To(Succeed())
1899+
Eventually(Get(&cluster)).Should(Succeed())
1900+
1901+
claim := ipamv1.IPAddressClaim{
17571902
ObjectMeta: metav1.ObjectMeta{
17581903
Name: "test",
17591904
Namespace: namespace,
1905+
Labels: map[string]string{
1906+
clusterv1.ClusterNameLabel: clusterName,
1907+
},
1908+
},
1909+
Spec: ipamv1.IPAddressClaimSpec{
1910+
PoolRef: corev1.TypedLocalObjectReference{
1911+
APIGroup: pointer.String("ipam.cluster.x-k8s.io"),
1912+
Kind: "InClusterIPPool",
1913+
Name: poolName,
1914+
},
17601915
},
1761-
Spec: ipamv1.IPAddressSpec{},
17621916
}
1917+
Expect(k8sClient.Create(context.Background(), &claim)).To(Succeed())
1918+
Eventually(Get(&claim)).Should(Succeed())
17631919

1764-
Eventually(Object(&address)).
1765-
WithTimeout(time.Second).WithPolling(100 * time.Millisecond).Should(
1766-
EqualObject(&expectedIPAddress, IgnoreAutogeneratedMetadata, IgnoreUIDsOnIPAddress),
1767-
)
1920+
addresses := ipamv1.IPAddressList{}
1921+
Consistently(ObjectList(&addresses)).
1922+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1923+
HaveField("Items", HaveLen(0)))
1924+
1925+
// update the cluster
1926+
delete(cluster.Annotations, clusterv1.PausedAnnotation)
1927+
Expect(k8sClient.Update(context.Background(), &cluster)).To(Succeed())
1928+
1929+
Eventually(ObjectList(&addresses)).
1930+
WithTimeout(5 * time.Second).WithPolling(100 * time.Millisecond).Should(
1931+
HaveField("Items", HaveLen(1)))
17681932
})
17691933
})
17701934

0 commit comments

Comments
 (0)