Skip to content

Commit

Permalink
Force to use only one retriever at the time
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Poignant committed Jan 13, 2021
1 parent 74d825d commit 25c65ca
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 100 deletions.
110 changes: 58 additions & 52 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,33 @@ type Config struct {
Logger *log.Logger
Context context.Context // default is context.Background()
LocalFile string
Retriever Retriever
HTTPRetriever *HTTPRetriever
S3Retriever *S3Retriever
GithubRetriever *GithubRetriever
}

// GetRetriever returns a retriever.FlagRetriever configure with the retriever available in the config.
func (c *Config) GetRetriever() (retriever.FlagRetriever, error) {
if c.Retriever == nil {
return nil, errors.New("no retriever in the configuration, impossible to get the flags")
}
return c.Retriever.getFlagRetriever()
}

type Retriever interface {
getFlagRetriever() (retriever.FlagRetriever, error)
}

// FileRetriever is a configuration struct for a local flat file.
type FileRetriever struct {
Path string
}

func (r *FileRetriever) getFlagRetriever() (retriever.FlagRetriever, error) { // nolint: unparam
return retriever.NewLocalRetriever(r.Path), nil
}

// HTTPRetriever is a configuration struct for an HTTP endpoint retriever.
type HTTPRetriever struct {
URL string
Expand All @@ -36,13 +58,46 @@ type HTTPRetriever struct {
Timeout time.Duration
}

func (r *HTTPRetriever) getFlagRetriever() (retriever.FlagRetriever, error) {
timeout := r.Timeout
if timeout <= 0 {
timeout = 10 * time.Second
}

return retriever.NewHTTPRetriever(
&http.Client{
Timeout: timeout,
},
r.URL,
r.Method,
r.Body,
r.Header,
), nil
}

// S3Retriever is a configuration struct for a S3 retriever.
type S3Retriever struct {
Bucket string
Item string
AwsConfig aws.Config
}

func (r *S3Retriever) getFlagRetriever() (retriever.FlagRetriever, error) {
// Create an AWS session
sess, err := session.NewSession(&r.AwsConfig)
if err != nil {
return nil, err
}

// Create a new AWS S3 downloader
downloader := s3manager.NewDownloader(sess)
return retriever.NewS3Retriever(
downloader,
r.Bucket,
r.Item,
), nil
}

// GithubRetriever is a configuration struct for a GitHub retriever.
type GithubRetriever struct {
RepositorySlug string
Expand All @@ -52,40 +107,7 @@ type GithubRetriever struct {
Timeout time.Duration // default is 10 seconds
}

// GetRetriever is used to get the retriever we will use to load the flags file.
func (c *Config) GetRetriever() (retriever.FlagRetriever, error) {
if c.GithubRetriever != nil {
return initGithubRetriever(*c.GithubRetriever)
}

if c.S3Retriever != nil {
// Create an AWS session
sess, err := session.NewSession(&c.S3Retriever.AwsConfig)
if err != nil {
return nil, err
}

// Create a new AWS S3 downloader
downloader := s3manager.NewDownloader(sess)
return retriever.NewS3Retriever(
downloader,
c.S3Retriever.Bucket,
c.S3Retriever.Item,
), nil
}

if c.HTTPRetriever != nil {
return initHTTPRetriever(*c.HTTPRetriever)
}

if c.LocalFile != "" {
return retriever.NewLocalRetriever(c.LocalFile), nil
}
return nil, errors.New("please add a config to get the flag config file")
}

// initGithubRetriever creates a HTTP retriever that allows to get changes from Github.
func initGithubRetriever(r GithubRetriever) (retriever.FlagRetriever, error) {
func (r *GithubRetriever) getFlagRetriever() (retriever.FlagRetriever, error) {
// default branch is main
branch := r.Branch
if branch == "" {
Expand All @@ -104,28 +126,12 @@ func initGithubRetriever(r GithubRetriever) (retriever.FlagRetriever, error) {
branch,
r.FilePath)

return initHTTPRetriever(HTTPRetriever{
httpRetriever := HTTPRetriever{
URL: URL,
Method: http.MethodGet,
Header: header,
Timeout: r.Timeout,
})
}

// initHttpRetriever creates a HTTP retriever
func initHTTPRetriever(r HTTPRetriever) (retriever.FlagRetriever, error) {
timeout := r.Timeout
if timeout <= 0 {
timeout = 10 * time.Second
}

return retriever.NewHTTPRetriever(
&http.Client{
Timeout: timeout,
},
r.URL,
r.Method,
r.Body,
r.Header,
), nil
return httpRetriever.getFlagRetriever()
}
55 changes: 8 additions & 47 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ import (

func TestConfig_GetRetriever(t *testing.T) {
type fields struct {
PollInterval int
LocalFile string
HTTPRetriever *ffClient.HTTPRetriever
S3Retriever *ffClient.S3Retriever
GithubRetriever *ffClient.GithubRetriever
PollInterval int
Retriever ffClient.Retriever
}
tests := []struct {
name string
Expand All @@ -28,7 +25,7 @@ func TestConfig_GetRetriever(t *testing.T) {
name: "File retriever",
fields: fields{
PollInterval: 3,
LocalFile: "file-example.yaml",
Retriever: &ffClient.FileRetriever{Path: "file-example.yaml"},
},
want: "*retriever.localRetriever",
wantErr: false,
Expand All @@ -37,7 +34,7 @@ func TestConfig_GetRetriever(t *testing.T) {
name: "S3 retriever",
fields: fields{
PollInterval: 3,
S3Retriever: &ffClient.S3Retriever{
Retriever: &ffClient.S3Retriever{
Bucket: "tpoi-test",
Item: "test.yaml",
AwsConfig: aws.Config{
Expand All @@ -52,7 +49,7 @@ func TestConfig_GetRetriever(t *testing.T) {
name: "HTTP retriever",
fields: fields{
PollInterval: 3,
HTTPRetriever: &ffClient.HTTPRetriever{
Retriever: &ffClient.HTTPRetriever{
URL: "http://example.com/test.yaml",
Method: http.MethodGet,
},
Expand All @@ -64,7 +61,7 @@ func TestConfig_GetRetriever(t *testing.T) {
name: "Github retriever",
fields: fields{
PollInterval: 3,
GithubRetriever: &ffClient.GithubRetriever{
Retriever: &ffClient.GithubRetriever{
RepositorySlug: "thomaspoignant/go-feature-flag",
FilePath: "testdata/test.yaml",
GithubToken: "XXX",
Expand All @@ -74,39 +71,6 @@ func TestConfig_GetRetriever(t *testing.T) {
want: "*retriever.httpRetriever",
wantErr: false,
},
{
name: "Priority to S3",
fields: fields{
PollInterval: 3,
HTTPRetriever: &ffClient.HTTPRetriever{
URL: "http://example.com/test.yaml",
Method: http.MethodGet,
},
S3Retriever: &ffClient.S3Retriever{
Bucket: "tpoi-test",
Item: "test.yaml",
AwsConfig: aws.Config{
Region: aws.String("eu-west-1"),
},
},
LocalFile: "file-example.yaml",
},
want: "*retriever.s3Retriever",
wantErr: false,
},
{
name: "Priority to HTTP",
fields: fields{
PollInterval: 3,
HTTPRetriever: &ffClient.HTTPRetriever{
URL: "http://example.com/test.yaml",
Method: http.MethodGet,
},
LocalFile: "file-example.yaml",
},
want: "*retriever.httpRetriever",
wantErr: false,
},
{
name: "No retriever",
fields: fields{
Expand All @@ -118,11 +82,8 @@ func TestConfig_GetRetriever(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &ffClient.Config{
PollInterval: tt.fields.PollInterval,
LocalFile: tt.fields.LocalFile,
HTTPRetriever: tt.fields.HTTPRetriever,
S3Retriever: tt.fields.S3Retriever,
GithubRetriever: tt.fields.GithubRetriever,
PollInterval: tt.fields.PollInterval,
Retriever: tt.fields.Retriever,
}
got, err := c.GetRetriever()
assert.Equal(t, tt.wantErr, err != nil)
Expand Down
2 changes: 1 addition & 1 deletion feature_flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestValidUseCase(t *testing.T) {
// Valid use case
err := ffclient.Init(ffclient.Config{
PollInterval: 0,
LocalFile: "testdata/test.yaml",
Retriever: &ffclient.FileRetriever{Path: "testdata/test.yaml"},
})

assert.NoError(t, err)
Expand Down

0 comments on commit 25c65ca

Please sign in to comment.