Skip to content

Commit

Permalink
Merge pull request #169 from btnguyen2k/pr-review
Browse files Browse the repository at this point in the history
Merged PR "sql.Open with aws.Config"
  • Loading branch information
btnguyen2k authored May 2, 2024
2 parents 8d852fc + b07fbc2 commit 3ee93c3
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 12 deletions.
4 changes: 1 addition & 3 deletions .semrelease/this_release
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
# This file has been cleaned up post-releasing version 1.2.1.
# Generate its content quickly using the following command:
# git log origin..HEAD | grep "^\s" > .semrelease/this_release
New feature: sql.Open with aws.Config
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,42 @@ Region=<aws-region>
- `Endpoint`: (optional) AWS DynamoDB endpoint, for example `http://localhost:8000`; useful when AWS DynamoDB is running on local machine.
- `TimeoutMs`: (optional) timeout in milliseconds. If not specified, default value is `10000`.

## Using `aws.Config`:

Since <<VERSION>>, `godynamo` supports using `aws.Config` to create the connection to DynamoDB:

```go
package main

import (
"database/sql"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/btnguyen2k/godynamo"
)

func main() {
driver := "godynamo"
awscfg := aws.Config{
Region: "<aws-region>",
Credentials: aws.StaticCredentialsProvider{
Value: aws.Credentials{
AccessKeyID: "<access-key-id>",
SecretAccessKey: "<secret-key>",
},
},
}
godynamo.RegisterAWSConfig(awscfg)

db, err := sql.Open(driver, "dummy")
if err != nil {
panic(err)
}
defer db.Close()

// db instance is ready to use
}
```

## Supported statements:

- [Table](SQL_TABLE.md):
Expand Down
54 changes: 54 additions & 0 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"reflect"
"strings"
"sync"
"time"

"github.com/aws/aws-sdk-go-v2/aws/transport/http"
Expand Down Expand Up @@ -93,5 +94,58 @@ func (d *Driver) Open(connStr string) (driver.Conn, error) {
}
}
client := dynamodb.New(opts)

awsConfigLock.RLock()
defer awsConfigLock.RUnlock()
conf := awsConfig
if conf != nil {
client = dynamodb.NewFromConfig(*conf, mergeDynamoDBOptions(opts))

Check warning on line 102 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L98-L102

Added lines #L98 - L102 were not covered by tests
}

return &Conn{client: client, timeout: time.Duration(timeoutMs) * time.Millisecond}, nil
}

// awsConfig is the AWS configuration to be used by the dynamodb client.
var (
awsConfigLock = &sync.RWMutex{}
awsConfig *aws.Config
)

// RegisterAWSConfig registers aws.Config to be used by the dynamodb client.
//
// The following configurations do not apply even if they are set in aws.Config.
// - HTTPClient
//
// @Available since <<VERSION>>
func RegisterAWSConfig(conf aws.Config) {
awsConfigLock.Lock()
defer awsConfigLock.Unlock()
awsConfig = &conf

Check warning on line 123 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L120-L123

Added lines #L120 - L123 were not covered by tests
}

// DeregisterAWSConfig removes the registered aws.Config.
//
// @Available since <<VERSION>>
func DeregisterAWSConfig() {
awsConfigLock.Lock()
defer awsConfigLock.Unlock()
awsConfig = nil

Check warning on line 132 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L129-L132

Added lines #L129 - L132 were not covered by tests
}

