Skip to content

Commit f387118

Browse files
committed
feat: added pagination cache config
1 parent b469c05 commit f387118

File tree

8 files changed

+242
-139
lines changed

8 files changed

+242
-139
lines changed

bluemix/configuration/config_helpers/helpers.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,6 @@ func ConfigDir() string {
2121
return defaultConfigDirOld()
2222
}
2323

24-
// func MigrateFromOldConfig() error {
25-
// new := defaultConfigDirNew()
26-
// if file_helpers.FileExists(new) {
27-
// return nil
28-
// }
29-
30-
// old := defaultConfigDirOld()
31-
// if !file_helpers.FileExists(old) {
32-
// return nil
33-
// }
34-
35-
// if err := file_helpers.CopyDir(old, new); err != nil {
36-
// return err
37-
// }
38-
// return os.RemoveAll(old)
39-
// }
40-
4124
func defaultConfigDirNew() string {
4225
return filepath.Join(homeDir(), ".ibmcloud")
4326
}

bluemix/configuration/config_helpers/helpers_test.go

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -103,82 +103,3 @@ func TestConfigDir_IbmCloudConfigHomeSet_Exists(t *testing.T) {
103103
os.Setenv("IBMCLOUD_CONFIG_HOME", userHome)
104104
assert.Equal(userHome, ConfigDir())
105105
}
106-
107-
// func TestMigrateFromOldConfig(t *testing.T) {
108-
// assert := assert.New(t)
109-
110-
// err := prepareBluemixHome()
111-
// assert.NoError(err)
112-
// defer clearBluemixHome()
113-
114-
// err = os.MkdirAll(oldConfigDir(), 0700)
115-
// assert.NoError(err)
116-
// oldConfigPath := filepath.Join(oldConfigDir(), "config.json")
117-
// err = ioutil.WriteFile(oldConfigPath, []byte("old"), 0600)
118-
// assert.NoError(err)
119-
120-
// err = MigrateFromOldConfig()
121-
// assert.NoError(err)
122-
123-
// newConfigPath := filepath.Join(newConfigDir(), "config.json")
124-
// assert.True(file_helpers.FileExists(newConfigPath))
125-
// content, err := ioutil.ReadFile(newConfigPath)
126-
// assert.NoError(err)
127-
// assert.Equal([]byte("old"), content, "should copy old config file")
128-
129-
// assert.False(file_helpers.FileExists(oldConfigDir()), "old config dir should be deleted")
130-
// }
131-
132-
// func TestMigrateFromOldConfig_NewConfigExist(t *testing.T) {
133-
// assert := assert.New(t)
134-
135-
// err := prepareBluemixHome()
136-
// assert.NoError(err)
137-
// defer clearBluemixHome()
138-
139-
// err = os.MkdirAll(oldConfigDir(), 0700)
140-
// assert.NoError(err)
141-
// oldConfigPath := filepath.Join(oldConfigDir(), "config.json")
142-
// err = ioutil.WriteFile(oldConfigPath, []byte("old"), 0600)
143-
// assert.NoError(err)
144-
145-
// err = os.MkdirAll(newConfigDir(), 0700)
146-
// assert.NoError(err)
147-
// newConfigPath := filepath.Join(newConfigDir(), "config.json")
148-
// err = ioutil.WriteFile(newConfigPath, []byte("new"), 0600)
149-
// assert.NoError(err)
150-
151-
// err = MigrateFromOldConfig()
152-
// assert.NoError(err)
153-
154-
// content, err := ioutil.ReadFile(newConfigPath)
155-
// assert.NoError(err)
156-
// assert.Equal([]byte("new"), content, "should not copy old config file")
157-
// }
158-
159-
// func TestMigrateFromOldConfig_OldConfigNotExist(t *testing.T) {
160-
// assert := assert.New(t)
161-
162-
// err := prepareBluemixHome()
163-
// assert.NoError(err)
164-
// defer clearBluemixHome()
165-
166-
// err = MigrateFromOldConfig()
167-
// assert.NoError(err)
168-
// }
169-
170-
// func prepareBluemixHome() error {
171-
// temp, err := ioutil.TempDir("", "IBMCloudSDKConfigTest")
172-
// if err != nil {
173-
// return err
174-
// }
175-
// os.Setenv("BLUEMIX_HOME", temp)
176-
// return nil
177-
// }
178-
179-
// func clearBluemixHome() {
180-
// if homeDir := os.Getenv("BLUEMIX_HOME"); homeDir != "" {
181-
// os.RemoveAll(homeDir)
182-
// os.Unsetenv("BLUEMIX_HOME")
183-
// }
184-
// }

bluemix/configuration/core_config/bx_config.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package core_config
22

33
import (
44
"encoding/json"
5+
"sort"
56
"strings"
67
"sync"
78
"time"
@@ -63,6 +64,7 @@ type BXConfigData struct {
6364
UpdateCheckInterval time.Duration
6465
UpdateRetryCheckInterval time.Duration
6566
UpdateNotificationInterval time.Duration
67+
PaginationURLs []models.PaginationURL
6668
raw raw
6769
}
6870

@@ -752,9 +754,47 @@ func (c *bxConfig) ClearSession() {
752754
c.data.IsLoggedInAsCRI = false
753755
c.data.ResourceGroup = models.ResourceGroup{}
754756
c.data.LoginAt = time.Time{}
757+
c.data.PaginationURLs = []models.PaginationURL{}
755758
})
756759
}
757760

