Merge release 1.15 to main (#3790)

Signed-off-by: Anton Troshin <anton@diagrid.io>
Signed-off-by: joshvanl <me@joshvanl.dev>
Signed-off-by: yaron2 <schneider.yaron@live.com>
Signed-off-by: Cassandra Coyle <cassie@diagrid.io>
Co-authored-by: Josh van Leeuwen <me@joshvanl.dev>
Co-authored-by: Yaron Schneider <schneider.yaron@live.com>
Co-authored-by: Cassie Coyle <cassie@diagrid.io>
This commit is contained in:
Anton Troshin 2025-07-31 09:45:54 -05:00 committed by Cassandra Coyle
parent adc76bd6ec
commit 8fc16f24f3
No known key found for this signature in database
6 changed files with 161 additions and 27 deletions

View File

@ -110,13 +110,7 @@ func (g *GCPStorage) Init(ctx context.Context, metadata bindings.Metadata) error
return err
}
b, err := json.Marshal(m)
if err != nil {
return err
}
clientOptions := option.WithCredentialsJSON(b)
client, err := storage.NewClient(ctx, clientOptions)
client, err := g.getClient(ctx, m)
if err != nil {
return err
}
@ -127,6 +121,41 @@ func (g *GCPStorage) Init(ctx context.Context, metadata bindings.Metadata) error
return nil
}
func (g *GCPStorage) getClient(ctx context.Context, m *gcpMetadata) (*storage.Client, error) {
var client *storage.Client
var err error
if m.Bucket == "" {
return nil, errors.New("missing property `bucket` in metadata")
}
if m.ProjectID == "" {
return nil, errors.New("missing property `project_id` in metadata")
}
// Explicit authentication
if m.PrivateKeyID != "" {
var b []byte
b, err = json.Marshal(m)
if err != nil {
return nil, err
}
clientOptions := option.WithCredentialsJSON(b)
client, err = storage.NewClient(ctx, clientOptions)
if err != nil {
return nil, err
}
} else {
// Implicit authentication, using GCP Application Default Credentials (ADC)
// Credentials search order: https://cloud.google.com/docs/authentication/application-default-credentials#order
client, err = storage.NewClient(ctx)
if err != nil {
return nil, err
}
}
return client, nil
}
func (g *GCPStorage) parseMetadata(meta bindings.Metadata) (*gcpMetadata, error) {
m := gcpMetadata{}
err := kitmd.DecodeMetadata(meta.Properties, &m)

View File

@ -15,6 +15,7 @@ package bucket
import (
"encoding/json"
"errors"
"testing"
"github.com/stretchr/testify/assert"
@ -234,6 +235,30 @@ func TestMergeWithRequestMetadata(t *testing.T) {
})
}
func TestInit(t *testing.T) {
t.Run("Init missing bucket from metadata", func(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{
"projectID": "my_project_id",
}
gs := GCPStorage{logger: logger.NewLogger("test")}
err := gs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `bucket` in metadata"))
})
t.Run("Init missing projectID from metadata", func(t *testing.T) {
m := bindings.Metadata{}
m.Properties = map[string]string{
"bucket": "my_bucket",
}
gs := GCPStorage{logger: logger.NewLogger("test")}
err := gs.Init(t.Context(), m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `project_id` in metadata"))
})
}
func TestGetOption(t *testing.T) {
gs := GCPStorage{logger: logger.NewLogger("test")}
gs.metadata = &gcpMetadata{}

View File

@ -88,12 +88,38 @@ func (s *Store) Init(ctx context.Context, metadataRaw secretstores.Metadata) err
}
func (s *Store) getClient(ctx context.Context, metadata *GcpSecretManagerMetadata) (*secretmanager.Client, error) {
b, _ := json.Marshal(metadata)
clientOptions := option.WithCredentialsJSON(b)
var client *secretmanager.Client
var err error
client, err := secretmanager.NewClient(ctx, clientOptions)
if err != nil {
return nil, err
if metadata.ProjectID == "" {
return nil, errors.New("missing property `project_id` in metadata")
}
// Explicit authentication
if metadata.PrivateKeyID != "" {
if metadata.Type == "" {
return nil, errors.New("missing property `type` in metadata")
}
if metadata.PrivateKey == "" {
return nil, errors.New("missing property `private_key` in metadata")
}
if metadata.ClientEmail == "" {
return nil, errors.New("missing property `client_email` in metadata")
}
b, _ := json.Marshal(metadata)
clientOptions := option.WithCredentialsJSON(b)
client, err = secretmanager.NewClient(ctx, clientOptions)
if err != nil {
return nil, err
}
} else {
// Implicit authentication, using GCP Application Default Credentials (ADC)
// Credentials search order: https://cloud.google.com/docs/authentication/application-default-credentials#order
client, err = secretmanager.NewClient(ctx)
if err != nil {
return nil, err
}
}
return client, nil
@ -183,18 +209,9 @@ func (s *Store) parseSecretManagerMetadata(metadataRaw secretstores.Metadata) (*
return nil, fmt.Errorf("failed to decode metadata: %w", err)
}
if meta.Type == "" {
return nil, errors.New("missing property `type` in metadata")
}
if meta.ProjectID == "" {
return nil, errors.New("missing property `project_id` in metadata")
}
if meta.PrivateKey == "" {
return nil, errors.New("missing property `private_key` in metadata")
}
if meta.ClientEmail == "" {
return nil, errors.New("missing property `client_email` in metadata")
}
return &meta, nil
}

View File

@ -76,11 +76,38 @@ func TestInit(t *testing.T) {
t.Run("Init with missing `type` metadata", func(t *testing.T) {
m.Properties = map[string]string{
"dummy": "a",
"dummy": "a",
"private_key_id": "a",
"project_id": "a",
}
err := sm.Init(ctx, m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `type` in metadata"))
assert.Equal(t, errors.New("failed to setup secretmanager client: missing property `type` in metadata"), err)
})
t.Run("Init with missing `private_key` metadata", func(t *testing.T) {
m.Properties = map[string]string{
"dummy": "a",
"private_key_id": "a",
"type": "a",
"project_id": "a",
}
err := sm.Init(ctx, m)
require.Error(t, err)
assert.Equal(t, errors.New("failed to setup secretmanager client: missing property `private_key` in metadata"), err)
})
t.Run("Init with missing `client_email` metadata", func(t *testing.T) {
m.Properties = map[string]string{
"dummy": "a",
"private_key_id": "a",
"private_key": "a",
"type": "a",
"project_id": "a",
}
err := sm.Init(ctx, m)
require.Error(t, err)
assert.Equal(t, errors.New("failed to setup secretmanager client: missing property `client_email` in metadata"), err)
})
t.Run("Init with missing `project_id` metadata", func(t *testing.T) {
@ -91,6 +118,22 @@ func TestInit(t *testing.T) {
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `project_id` in metadata"))
})
t.Run("Init with missing `project_id` metadata", func(t *testing.T) {
m.Properties = map[string]string{
"type": "service_account",
}
err := sm.Init(ctx, m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `project_id` in metadata"))
})
t.Run("Init with empty metadata", func(t *testing.T) {
m.Properties = map[string]string{}
err := sm.Init(ctx, m)
require.Error(t, err)
assert.Equal(t, err, errors.New("missing property `project_id` in metadata"))
})
}
func TestGetSecret(t *testing.T) {

View File

@ -16,6 +16,7 @@ package tablestore
import (
"bytes"
"encoding/binary"
"sync"
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
)
@ -24,6 +25,7 @@ type mockClient struct {
tablestore.TableStoreClient
data map[string][]byte
mu sync.RWMutex
}
func (m *mockClient) DeleteRow(request *tablestore.DeleteRowRequest) (*tablestore.DeleteRowResponse, error) {
@ -36,7 +38,9 @@ func (m *mockClient) DeleteRow(request *tablestore.DeleteRowRequest) (*tablestor
}
}
m.mu.Lock()
delete(m.data, key)
m.mu.Unlock()
return nil, nil
}
@ -51,7 +55,9 @@ func (m *mockClient) GetRow(request *tablestore.GetRowRequest) (*tablestore.GetR
}
}
m.mu.RLock()
val := m.data[key]
m.mu.RUnlock()
resp := &tablestore.GetRowResponse{
Columns: []*tablestore.AttributeColumn{{
@ -87,7 +93,9 @@ func (m *mockClient) UpdateRow(req *tablestore.UpdateRowRequest) (*tablestore.Up
}
}
m.mu.Lock()
m.data[key] = val
m.mu.Unlock()
return nil, nil
}
@ -97,6 +105,7 @@ func (m *mockClient) BatchGetRow(request *tablestore.BatchGetRowRequest) (*table
TableToRowsResult: map[string][]tablestore.RowResult{},
}
m.mu.RLock()
for _, criteria := range request.MultiRowQueryCriteria {
tableRes := resp.TableToRowsResult[criteria.TableName]
if tableRes == nil {
@ -136,12 +145,14 @@ func (m *mockClient) BatchGetRow(request *tablestore.BatchGetRowRequest) (*table
}
}
}
m.mu.RUnlock()
return resp, nil
}
func (m *mockClient) BatchWriteRow(request *tablestore.BatchWriteRowRequest) (*tablestore.BatchWriteRowResponse, error) {
resp := &tablestore.BatchWriteRowResponse{}
m.mu.Lock()
for _, changes := range request.RowChangesGroupByTable {
for _, change := range changes {
switch inst := change.(type) {
@ -174,6 +185,7 @@ func (m *mockClient) BatchWriteRow(request *tablestore.BatchWriteRowRequest) (*t
}
}
}
m.mu.Unlock()
return resp, nil
}

View File

@ -514,8 +514,16 @@ func (o *oracleDatabaseAccess) ensureStateTable(stateTableName string) error {
}
func tableExists(db *sql.DB, tableName string) (bool, error) {
var tblCount int32
err := db.QueryRow("SELECT count(table_name) tbl_count FROM user_tables WHERE table_name = upper(:tablename)", tableName).Scan(&tblCount)
exists := tblCount > 0
return exists, err
//nolint:gosec
query := fmt.Sprintf("SELECT 1 FROM %s WHERE ROWNUM = 1", tableName)
var dummy int
err := db.QueryRow(query).Scan(&dummy)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return true, nil // Table exists but is empty
}
return false, nil // Likely a table does not exist error
}
return true, nil
}