Skip to content

Commit 6462b88

Browse files
Add Limit and Continue functional list options for client
1 parent 320b6b6 commit 6462b88

File tree

2 files changed

+169
-1
lines changed

2 files changed

+169
-1
lines changed

pkg/client/client_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,89 @@ var _ = Describe("Client", func() {
17051705
close(done)
17061706
}, serverSideTimeoutSeconds)
17071707

1708+
It("should filter results using limit and continue options", func() {
1709+
1710+
makeDeployment := func(suffix string) *appsv1.Deployment {
1711+
return &appsv1.Deployment{
1712+
ObjectMeta: metav1.ObjectMeta{
1713+
Name: fmt.Sprintf("deployment-%s", suffix),
1714+
},
1715+
Spec: appsv1.DeploymentSpec{
1716+
Selector: &metav1.LabelSelector{
1717+
MatchLabels: map[string]string{"foo": "bar"},
1718+
},
1719+
Template: corev1.PodTemplateSpec{
1720+
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar"}},
1721+
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}},
1722+
},
1723+
},
1724+
}
1725+
}
1726+
1727+
By("creating 4 deployments")
1728+
dep1 := makeDeployment("1")
1729+
dep1, err := clientset.AppsV1().Deployments(ns).Create(dep1)
1730+
Expect(err).NotTo(HaveOccurred())
1731+
defer deleteDeployment(dep1, ns)
1732+
1733+
dep2 := makeDeployment("2")
1734+
dep2, err = clientset.AppsV1().Deployments(ns).Create(dep2)
1735+
Expect(err).NotTo(HaveOccurred())
1736+
defer deleteDeployment(dep2, ns)
1737+
1738+
dep3 := makeDeployment("3")
1739+
dep3, err = clientset.AppsV1().Deployments(ns).Create(dep3)
1740+
Expect(err).NotTo(HaveOccurred())
1741+
defer deleteDeployment(dep3, ns)
1742+
1743+
dep4 := makeDeployment("4")
1744+
dep4, err = clientset.AppsV1().Deployments(ns).Create(dep4)
1745+
Expect(err).NotTo(HaveOccurred())
1746+
defer deleteDeployment(dep4, ns)
1747+
1748+
cl, err := client.New(cfg, client.Options{})
1749+
Expect(err).NotTo(HaveOccurred())
1750+
1751+
By("listing 1 deployment when limit=1 is used")
1752+
deps := &appsv1.DeploymentList{}
1753+
err = cl.List(context.Background(), deps,
1754+
client.Limit(1),
1755+
)
1756+
Expect(err).NotTo(HaveOccurred())
1757+
1758+
Expect(deps.Items).To(HaveLen(1))
1759+
Expect(deps.Continue).NotTo(BeEmpty())
1760+
Expect(deps.Items[0].Name).To(Equal(dep1.Name))
1761+
1762+
continueToken := deps.Continue
1763+
1764+
By("listing the next deployment when previous continuation token is used and limit=1")
1765+
deps = &appsv1.DeploymentList{}
1766+
err = cl.List(context.Background(), deps,
1767+
client.Limit(1),
1768+
client.Continue(continueToken),
1769+
)
1770+
Expect(err).NotTo(HaveOccurred())
1771+
1772+
Expect(deps.Items).To(HaveLen(1))
1773+
Expect(deps.Continue).NotTo(BeEmpty())
1774+
Expect(deps.Items[0].Name).To(Equal(dep2.Name))
1775+
1776+
continueToken = deps.Continue
1777+
1778+
By("listing the 2 remaining deployments when previous continuation token is used without a limit")
1779+
deps = &appsv1.DeploymentList{}
1780+
err = cl.List(context.Background(), deps,
1781+
client.Continue(continueToken),
1782+
)
1783+
Expect(err).NotTo(HaveOccurred())
1784+
1785+
Expect(deps.Items).To(HaveLen(2))
1786+
Expect(deps.Continue).To(BeEmpty())
1787+
Expect(deps.Items[0].Name).To(Equal(dep3.Name))
1788+
Expect(deps.Items[1].Name).To(Equal(dep4.Name))
1789+
}, serverSideTimeoutSeconds)
1790+
17081791
PIt("should fail if the object doesn't have meta", func() {
17091792

17101793
})
@@ -2078,11 +2161,15 @@ var _ = Describe("Client", func() {
20782161
client.MatchingField("field1", "bar"),
20792162
client.InNamespace("test-namespace"),
20802163
client.MatchingLabels{"foo": "bar"},
2164+
client.Limit(1),
2165+
client.Continue("foo"),
20812166
})
20822167
mlo := lo.AsListOptions()
20832168
Expect(mlo).NotTo(BeNil())
20842169
Expect(mlo.LabelSelector).To(Equal("foo=bar"))
20852170
Expect(mlo.FieldSelector).To(Equal("field1=bar"))
2171+
Expect(mlo.Limit).To(Equal(int64(1)))
2172+
Expect(mlo.Continue).To(Equal("foo"))
20862173
})
20872174