761+
func (c *bxConfig) SetPaginationURLs(paginationURLs []models.PaginationURL) {
762+
c.write(func() {
763+
c.data.PaginationURLs = paginationURLs
764+
})
765+
}
766+
767+
func (c *bxConfig) ClearPaginationURLs() {
768+
c.write(func() {
769+
c.data.PaginationURLs = []models.PaginationURL{}
770+
})
771+
}
772+
773+
func (c *bxConfig) AddPaginationURL(index int, url string) error {
774+
urls, err := c.PaginationURLs()
775+
if err != nil {
776+
return err
777+
}
778+
779+
urls = append(urls, models.PaginationURL{
780+
LastIndex: index,
781+
NextURL: url,
782+
})
783+
784+
// sort by last index for easier retrieval
785+
sort.Sort(models.ByLastIndex(urls))
786+
c.SetPaginationURLs(urls)
787+
return nil
788+
}
789+
790+
func (c *bxConfig) PaginationURLs() (paginationURLs []models.PaginationURL, err error) {
791+
c.read(func() {
792+
paginationURLs = c.data.PaginationURLs
793+
})
794+
795+
return
796+
}
797+
758798
func (c *bxConfig) UnsetAPI() {
759799
c.write(func() {
760800
c.data.APIEndpoint = ""

bluemix/configuration/core_config/bx_config_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,34 @@ func TestLastUpdateSessionTime(t *testing.T) {
469469

470470
}
471471

472+
func TestPaginationURLs(t *testing.T) {
473+
config := prepareConfigForCLI(`{}`, t)
474+
475+
// check initial state
476+
paginationURLs, err := config.PaginationURLs()
477+
assert.Nil(t, err)
478+
assert.Empty(t, paginationURLs)
479+
480+
// update session
481+
expected := []models.PaginationURL{
482+
{
483+
NextURL: "https://api.example.com?token=dd3784000d9744acb2a23ad121a7bb4b",
484+
LastIndex: 50,
485+
},
486+
}
487+
err = config.SetPaginationURLs(expected)
488+
assert.Nil(t, err)
489+
490+
paginationURLs, err = config.PaginationURLs()
491+
assert.Nil(t, err)
492+
assert.Equal(t, 1, len(paginationURLs))
493+
assert.Equal(t, expected[0].LastIndex, paginationURLs[0].LastIndex)
494+
assert.Equal(t, expected[0].NextURL, paginationURLs[0].NextURL)
495+
496+
t.Cleanup(cleanupConfigFiles)
497+
498+
}
499+
472500
func checkUsageStats(enabled bool, timeStampExist bool, config core_config.Repository, t *testing.T) {
473501
assert.Equal(t, config.UsageStatsEnabled(), enabled)
474502
assert.Equal(t, config.UsageStatsEnabledLastUpdate().IsZero(), !timeStampExist)

bluemix/configuration/core_config/repository.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ type Repository interface {
125125

126126
SetLastSessionUpdateTime()
127127
LastSessionUpdateTime() (session int64)
128+
129+
SetPaginationURLs(paginationURLs []models.PaginationURL)
130+
ClearPaginationURLs()
131+
AddPaginationURL(lastIndex int, nextURL string) error
132+
PaginationURLs() ([]models.PaginationURL, error)
128133
}
129134

130135
// Deprecated
@@ -368,6 +373,22 @@ func (c repository) SetLastSessionUpdateTime() {
368373
c.bxConfig.SetLastSessionUpdateTime()
369374
}
370375

376+
func (c repository) PaginationURLs() ([]models.PaginationURL, error) {
377+
return c.bxConfig.PaginationURLs()
378+
}
379+
380+
func (c repository) AddPaginationURL(index int, url string) error {
381+
return c.bxConfig.AddPaginationURL(index, url)
382+
}
383+
384+
func (c repository) SetPaginationURLs(paginationURLs []models.PaginationURL) {
385+
c.bxConfig.SetPaginationURLs(paginationURLs)
386+
}
387+
388+
func (c repository) ClearPaginationURLs() {
389+
c.bxConfig.ClearPaginationURLs()
390+
}
391+
371392
func NewCoreConfig(errHandler func(error)) ReadWriter {
372393
// config_helpers.MigrateFromOldConfig() // error ignored
373394
return NewCoreConfigFromPath(config_helpers.CFConfigFilePath(), config_helpers.ConfigFilePath(), errHandler)

bluemix/models/pagination.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package models
2+
3+
// ByLastIndex sorts PaginationURLs by LastIndex
4+
type ByLastIndex []PaginationURL
5+
6+
func (a ByLastIndex) Len() int { return len(a) }
7+
8+
func (a ByLastIndex) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
9+
10+
func (a ByLastIndex) Less(i, j int) bool { return a[i].LastIndex < a[j].LastIndex }
11+
12+
type PaginationURL struct {
13+
LastIndex int
14+
NextURL string
15+
}

common/rest/request.go

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,45 @@
11
// Request examples:
2-
// // create a simple GET request
3-
// req := GetRequest("http://www.example.com")
42
//
5-
// // set header
6-
// req.Set("Accept", "application/json")
3+
// // create a simple GET request
4+
// req := GetRequest("http://www.example.com")
75
//
8-
// // set query parameters
9-
// req.Query("foo1", "bar1")
10-
// req.Query("foo2", "bar2")
6+
// // set header
7+
// req.Set("Accept", "application/json")
118
//
12-
// // Build to a HTTP request
13-
// req.Build()
9+
// // set query parameters
10+
// req.Query("foo1", "bar1")
11+
// req.Query("foo2", "bar2")
1412
//
15-
// // method chaining is also supported
16-
// // the above is equal to:
17-
// GetRequest("http://www.example.com").
18-
// Set("Accept", "application/json").
19-
// Query("foo1", "bar1").
20-
// Query("foo2", "bar2").
21-
// Build()
13+
// // Build to a HTTP request
14+
// req.Build()
2215
//
23-
// // struct body
24-
// foo = Foo{Bar: "val"}
25-
// PostRequest("http://www.example.com").
26-
// Body(foo)
16+
// // method chaining is also supported
17+
// // the above is equal to:
18+
// GetRequest("http://www.example.com").
19+
// Set("Accept", "application/json").
20+
// Query("foo1", "bar1").
21+
// Query("foo2", "bar2").
22+
// Build()
2723
//
28-
// // String body
29-
// PostRequest("http://www.example.com").
30-
// Body("{\"bar\": \"val\"}")
24+
// // struct body
25+
// foo = Foo{Bar: "val"}
26+
// PostRequest("http://www.example.com").
27+
// Body(foo)
3128
//
32-
// // Stream body
33-
// PostRequest("http://www.example.com").
34-
// Body(strings.NewReader("abcde"))
29+
// // String body
30+
// PostRequest("http://www.example.com").
31+
// Body("{\"bar\": \"val\"}")
3532
//
36-
// // Multipart POST request
37-
// var f *os.File
38-
// PostRequest("http://www.example.com").
39-
// Field("foo", "bar").
40-
// File("file1", File{Name: f.Name(), Content: f}).
41-
// File("file2", File{Name: "1.txt", Content: []byte("abcde"), Type: "text/plain"})
33+
// // Stream body
34+
// PostRequest("http://www.example.com").
35+
// Body(strings.NewReader("abcde"))
36+
//
37+
// // Multipart POST request
38+
// var f *os.File
39+
// PostRequest("http://www.example.com").
40+
// Field("foo", "bar").
41+
// File("file1", File{Name: f.Name(), Content: f}).
42+
// File("file2", File{Name: "1.txt", Content: []byte("abcde"), Type: "text/plain"})
4243
package rest
4344

4445
import (
@@ -51,12 +52,14 @@ import (
5152
"net/textproto"
5253
"net/url"
5354
"strings"
55+
56+
"github.com/IBM-Cloud/ibm-cloud-cli-sdk/bluemix/models"
5457
)
5558

5659
const (
57-
contentType = "Content-Type"
58-
jsonContentType = "application/json"
59-
formUrlEncodedContentType = "application/x-www-form-urlencoded"
60+
ContentType = "Content-Type"
61+
JSONContentType = "application/json"
62+
FormUrlEncodedContentType = "application/x-www-form-urlencoded"
6063
)
6164

6265
// File represents a file upload in HTTP request
@@ -138,6 +141,17 @@ func OptionsRequest(rawUrl string) *Request {
138141
return NewRequest(rawUrl).Method("OPTIONS")
139142
}
140143

144+
// CachedPaginationNextURL will attempt to return a cached URL with last index
145+
// if there exists a URL with a last index smaller than the offset provided
146+
func CachedPaginationNextURL(paginationURLs []models.PaginationURL, offset int) models.PaginationURL {
147+
for _, p := range paginationURLs {
148+
if p.LastIndex < offset {
149+
return p
150+
}
151+
}
152+
return models.PaginationURL{}
153+
}
154+
141155
// Add adds the key, value pair to the request header. It appends to any
142156
// existing values associated with key.
143157
func (r *Request) Add(key string, value string) *Request {
@@ -272,7 +286,7 @@ func (r *Request) buildFormMultipart() (io.Reader, error) {
272286
}
273287
}
274288

275-
r.header.Set(contentType, w.FormDataContentType())
289+
r.header.Set(ContentType, w.FormDataContentType())
276290
return b, nil
277291
}
278292

@@ -296,7 +310,7 @@ func escapeQuotes(s string) string {
296310
}
297311

298312
func (r *Request) buildFormFields() (io.Reader, error) {
299-
r.header.Set(contentType, formUrlEncodedContentType)
313+
r.header.Set(ContentType, FormUrlEncodedContentType)
300314
return strings.NewReader(r.formParams.Encode()), nil
301315
}
302316

0 commit comments

Comments
 (0)