Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ linters:
- linters:
- errcheck
text: "conf.UnsetEnv|conf.SetEnv" # these are used and unchecked in over 280 test files
# disable package deprecation for aws-sdk-go until https://jira.cms.gov/browse/BCDA-9484 is finished
- linters:
- staticcheck
text: "aws-sdk-go"
#- end disable for BCDA-9484
formatters:
enable:
- gofmt
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"go.testEnvVars": {
"ENV": "local",
"LOCAL_STACK_ENDPOINT": "http://localhost:4566",
"AWS_ENDPOINT_URL": "http://localhost:4566",
"DB": "postgresql://postgres:toor@localhost:15432",
"DB_HOST_URL": "postgresql://postgres:toor@localhost:15432?sslmode=disable",
"TEST_DB_URL": "postgresql://postgres:toor@localhost:15432/bcda_test?sslmode=disable",
Expand Down
49 changes: 49 additions & 0 deletions bcda/aws/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package bcdaaws
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this from its own package to under our aws helpers package.


import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
)

type Sampler struct {
Ctx context.Context
Namespace string
Unit string
Service *cloudwatch.Client
}

func PutMetricSample(
ctx context.Context,
namespace string,
name string,
unit types.StandardUnit,
value float64,
dimensions []types.Dimension,
) error {
data := types.MetricDatum{
Dimensions: dimensions,
MetricName: &name,
Unit: unit,
Value: &value,
}

input := &cloudwatch.PutMetricDataInput{
MetricData: []types.MetricDatum{data},
Namespace: aws.String(namespace),
}

cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
return err
}

client := cloudwatch.NewFromConfig(cfg)

_, err = client.PutMetricData(ctx, input)

return err
}
21 changes: 21 additions & 0 deletions bcda/aws/metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package bcdaaws

import (
"testing"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
"github.com/stretchr/testify/assert"
)

func TestPutMetricSample(t *testing.T) {
err := PutMetricSample(
t.Context(),
"Namespace",
"Name",
"Count",
float64(32),
[]types.Dimension{{Name: aws.String("name"), Value: aws.String("value")}},
)
assert.Nil(t, err)
}
34 changes: 12 additions & 22 deletions bcda/aws/parameters.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
package bcdaaws

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go-v2/service/ssm"
)

// Makes this easier to mock and unit test
var ssmNew = ssm.New
var ssmsvcGetParameter = (*ssm.SSM).GetParameter
var ssmsvcGetParameters = (*ssm.SSM).GetParameters

