Skip to content

Commit 7cb1940

Browse files
committed
Implement ContainersAll, ContainerNamesAll, ObjectsAll and ObjectNamesAll
These wrap the non All versions using Limit and Marker to read all the items
1 parent 3ba9982 commit 7cb1940

File tree

3 files changed

+236
-2
lines changed

3 files changed

+236
-2
lines changed

notes.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ Rename to go-swift to match user agent string?
1111

1212
Reconnect on auth error - 401 when token expires isn't tested
1313

14-
Implement higher level read all files / containers which uses limit and marker to loop
15-
1614
Make more api compatible with python cloudfiles?
1715

1816
Retry operations on timeout / network errors?

swift.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,64 @@ func (c *Connection) Containers(opts *ContainersOpts) ([]Container, error) {
429429
return containers, err
430430
}
431431

432+
// containersAllOpts makes a copy of opts if set or makes a new one and
433+
// overrides Limit and Marker
434+
func containersAllOpts(opts *ContainersOpts) *ContainersOpts {
435+
var newOpts ContainersOpts
436+
if opts != nil {
437+
newOpts = *opts
438+
}
439+
if newOpts.Limit == 0 {
440+
newOpts.Limit = 10000
441+
}
442+
newOpts.Marker = ""
443+
return &newOpts
444+
}
445+
446+
// ContainersAll is like Containers but it returns all the Containers
447+
//
448+
// It calls Containers multiple times using the Marker parameter
449+
//
450+
// It has a default Limit parameter but you may pass in your own
451+
func (c *Connection) ContainersAll(opts *ContainersOpts) ([]Container, error) {
452+
opts = containersAllOpts(opts)
453+
containers := make([]Container, 0)
454+
for {
455+
newContainers, err := c.Containers(opts)
456+
if err != nil {
457+
return nil, err
458+
}
459+
containers = append(containers, newContainers...)
460+
if len(newContainers) < opts.Limit {
461+
break
462+
}
463+
opts.Marker = newContainers[len(newContainers)-1].Name
464+
}
465+
return containers, nil
466+
}
467+
468+
// ContainerNamesAll is like ContainerNamess but it returns all the Containers
469+
//
470+
// It calls ContainerNames multiple times using the Marker parameter
471+
//
472+
// It has a default Limit parameter but you may pass in your own
473+
func (c *Connection) ContainerNamesAll(opts *ContainersOpts) ([]string, error) {
474+
opts = containersAllOpts(opts)
475+
containers := make([]string, 0)
476+
for {
477+
newContainers, err := c.ContainerNames(opts)
478+
if err != nil {
479+
return nil, err
480+
}
481+
containers = append(containers, newContainers...)
482+
if len(newContainers) < opts.Limit {
483+
break
484+
}
485+
opts.Marker = newContainers[len(newContainers)-1]
486+
}
487+
return containers, nil
488+
}
489+
432490
/* ------------------------------------------------------------ */
433491

434492
// ObjectOpts is options for Objects() and ObjectNames()
@@ -548,6 +606,64 @@ func (c *Connection) Objects(container string, opts *ObjectsOpts) ([]Object, err
548606
return objects, err
549607
}
550608

