Skip to content

Commit

Permalink
adding pemContents and errs for defer funcs
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardfward committed Nov 30, 2024
1 parent 1e095ed commit 8fec658
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 17 deletions.
9 changes: 9 additions & 0 deletions bindings/mysql/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ metadata:
description: "Path to the PEM file. Used with SSL connection"
example: '"path/to/pem/file"'
type: string
- name: pemContents
required: false
description: "Base64-encoded PEM file contents. Used with SSL connection. Supersedes pemPath if both provided."
example: '"-----BEGIN CERTIFICATE-----
MIIFaDCCBFCgAwIBAgISESHkvZFwK9Qz0KsXD3x8p44aMA0GCSqGSIb3DQEBCwUA
...
bml6YXRpb252YWxzaGEyZzIuY3JsMIGgBggrBgEFBQcBAQSBkzCBkDBNBggrBgEF
-----END CERTIFICATE-----"'
type: string
- name: maxIdleConns
required: false
description: "The max idle connections. Integer greater than 0"
Expand Down
46 changes: 33 additions & 13 deletions bindings/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ type mysqlMetadata struct {
// PemPath is the path to the pem file to connect to MySQL over SSL.
PemPath string `mapstructure:"pemPath"`

// PemContents is the contents of the pem file to connect to MySQL over SSL.
// PemContents supersedes PemPath if both are provided.
PemContents string `mapstructure:"pemContents"`

// MaxIdleConns is the maximum number of connections in the idle connection pool.
MaxIdleConns int `mapstructure:"maxIdleConns"`

Expand Down Expand Up @@ -117,7 +121,19 @@ func (m *Mysql) Init(ctx context.Context, md bindings.Metadata) error {
return errors.New("missing MySql connection string")
}

m.db, err = initDB(meta.URL, meta.PemPath)
var pemContents []byte

// meta.PemContents supersedes meta.PemPath if both are provided.
if meta.PemContents != "" {
pemContents = []byte(meta.PemContents)
} else if meta.PemPath != "" {
pemContents, err = os.ReadFile(meta.PemPath)
if err != nil {
return fmt.Errorf("unable to read pem file: %w", err)
}
}

m.db, err = initDB(meta.URL, pemContents)
if err != nil {
return err
}
Expand Down Expand Up @@ -234,7 +250,9 @@ func (m *Mysql) Close() error {
}

if m.db != nil {
m.db.Close()
if err := m.db.Close(); err != nil {
m.logger.Warnf("error closing DB: %v", err)
}
m.db = nil
}

Expand All @@ -246,7 +264,12 @@ func (m *Mysql) query(ctx context.Context, sql string, params ...any) ([]byte, e
if err != nil {
return nil, fmt.Errorf("error executing query: %w", err)
}
defer rows.Close()

defer func() {
if err = rows.Close(); err != nil {
m.logger.Warnf("error closing rows: %v", err)
}
}()

result, err := m.jsonify(rows)
if err != nil {
Expand All @@ -265,21 +288,15 @@ func (m *Mysql) exec(ctx context.Context, sql string, params ...any) (int64, err
return res.RowsAffected()
}

func initDB(url, pemPath string) (*sql.DB, error) {
func initDB(url string, pemContents []byte) (*sql.DB, error) {
conf, err := mysql.ParseDSN(url)
if err != nil {
return nil, fmt.Errorf("illegal Data Source Name (DSN) specified by %s", connectionURLKey)
}

if pemPath != "" {
var pem []byte
if len(pemContents) != 0 {
rootCertPool := x509.NewCertPool()
pem, err = os.ReadFile(pemPath)
if err != nil {
return nil, fmt.Errorf("error reading PEM file from %s: %w", pemPath, err)
}

ok := rootCertPool.AppendCertsFromPEM(pem)
ok := rootCertPool.AppendCertsFromPEM(pemContents)
if !ok {
return nil, errors.New("failed to append PEM")
}
Expand Down Expand Up @@ -373,6 +390,9 @@ func (m *Mysql) convert(columnTypes []*sql.ColumnType, values []any) map[string]
// GetComponentMetadata returns the metadata of the component.
func (m *Mysql) GetComponentMetadata() (metadataInfo metadata.MetadataMap) {
metadataStruct := mysqlMetadata{}
metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo, metadata.BindingType)
if err := metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo, metadata.BindingType); err != nil {
m.logger.Warnf("error retrieving metadata info: %v", err)
}

return
}
6 changes: 5 additions & 1 deletion bindings/mysql/mysql_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ func TestMysqlIntegration(t *testing.T) {
err := b.Init(context.Background(), m)
require.NoError(t, err)

defer b.Close()
defer func() {
if err = b.Close(); err != nil {
t.Errorf("failed to close database: %s", err)
}
}()

t.Run("Invoke create table", func(t *testing.T) {
res, err := b.Invoke(context.Background(), &bindings.InvokeRequest{
Expand Down
22 changes: 19 additions & 3 deletions bindings/mysql/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ import (

func TestQuery(t *testing.T) {
m, mock, _ := mockDatabase(t)
defer m.Close()

defer func() {
if err := m.Close(); err != nil {
t.Errorf("failed to close database: %s", err)
}
}()

t.Run("no dbType provided", func(t *testing.T) {
rows := sqlmock.NewRows([]string{"id", "value", "timestamp"}).
Expand Down Expand Up @@ -83,7 +88,13 @@ func TestQuery(t *testing.T) {

func TestExec(t *testing.T) {
m, mock, _ := mockDatabase(t)
defer m.Close()

defer func() {
if err := m.Close(); err != nil {
t.Errorf("failed to close database: %s", err)
}
}()

mock.ExpectExec("INSERT INTO foo \\(id, v1, ts\\) VALUES \\(.*\\)").WillReturnResult(sqlmock.NewResult(1, 1))
i, err := m.exec(context.Background(), "INSERT INTO foo (id, v1, ts) VALUES (1, 'test-1', '2021-01-22')")
assert.Equal(t, int64(1), i)
Expand All @@ -92,7 +103,12 @@ func TestExec(t *testing.T) {

func TestInvoke(t *testing.T) {
m, mock, _ := mockDatabase(t)
defer m.Close()

defer func() {
if err := m.Close(); err != nil {
t.Errorf("failed to close database: %s", err)
}
}()

t.Run("exec operation succeeds", func(t *testing.T) {
mock.ExpectExec("INSERT INTO foo \\(id, v1, ts\\) VALUES \\(.*\\)").WillReturnResult(sqlmock.NewResult(1, 1))
Expand Down

0 comments on commit 8fec658

Please sign in to comment.