func GetParameter(s *session.Session, keyname string) (string, error) {
ssmsvc := ssmNew(s)

// Returns the value of a single parameter from the SSM Parameter Store
func GetParameter(ctx context.Context, client *ssm.Client, keyname string) (string, error) {
withDecryption := true
result, err := ssmsvcGetParameter(ssmsvc, &ssm.GetParameterInput{
result, err := client.GetParameter(ctx, &ssm.GetParameterInput{
Name: &keyname,
WithDecryption: &withDecryption,
})

if err != nil {
return "", fmt.Errorf("error retrieving parameter %s from parameter store: %w", keyname, err)
}

val := *result.Parameter.Value

if val == "" {
return "", fmt.Errorf("no parameter store value found for %s", keyname)
}
Expand All @@ -35,12 +27,9 @@ func GetParameter(s *session.Session, keyname string) (string, error) {
}

// Returns a list of parameters from the SSM Parameter Store
func GetParameters(s *session.Session, keynames []*string) (map[string]string, error) {
// Create an SSM client and pull down keys from the param store
ssmsvc := ssmNew(s)

func GetParameters(ctx context.Context, client *ssm.Client, keynames []string) (map[string]string, error) {
withDecryption := true
params, err := ssmsvcGetParameters(ssmsvc, &ssm.GetParametersInput{
output, err := client.GetParameters(ctx, &ssm.GetParametersInput{
Names: keynames,
WithDecryption: &withDecryption,
})
Expand All @@ -49,19 +38,20 @@ func GetParameters(s *session.Session, keynames []*string) (map[string]string, e
}

// Unknown keys will come back as invalid, make sure we error on them
if len(params.InvalidParameters) > 0 {
if len(output.InvalidParameters) > 0 {
invalidParamsStr := ""
for i := 0; i < len(params.InvalidParameters); i++ {
invalidParamsStr += fmt.Sprintf("%s,\n", *params.InvalidParameters[i])
for i := 0; i < len(output.InvalidParameters); i++ {
invalidParamsStr += fmt.Sprintf("%s,\n", output.InvalidParameters[i])
}
return nil, fmt.Errorf("invalid parameters error: %s", invalidParamsStr)
}

// Build the parameter map that we're going to return
paramMap := make(map[string]string)

for _, item := range params.Parameters {
for _, item := range output.Parameters {
paramMap[*item.Name] = *item.Value
}

return paramMap, nil
}
135 changes: 38 additions & 97 deletions bcda/aws/parameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,146 +2,87 @@ package bcdaaws

import (
"errors"
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/CMSgov/bcda-app/bcda/testUtils"
"github.com/stretchr/testify/assert"
)

func TestGetParameter(t *testing.T) {
key1 := "key1"
parm1 := "parm1"
val1 := "val1"
cleanupParam1 := testUtils.SetParameter(t, key1, val1)
defer cleanupParam1()

tests := []struct {
keyname string
expectedValue string
expectedErr error
ssmNew func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM
ssmsvcGetParameter func(c *ssm.SSM, input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error)
desc string
keyname string
expectedValue string
expectedErr error
}{
{
// Happy path
desc: "Happy path",
keyname: key1,
expectedValue: parm1,
expectedValue: val1,
expectedErr: nil,
ssmNew: func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM { return nil },
ssmsvcGetParameter: func(c *ssm.SSM, input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) {
parm := ssm.Parameter{
Name: &key1, Value: &parm1,
}
getParametersOutput := ssm.GetParameterOutput{Parameter: &parm}
return &getParametersOutput, nil
},
},
{
// GetParameter fails
keyname: key1,
expectedValue: "",
expectedErr: errors.New("error retrieving parameter key1 from parameter store: error"),
ssmNew: func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM { return nil },
ssmsvcGetParameter: func(c *ssm.SSM, input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) {
return nil, errors.New("error")
},
},
{
// Empty parameter
keyname: key1,
desc: "Missing parameter",
keyname: "asdf",
expectedValue: "",
expectedErr: fmt.Errorf("no parameter store value found for %s", key1),
ssmNew: func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM { return nil },
ssmsvcGetParameter: func(c *ssm.SSM, input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) {
val := ""
parm := ssm.Parameter{
Name: &key1, Value: &val,
}

getParameterOutput := ssm.GetParameterOutput{Parameter: &parm}
return &getParameterOutput, nil
},
expectedErr: errors.New("error retrieving parameter asdf from parameter store"),
},
}

client := testUtils.TestSSMClient(t, testUtils.TestAWSConfig(t))
for _, test := range tests {
ssmNew = test.ssmNew
ssmsvcGetParameter = test.ssmsvcGetParameter

value, err := GetParameter(nil, test.keyname)
value, err := GetParameter(t.Context(), client, test.keyname)
assert.Equal(t, test.expectedValue, value)

if test.expectedErr == nil {
assert.Nil(t, err)
} else {
assert.Equal(t, test.expectedErr.Error(), err.Error())
assert.Contains(t, err.Error(), test.expectedErr.Error())
}
}
}

func TestGetParameters(t *testing.T) {
key1 := "key1"
key2 := "key2"
parm1 := "parm1"
parm2 := "parm2"
val1 := "val1"
val2 := "val2"

cleanupParam1 := testUtils.SetParameter(t, key1, val1)
cleanupParam2 := testUtils.SetParameter(t, key2, val2)
defer cleanupParam1()
defer cleanupParam2()

tests := []struct {
keys []*string
parms map[string]string
err error
ssmNew func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM
ssmsvcGetParameters func(c *ssm.SSM, input *ssm.GetParametersInput) (*ssm.GetParametersOutput, error)
desc string
keys []string
vals map[string]string
err error
}{
{
// Happy path
keys: []*string{&key1, &key2},
parms: map[string]string{key1: parm1, key2: parm2},
err: nil,
ssmNew: func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM { return nil },
ssmsvcGetParameters: func(c *ssm.SSM, input *ssm.GetParametersInput) (*ssm.GetParametersOutput, error) {
parms := []*ssm.Parameter{
{Name: &key1, Value: &parm1},
{Name: &key2, Value: &parm2},
}
getParametersOutput := ssm.GetParametersOutput{Parameters: parms}
return &getParametersOutput, nil
},
},
{
// GetParameters fails
keys: []*string{&key1, &key2},
parms: nil,
err: errors.New("error connecting to parameter store: error"),
ssmNew: func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM { return nil },
ssmsvcGetParameters: func(c *ssm.SSM, input *ssm.GetParametersInput) (*ssm.GetParametersOutput, error) {
return nil, errors.New("error")
},
desc: "Happy path",
keys: []string{key1, key2},
vals: map[string]string{key1: val1, key2: val2},
err: nil,
},
{
// Invalid parameter
keys: []*string{&key1, &key2},
parms: nil,
err: fmt.Errorf("invalid parameters error: %s,\n", key2),
ssmNew: func(p client.ConfigProvider, cfgs ...*aws.Config) *ssm.SSM { return nil },
ssmsvcGetParameters: func(c *ssm.SSM, input *ssm.GetParametersInput) (*ssm.GetParametersOutput, error) {
parms := []*ssm.Parameter{
{Name: &key1, Value: &parm1},
}
invalidParms := []*string{&key2}

getParametersOutput := ssm.GetParametersOutput{Parameters: parms, InvalidParameters: invalidParms}
return &getParametersOutput, nil
},
desc: "Invalid parameter",
keys: []string{"invalid", key2},
vals: nil,
err: errors.New("invalid parameters error: invalid,\n"),
},
}

client := testUtils.TestSSMClient(t, testUtils.TestAWSConfig(t))
for _, test := range tests {
ssmNew = test.ssmNew
ssmsvcGetParameters = test.ssmsvcGetParameters

parms, err := GetParameters(nil, test.keys)
vals, err := GetParameters(t.Context(), client, test.keys)

assert.Equal(t, test.parms, parms)
assert.Equal(t, test.vals, vals)
assert.Equal(t, test.err, err)
}
}
43 changes: 0 additions & 43 deletions bcda/aws/session.go
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWS session is no longer a thing in v2. Instead each service creates a client for itself using AWS config.

This file was deleted.

Loading
Loading