609+
// objectsAllOpts makes a copy of opts if set or makes a new one and
610+
// overrides Limit and Marker
611+
func objectsAllOpts(opts *ObjectsOpts) *ObjectsOpts {
612+
var newOpts ObjectsOpts
613+
if opts != nil {
614+
newOpts = *opts
615+
}
616+
if newOpts.Limit == 0 {
617+
newOpts.Limit = 10000
618+
}
619+
newOpts.Marker = ""
620+
return &newOpts
621+
}
622+
623+
// ObjectsAll is like Objects but it returns all the Objects
624+
//
625+
// It calls Objects multiple times using the Marker parameter
626+
//
627+
// It has a default Limit parameter but you may pass in your own
628+
func (c *Connection) ObjectsAll(container string, opts *ObjectsOpts) ([]Object, error) {
629+
opts = objectsAllOpts(opts)
630+
objects := make([]Object, 0)
631+
for {
632+
newObjects, err := c.Objects(container, opts)
633+
if err != nil {
634+
return nil, err
635+
}
636+
objects = append(objects, newObjects...)
637+
if len(newObjects) < opts.Limit {
638+
break
639+
}
640+
opts.Marker = newObjects[len(newObjects)-1].Name
641+
}
642+
return objects, nil
643+
}
644+
645+
// ObjectNamesAll is like ObjectNamess but it returns all the Objects
646+
//
647+
// It calls ObjectNames multiple times using the Marker parameter
648+
//
649+
// It has a default Limit parameter but you may pass in your own
650+
func (c *Connection) ObjectNamesAll(container string, opts *ObjectsOpts) ([]string, error) {
651+
opts = objectsAllOpts(opts)
652+
objects := make([]string, 0)
653+
for {
654+
newObjects, err := c.ObjectNames(container, opts)
655+
if err != nil {
656+
return nil, err
657+
}
658+
objects = append(objects, newObjects...)
659+
if len(newObjects) < opts.Limit {
660+
break
661+
}
662+
opts.Marker = newObjects[len(newObjects)-1]
663+
}
664+
return objects, nil
665+
}
666+
551667
// Account contains information about this account.
552668
type Account struct {
553669
BytesUsed int64 // total number of bytes used

swift_test.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,44 @@ func TestContainer(t *testing.T) {
144144
//fmt.Println(headers)
145145
}
146146

147+
func TestContainersAll(t *testing.T) {
148+
containers1, err := c.ContainersAll(nil)
149+
if err != nil {
150+
t.Fatal(err)
151+
}
152+
containers2, err := c.Containers(nil)
153+
if err != nil {
154+
t.Fatal(err)
155+
}
156+
if len(containers1) != len(containers2) {
157+
t.Fatal("Wrong length")
158+
}
159+
for i := range containers1 {
160+
if containers1[i] != containers2[i] {
161+
t.Fatal("Not the same")
162+
}
163+
}
164+
}
165+
166+
func TestContainersAllWithLimit(t *testing.T) {
167+
containers1, err := c.ContainersAll(&swift.ContainersOpts{Limit: 1})
168+
if err != nil {
169+
t.Fatal(err)
170+
}
171+
containers2, err := c.Containers(nil)
172+
if err != nil {
173+
t.Fatal(err)
174+
}
175+
if len(containers1) != len(containers2) {
176+
t.Fatal("Wrong length")
177+
}
178+
for i := range containers1 {
179+
if containers1[i] != containers2[i] {
180+
t.Fatal("Not the same")
181+
}
182+
}
183+
}
184+
147185
func TestContainerUpdate(t *testing.T) {
148186
err := c.ContainerUpdate(CONTAINER, m2.ContainerHeaders())
149187
if err != nil {
@@ -176,6 +214,44 @@ func TestContainerNames(t *testing.T) {
176214
// fmt.Println(containers)
177215
}
178216

217+
func TestContainerNamesAll(t *testing.T) {
218+
containers1, err := c.ContainerNamesAll(nil)
219+
if err != nil {
220+
t.Fatal(err)
221+
}
222+
containers2, err := c.ContainerNames(nil)
223+
if err != nil {
224+
t.Fatal(err)
225+
}
226+
if len(containers1) != len(containers2) {
227+
t.Fatal("Wrong length")
228+
}
229+
for i := range containers1 {
230+
if containers1[i] != containers2[i] {
231+
t.Fatal("Not the same")
232+
}
233+
}
234+
}
235+
236+
func TestContainerNamesAllWithLimit(t *testing.T) {
237+
containers1, err := c.ContainerNamesAll(&swift.ContainersOpts{Limit: 1})
238+
if err != nil {
239+
t.Fatal(err)
240+
}
241+
containers2, err := c.ContainerNames(nil)
242+
if err != nil {
243+
t.Fatal(err)
244+
}
245+
if len(containers1) != len(containers2) {
246+
t.Fatal("Wrong length")
247+
}
248+
for i := range containers1 {
249+
if containers1[i] != containers2[i] {
250+
t.Fatal("Not the same")
251+
}
252+
}
253+
}
254+
179255
func TestObjectPutString(t *testing.T) {
180256
err := c.ObjectPutString(CONTAINER, OBJECT, CONTENTS, "")
181257
if err != nil {
@@ -273,6 +349,28 @@ func TestObjectNames(t *testing.T) {
273349
//fmt.Println(objects)
274350
}
275351

352+
func TestObjectNamesAll(t *testing.T) {
353+
objects, err := c.ObjectNamesAll(CONTAINER, nil)
354+
if err != nil {
355+
t.Fatal(err)
356+
}
357+
if len(objects) != 1 || objects[0] != OBJECT {
358+
t.Error("Incorrect listing", objects)
359+
}
360+
//fmt.Println(objects)
361+
}
362+
363+
func TestObjectNamesAllWithLimit(t *testing.T) {
364+
objects, err := c.ObjectNamesAll(CONTAINER, &swift.ObjectsOpts{Limit: 1})
365+
if err != nil {
366+
t.Fatal(err)
367+
}
368+
if len(objects) != 1 || objects[0] != OBJECT {
369+
t.Error("Incorrect listing", objects)
370+
}
371+
//fmt.Println(objects)
372+
}
373+
276374
func TestObjects(t *testing.T) {
277375
objects, err := c.Objects(CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
278376
if err != nil {
@@ -289,6 +387,28 @@ func TestObjects(t *testing.T) {
289387
// fmt.Println(objects)
290388
}
291389

390+
func TestObjectsAll(t *testing.T) {
391+
objects, err := c.ObjectsAll(CONTAINER, nil)
392+
if err != nil {
393+
t.Fatal(err)
394+
}
395+
if len(objects) != 1 || objects[0].Name != OBJECT {
396+
t.Error("Incorrect listing", objects)
397+
}
398+
//fmt.Println(objects)
399+
}
400+
401+
func TestObjectsAllWithLimit(t *testing.T) {
402+
objects, err := c.ObjectsAll(CONTAINER, &swift.ObjectsOpts{Limit: 1})
403+
if err != nil {
404+
t.Fatal(err)
405+
}
406+
if len(objects) != 1 || objects[0].Name != OBJECT {
407+
t.Error("Incorrect listing", objects)
408+
}
409+
//fmt.Println(objects)
410+
}
411+
292412
func TestObjectNamesWithPath(t *testing.T) {
293413
objects, err := c.ObjectNames(CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: ""})
294414
if err != nil {

0 commit comments

Comments
 (0)