// mergeDynamoDBOptions merges the provided dynamodb.Options into the default dynamodb.Options.
func mergeDynamoDBOptions(providedOpts dynamodb.Options) func(*dynamodb.Options) {
return func(defaultOpts *dynamodb.Options) {
if defaultOpts.Region == "" {
defaultOpts.Region = providedOpts.Region

Check warning on line 139 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L136-L139

Added lines #L136 - L139 were not covered by tests
}
if defaultOpts.Credentials == nil {
defaultOpts.Credentials = providedOpts.Credentials

Check warning on line 142 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L141-L142

Added lines #L141 - L142 were not covered by tests
}
defaultOpts.HTTPClient = providedOpts.HTTPClient

Check warning on line 144 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L144

Added line #L144 was not covered by tests

if defaultOpts.BaseEndpoint == nil {
defaultOpts.BaseEndpoint = providedOpts.BaseEndpoint
defaultOpts.EndpointOptions = providedOpts.EndpointOptions

Check warning on line 148 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L146-L148

Added lines #L146 - L148 were not covered by tests
}
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

require (
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2/credentials v1.17.8
github.com/aws/aws-sdk-go-v2/credentials v1.17.11
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.31.1
github.com/aws/smithy-go v1.20.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/credentials v1.17.8 h1:WUdNLXbyNbU07V/WFrSOBXqZTDgmmMNMgUFzpYOKJhw=
github.com/aws/aws-sdk-go-v2/credentials v1.17.8/go.mod h1:iPZzLpaBIfhyvVS/XGD3JvR1GP3YdHTqpySKDlqkfs8=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11 h1:nyWawIVs7Y75DuNhh6vao/qmKKWS56zUuWt/+dOE5iI=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11/go.mod h1:5WPGXfp9+ss7gYsZ5QjJeY16qTpCLaIcQItE7Yw7ld4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
Expand Down
2 changes: 1 addition & 1 deletion module_test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ replace github.com/btnguyen2k/godynamo => ../

require (
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2/credentials v1.17.11
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.31.1
github.com/aws/smithy-go v1.20.2
github.com/btnguyen2k/consu/reddo v0.1.9
Expand All @@ -14,7 +15,6 @@ require (
)

require (
github.com/aws/aws-sdk-go-v2/credentials v1.17.8 // indirect
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
Expand Down
4 changes: 2 additions & 2 deletions module_test/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/credentials v1.17.8 h1:WUdNLXbyNbU07V/WFrSOBXqZTDgmmMNMgUFzpYOKJhw=
github.com/aws/aws-sdk-go-v2/credentials v1.17.8/go.mod h1:iPZzLpaBIfhyvVS/XGD3JvR1GP3YdHTqpySKDlqkfs8=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11 h1:nyWawIVs7Y75DuNhh6vao/qmKKWS56zUuWt/+dOE5iI=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11/go.mod h1:5WPGXfp9+ss7gYsZ5QjJeY16qTpCLaIcQItE7Yw7ld4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
Expand Down
86 changes: 86 additions & 0 deletions module_test/godynamo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/btnguyen2k/consu/reddo"
"github.com/btnguyen2k/godynamo"
"os"
Expand Down Expand Up @@ -35,6 +38,66 @@ func Test_OpenDatabase(t *testing.T) {
}
}

func Test_OpenDatabase_With_AWSConfig_Endpoint(t *testing.T) {
testName := "Test_OpenDatabase_With_AWSConfig_Endpoint"
dbdriver := "godynamo"

dsnEndpoint := "http://1.2.3.4:1234/"
dsn := fmt.Sprintf("Region=dummy-region;AkId=dummy-key-id;SecretKey=dummy-key;Endpoint=%s", dsnEndpoint)

{
// without AWSConfig
db, err := sql.Open(dbdriver, dsn)
if err != nil {
t.Fatalf("%s failed: %s", testName+"/open", err)
}
_, err = db.QueryContext(context.Background(), "LIST TABLES")
if err == nil {
t.Fatalf("%s failed: expected error", testName+"/query")
}
if strings.Index(err.Error(), fmt.Sprintf(`"%s"`, dsnEndpoint)) < 0 {
t.Fatalf("%s failed: expected error message to contain [%s], but received [%s]", testName, dsnEndpoint, err)
}
}

defer godynamo.DeregisterAWSConfig()

// with AWSConfig
cfgEndpoint := "http://5.6.7.8:5678/"
godynamo.RegisterAWSConfig(aws.Config{
BaseEndpoint: aws.String(cfgEndpoint),
})
{
db, err := sql.Open(dbdriver, dsn)
if err != nil {
t.Fatalf("%s failed: %s", testName+"/open", err)
}
_, err = db.QueryContext(context.Background(), "LIST TABLES")
if err == nil {
t.Fatalf("%s failed: expected error", testName+"/query")
}
if strings.Index(err.Error(), fmt.Sprintf(`"%s"`, cfgEndpoint)) < 0 {
t.Fatalf("%s failed: expected error message to contain [%s], but received [%s]", testName, cfgEndpoint, err)
}
}

// with empty AWSConfig
godynamo.RegisterAWSConfig(aws.Config{})
{
db, err := sql.Open(dbdriver, dsn)
if err != nil {
t.Fatalf("%s failed: %s", testName+"/open", err)
}
_, err = db.QueryContext(context.Background(), "LIST TABLES")
if err == nil {
t.Fatalf("%s failed: expected error", testName+"/query")
}
if strings.Index(err.Error(), fmt.Sprintf(`"%s"`, dsnEndpoint)) < 0 {
t.Fatalf("%s failed: expected error message to contain [%s], but received [%s]", testName, dsnEndpoint, err)
}
}
}

func TestConn_ValuesToNamedValues(t *testing.T) {
testName := "TestConn_ValuesToNamedValues"
values := []driver.Value{1, "2", true}
Expand Down Expand Up @@ -111,3 +174,26 @@ func TestDriver_Close(t *testing.T) {
t.Fatalf("%s failed: %s", testName, err)
}
}

func TestDriver_Open_With_AWSConfig(t *testing.T) {
testName := "TestDriver_Open_With_AWSConfig"
godynamo.RegisterAWSConfig(aws.Config{
Region: "us-west-2",
Credentials: credentials.NewStaticCredentialsProvider(
"abcdefg123456789", "abcdefg123456789", ""),
})
defer godynamo.DeregisterAWSConfig()
db := _openDb(t, testName)
defer func() { _ = db.Close() }()
if err := db.Ping(); err != nil {
t.Fatalf("%s failed: %s", testName, err)
}

// with empty aws.Config
godynamo.RegisterAWSConfig(aws.Config{})
dbWithEmptyAWSConfig := _openDb(t, testName)
defer func() { _ = dbWithEmptyAWSConfig.Close() }()
if err := dbWithEmptyAWSConfig.Ping(); err != nil {
t.Fatalf("%s failed: %s", testName, err)
}
}
2 changes: 1 addition & 1 deletion module_test_real/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (

require (
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.8 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
Expand Down
4 changes: 2 additions & 2 deletions module_test_real/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/credentials v1.17.8 h1:WUdNLXbyNbU07V/WFrSOBXqZTDgmmMNMgUFzpYOKJhw=
github.com/aws/aws-sdk-go-v2/credentials v1.17.8/go.mod h1:iPZzLpaBIfhyvVS/XGD3JvR1GP3YdHTqpySKDlqkfs8=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11 h1:nyWawIVs7Y75DuNhh6vao/qmKKWS56zUuWt/+dOE5iI=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.11/go.mod h1:5WPGXfp9+ss7gYsZ5QjJeY16qTpCLaIcQItE7Yw7ld4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
Expand Down

0 comments on commit 3ee93c3

Please sign in to comment.