Skip to content

Commit

Permalink
Merge pull request #6 from mumoshu/fix-s3-metrics-test
Browse files Browse the repository at this point in the history
Fix S3 metrics test to actually test the correct code path
  • Loading branch information
cw-atkhry authored Sep 6, 2024
2 parents 0e55358 + 8076a44 commit 2636144
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 7 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,16 @@ jobs:
install-awslocal: 'true'
- name: Run tests
run: go test -v ./...
env:
# localstack requires these environment variables
AWS_DEFAULT_REGION: ap-northeast-1
# Credentials are important for localstack
# Without them, the tests will fail like:
# operation error S3: CreateBucket, get identity: get credentials: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, failed to get API token, operation error ec2imds: getToken, http response error StatusCode: 400, request to EC2 IMDS failed
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
# These environment variables are required by main and main_test
# Without them, the tests will fail like:
# operation error S3: CreateBucket, exceeded maximum number of attempts, 3, https response error StatusCode: 500, RequestID: 346f5995-bbe8-41e2-be03-3a6ab0ad5edd, HostID: s9lzHYrFp76ZVxRcpX9+5cjAnEH2ROuNkd2BHfIa6UkFVdtjf5mKR3/eTPFvsiP/XV/VLi31234=, api error InternalError: exception while calling s3 with unknown operation: Unable to find operation for request to service s3: PUT /
S3_BUCKET: mybucket
S3_KEY: mykey
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
golang.org/x/sys v0.17.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/sys v0.21.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,37 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
91 changes: 89 additions & 2 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/cw-sakamoto/sample/localstack"
"github.com/prometheus/common/expfmt"
"github.com/stretchr/testify/require"
)

Expand All @@ -25,10 +29,17 @@ func TestSigint(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

awsConfig, err := config.LoadDefaultConfig(ctx)
require.NoError(t, err)

s3EndpointResolver := localstack.S3EndpointResolver()

setupS3BucketAndObject(t, ctx, awsConfig, s3EndpointResolver)

go func() {
runErr <- Run(ContextWithSignal(ctx, sigs), func(c *checker) {
// Use localstack for S3
c.s3Opts = append(c.s3Opts, s3.WithEndpointResolverV2(localstack.S3EndpointResolver()))
c.s3Opts = append(c.s3Opts, s3.WithEndpointResolverV2(s3EndpointResolver))
})

cancel()
Expand All @@ -55,7 +66,38 @@ func TestSigint(t *testing.T) {
// m is the metrics in the Prometheus exposition format,
// expectedly containing the aws_request_duration_seconds metric.
// We can check the presence of any metric here, in any detail.
require.Contains(t, m, "promhttp_metric_handler_requests_total")

p := expfmt.TextParser{}
mf, err := p.TextToMetricFamilies(strings.NewReader(m))
require.NoError(t, err)

mt, ok := mf["aws_request_duration_seconds"]
require.True(t, ok)

type labels struct {
service, method, status string
}

mm := make(map[labels]struct{})

for _, m := range mt.Metric {
t.Logf("Metric: %v", m)
var labels labels
for _, l := range m.Label {
switch *l.Name {
case "service":
labels.service = *l.Value
case "method":
labels.method = *l.Value
case "status":
labels.status = *l.Value
}
}
mm[labels] = struct{}{}
}

require.Len(t, mm, 1)
require.Contains(t, mm, labels{"S3", "GetObject", "Success"})
case <-time.After(2 * time.Second):
// We assume that the server is expected to start and expose metrics within 2 seconds.
// Otherwise, we consider it as a failure, and you may need to fix the server implementation,
Expand All @@ -75,6 +117,51 @@ func TestSigint(t *testing.T) {
}
}

// Put s3 object for testing
func setupS3BucketAndObject(t *testing.T, ctx context.Context, awsConfig aws.Config, s3EndpointResolver s3.EndpointResolverV2) {
s3Client := s3.NewFromConfig(awsConfig, s3.WithEndpointResolverV2(s3EndpointResolver))

// We assume that S3_BUCKET and S3_KEY are set in the environment variables
// before running the tests.
s3Bucket := os.Getenv("S3_BUCKET")
s3Key := os.Getenv("S3_KEY")

_, err := s3Client.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: &s3Bucket,
// LocationConstraint is required when AWS_DEFAULT_REGION is not us-east-1
// Otherwise, you will get the following error:
// IllegalLocationConstraintException: The unspecified location constraint is incompatible for the region specific endpoint this request was sent to.
CreateBucketConfiguration: &s3types.CreateBucketConfiguration{
LocationConstraint: s3types.BucketLocationConstraint(os.Getenv("AWS_DEFAULT_REGION")),
},
})
require.NoError(t, err)
t.Cleanup(func() {
_, err = s3Client.DeleteBucket(context.Background(), &s3.DeleteBucketInput{
Bucket: &s3Bucket,
})
if err != nil {
t.Logf("Error: %v", err)
}
})

_, err = s3Client.PutObject(ctx, &s3.PutObjectInput{
Bucket: &s3Bucket,
Key: &s3Key,
Body: strings.NewReader("hello"),
})
require.NoError(t, err)
t.Cleanup(func() {
_, err := s3Client.DeleteObject(context.Background(), &s3.DeleteObjectInput{
Bucket: &s3Bucket,
Key: &s3Key,
})
if err != nil {
t.Logf("Error: %v", err)
}
})
}

func httpGetStr(t *testing.T, url string) string {
resp, err := http.Get(url)
if err != nil {
Expand Down

0 comments on commit 2636144

Please sign in to comment.