20882175
It("should be populated by MatchingLabels", func() {
@@ -2105,6 +2192,58 @@ var _ = Describe("Client", func() {
21052192
Expect(lo).NotTo(BeNil())
21062193
Expect(lo.Namespace).To(Equal("test"))
21072194
})
2195+
2196+
It("should be populated by Limit", func() {
2197+
lo := &client.ListOptions{}
2198+
client.Limit(1).ApplyToList(lo)
2199+
Expect(lo).NotTo(BeNil())
2200+
Expect(lo.Limit).To(Equal(int64(1)))
2201+
})
2202+
2203+
It("should ignore Limit when converted to metav1.ListOptions and watch is true", func() {
2204+
lo := &client.ListOptions{
2205+
Raw: &metav1.ListOptions{Watch: true},
2206+
}
2207+
lo.ApplyOptions([]client.ListOption{
2208+
client.Limit(1),
2209+
})
2210+
mlo := lo.AsListOptions()
2211+
Expect(mlo).NotTo(BeNil())
2212+
Expect(mlo.Limit).To(BeZero())
2213+
})
2214+
2215+
It("should be populated by Continue", func() {
2216+
lo := &client.ListOptions{}
2217+
client.Continue("foo").ApplyToList(lo)
2218+
Expect(lo).NotTo(BeNil())
2219+
Expect(lo.Continue).To(Equal("foo"))
2220+
})
2221+
2222+
It("should ignore Continue token when converted to metav1.ListOptions and watch is true", func() {
2223+
lo := &client.ListOptions{
2224+
Raw: &metav1.ListOptions{Watch: true},
2225+
}
2226+
lo.ApplyOptions([]client.ListOption{
2227+
client.Continue("foo"),
2228+
})
2229+
mlo := lo.AsListOptions()
2230+
Expect(mlo).NotTo(BeNil())
2231+
Expect(mlo.Continue).To(BeEmpty())
2232+
})
2233+
2234+
It("should ignore both Limit and Continue token when converted to metav1.ListOptions and watch is true", func() {
2235+
lo := &client.ListOptions{
2236+
Raw: &metav1.ListOptions{Watch: true},
2237+
}
2238+
lo.ApplyOptions([]client.ListOption{
2239+
client.Limit(1),
2240+
client.Continue("foo"),
2241+
})
2242+
mlo := lo.AsListOptions()
2243+
Expect(mlo).NotTo(BeNil())
2244+
Expect(mlo.Limit).To(BeZero())
2245+
Expect(mlo.Continue).To(BeEmpty())
2246+
})
21082247
})
21092248

21102249
Describe("UpdateOptions", func() {

pkg/client/options.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,20 @@ type ListOptions struct {
249249
// non-namespaced objects, or to list across all namespaces.
250250
Namespace string
251251

252+
// Limit specifies the maximum number of results to return from the server. The server may
253+
// not support this field on all resource types, but if it does and more results remain it
254+
// will set the continue field on the returned list object. This field is not supported if watch
255+
// is true in the Raw ListOptions.
256+
Limit int64
257+
// Continue is a token returned by the server that lets a client retrieve chunks of results
258+
// from the server by specifying limit. The server may reject requests for continuation tokens
259+
// it does not recognize and will return a 410 error if the token can no longer be used because
260+
// it has expired. This field is not supported if watch is true in the Raw ListOptions.
261+
Continue string
262+
252263
// Raw represents raw ListOptions, as passed to the API server. Note
253264
// that these may not be respected by all implementations of interface,
254-
// and the LabelSelector and FieldSelector fields are ignored.
265+
// and the LabelSelector, FieldSelector, Limit and Continue fields are ignored.
255266
Raw *metav1.ListOptions
256267
}
257268

@@ -270,6 +281,10 @@ func (o *ListOptions) AsListOptions() *metav1.ListOptions {
270281
if o.FieldSelector != nil {
271282
o.Raw.FieldSelector = o.FieldSelector.String()
272283
}
284+
if !o.Raw.Watch {
285+
o.Raw.Limit = o.Limit
286+
o.Raw.Continue = o.Continue
287+
}
273288
return o.Raw
274289
}
275290

@@ -316,6 +331,20 @@ func (n InNamespace) ApplyToList(opts *ListOptions) {
316331
opts.Namespace = string(n)
317332
}
318333

334+
// Limit specifies the maximum number of results to return from the server.
335+
type Limit int64
336+
337+
func (l Limit) ApplyToList(opts *ListOptions) {
338+
opts.Limit = int64(l)
339+
}
340+
341+
// Continue sets a continuation token to retrieve chunks of results when using limit.
342+
type Continue string
343+
344+
func (c Continue) ApplyToList(opts *ListOptions) {
345+
opts.Continue = string(c)
346+
}
347+
319348
// }}}
320349

321350
// {{{ Update Options

0 commit comments

Comments
 (0)