-
-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New retriever for s3 that supports go-aws-sdk-v2 SDK (#990)
* Update openfeature_javascript.mdx * change doc Signed-off-by: Thomas Poignant <[email protected]> * Use v2 in relay proxy Signed-off-by: Thomas Poignant <[email protected]> --------- Signed-off-by: Thomas Poignant <[email protected]>
- Loading branch information
1 parent
0c2c622
commit dd2a703
Showing
9 changed files
with
233 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package s3retrieverv2 | ||
|
||
import ( | ||
"context" | ||
"github.com/aws/aws-sdk-go-v2/feature/s3/manager" | ||
"github.com/aws/aws-sdk-go-v2/service/s3" | ||
"io" | ||
) | ||
|
||
// DownloaderAPI provides methods to manage downloads to an S3 bucket. | ||
type DownloaderAPI interface { | ||
Download(ctx context.Context, w io.WriterAt, input *s3.GetObjectInput, options ...func(*manager.Downloader)) ( | ||
n int64, err error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package s3retrieverv2 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/aws/aws-sdk-go-v2/aws" | ||
"github.com/aws/aws-sdk-go-v2/config" | ||
"github.com/aws/aws-sdk-go-v2/feature/s3/manager" | ||
"github.com/aws/aws-sdk-go-v2/service/s3" | ||
"os" | ||
"sync" | ||
) | ||
|
||
// Retriever is a configuration struct for a S3 retriever. | ||
type Retriever struct { | ||
// Bucket is the name of your S3 Bucket. | ||
Bucket string | ||
|
||
// Item is the path to your flag file in your bucket. | ||
Item string | ||
|
||
// AwsConfig is the AWS SDK configuration object we will use to | ||
// download your feature flag configuration file. | ||
AwsConfig *aws.Config | ||
|
||
// downloader is an internal field, it is the downloader use by the AWS-SDK | ||
downloader DownloaderAPI | ||
init sync.Once | ||
} | ||
|
||
func (s *Retriever) Retrieve(ctx context.Context) ([]byte, error) { | ||
if s.downloader == nil { | ||
initErr := s.initializeDownloader(ctx) | ||
if initErr != nil { | ||
return nil, initErr | ||
} | ||
} | ||
|
||
// Download the item from the bucket. | ||
// If an error occurs, log it and exit. | ||
// Otherwise, notify the user that the download succeeded. | ||
file, err := os.CreateTemp("", "go_feature_flag") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
s3Req := &s3.GetObjectInput{ | ||
Bucket: aws.String(s.Bucket), | ||
Key: aws.String(s.Item), | ||
} | ||
_, err = s.downloader.Download(ctx, file, s3Req) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to download item from S3 %q, %v", s.Item, err) | ||
} | ||
// Read file content | ||
content, err := os.ReadFile(file.Name()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return content, nil | ||
} | ||
|
||
func (s *Retriever) initializeDownloader(ctx context.Context) error { | ||
var initErr error | ||
s.init.Do(func() { | ||
if s.AwsConfig == nil { | ||
cfg, err := config.LoadDefaultConfig(ctx) | ||
if err != nil { | ||
initErr = fmt.Errorf("impossible to init S3 retriever: %v", err) | ||
return | ||
} | ||
s.AwsConfig = &cfg | ||
} | ||
client := s3.NewFromConfig(*s.AwsConfig) | ||
s.downloader = manager.NewDownloader(client) | ||
}) | ||
return initErr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package s3retrieverv2 | ||
|
||
import ( | ||
"context" | ||
"github.com/aws/aws-sdk-go-v2/config" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/thomaspoignant/go-feature-flag/testutils" | ||
"os" | ||
"testing" | ||
) | ||
|
||
func Test_s3Retriever_Retrieve(t *testing.T) { | ||
type fields struct { | ||
downloader DownloaderAPI | ||
bucket string | ||
item string | ||
context context.Context | ||
} | ||
tests := []struct { | ||
name string | ||
fields fields | ||
want string | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "File on S3", | ||
fields: fields{ | ||
downloader: &testutils.S3ManagerV2Mock{ | ||
TestDataLocation: "./testdata", | ||
}, | ||
bucket: "Bucket", | ||
item: "valid", | ||
}, | ||
want: "./testdata/flag-config.yaml", | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "File not present S3", | ||
fields: fields{ | ||
downloader: &testutils.S3ManagerV2Mock{ | ||
TestDataLocation: "./testdata", | ||
}, | ||
bucket: "Bucket", | ||
item: "no-file", | ||
}, | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "File on S3 with context", | ||
fields: fields{ | ||
downloader: &testutils.S3ManagerV2Mock{ | ||
TestDataLocation: "./testdata", | ||
}, | ||
bucket: "Bucket", | ||
item: "valid", | ||
context: context.Background(), | ||
}, | ||
want: "./testdata/flag-config.yaml", | ||
wantErr: false, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
awsConf, _ := config.LoadDefaultConfig(context.TODO()) | ||
s := Retriever{ | ||
Bucket: tt.fields.bucket, | ||
Item: tt.fields.item, | ||
AwsConfig: &awsConf, | ||
downloader: tt.fields.downloader, | ||
} | ||
got, err := s.Retrieve(tt.fields.context) | ||
assert.Equal(t, tt.wantErr, err != nil, "Retrieve() error = %v, wantErr %v", err, tt.wantErr) | ||
if err == nil { | ||
want, err := os.ReadFile(tt.want) | ||
assert.NoError(t, err) | ||
assert.Equal(t, string(want), string(got), "Retrieve() got = %v, want %v", string(want), string(got)) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
test-flag: | ||
rule: key eq "random-key" | ||
percentage: 100 | ||
true: true | ||
false: false | ||
default: false | ||
|
||
test-flag2: | ||
rule: key eq "not-a-key" | ||
percentage: 100 | ||
true: true | ||
false: false | ||
default: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters