Skip to content

Commit

Permalink
feat(tests): added some simple test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
stvnksslr committed Sep 12, 2024
1 parent 52ab4cd commit 4d8a005
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
- name: Build
id: docker_build
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
push: false
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/code-quality.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ jobs:
cache: false

- name: Lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v6
with:
version: latest

- name: Test
run: go test

lint-chart:
name: Lint chart

Expand All @@ -39,7 +42,7 @@ jobs:
fetch-depth: 0

- name: Set up Helm
uses: azure/setup-helm@v3
uses: azure/setup-helm@v4
with:
version: v3.12.1

Expand Down
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sqs v1.34.8
github.com/prometheus/client_golang v1.20.3
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
)

require (
Expand All @@ -24,13 +25,18 @@ require (
github.com/aws/smithy-go v1.20.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // 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.6.1 // indirect
github.com/prometheus/common v0.59.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
golang.org/x/sys v0.25.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 @@ -31,13 +31,18 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
Expand All @@ -59,9 +64,13 @@ github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJ
github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand All @@ -71,5 +80,8 @@ golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
42 changes: 27 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ import (
)

// Default to checking queues every 30 seconds
const defaultMonitorInterval = 30
const defaultMonitorInterval = 30 * time.Second

var svc = getSqsClient()
// SQSClientInterface defines the interface for SQS operations we use
type SQSClientInterface interface {
GetQueueAttributes(ctx context.Context, params *sqs.GetQueueAttributesInput, optFns ...func(*sqs.Options)) (*sqs.GetQueueAttributesOutput, error)
}

var svc SQSClientInterface

var monitorInterval = getMonitorInterval()
var monitorInterval time.Duration

var labelNames = []string{"queue"}

Expand All @@ -48,7 +53,7 @@ type queueResult struct {
QueueResults *sqs.GetQueueAttributesOutput
}

func getSqsClient() *sqs.Client {
func getSqsClient() SQSClientInterface {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Error().Str("errorMessage", err.Error()).Msg("error loading AWS config")
Expand All @@ -62,15 +67,15 @@ func getMonitorInterval() time.Duration {
monitorIntervalStr, varSet := os.LookupEnv("SQS_MONITOR_INTERVAL_SECONDS")
if !varSet || monitorIntervalStr == "" {
log.Warn().Msg(fmt.Sprintf("Monitor interval not set, defaulting to %v", defaultMonitorInterval))
return time.Duration(defaultMonitorInterval)
return defaultMonitorInterval
}

monitorInterval, err := strconv.Atoi(monitorIntervalStr)
if err != nil {
log.Error().Str("errorMessage", err.Error()).Msg("bad value for SQS_MONITOR_INTERVAL")
os.Exit(1)
log.Warn().Str("errorMessage", err.Error()).Msg("Invalid value for SQS_MONITOR_INTERVAL, using default")
return defaultMonitorInterval
}
return time.Duration(monitorInterval)
return time.Duration(monitorInterval) * time.Second
}

func monitorQueue(queueURL string, c chan queueResult) {
Expand All @@ -89,7 +94,8 @@ func monitorQueue(queueURL string, c chan queueResult) {
resp, err := svc.GetQueueAttributes(context.TODO(), params)
if err != nil {
log.Error().Str("errorMessage", err.Error()).Msg("error checking queue")
os.Exit(1)
c <- queueResult{queueURL, queueName, nil} // Send a result with nil QueueResults to indicate error
return
}

c <- queueResult{queueURL, queueName, resp}
Expand All @@ -104,6 +110,9 @@ func monitorQueues(queueUrls []string) {

for i := 0; i < len(queueUrls); i++ {
queueResult := <-c
if queueResult.QueueResults == nil {
continue // Skip this queue if there was an error
}
for attrib := range queueResult.QueueResults.Attributes {
prop := queueResult.QueueResults.Attributes[attrib]
nMessages, _ := strconv.ParseFloat(prop, 64)
Expand All @@ -115,18 +124,17 @@ func monitorQueues(queueUrls []string) {
case "ApproximateNumberOfMessagesNotVisible":
promMessagesNotVisible.WithLabelValues(queueResult.QueueName).Set(nMessages)
default:
log.Error().Msg(fmt.Sprintf("unknown attribute %v", attrib))
os.Exit(1)
log.Warn().Msg(fmt.Sprintf("unknown attribute %v", attrib))
}
}
}

time.Sleep(monitorInterval * time.Second)
time.Sleep(monitorInterval)
}
}

// Return an empty 200 response for healthchecks
func healthcheck(http.ResponseWriter, *http.Request) {
func healthcheck(w http.ResponseWriter, r *http.Request) {
}

func main() {
Expand All @@ -142,13 +150,17 @@ func main() {
port = "8080"
}

log.Info().Int("interval", int(monitorInterval)).Strs("queueUrls", queueUrls).Str("port", port).Msg("Starting queue monitors")
monitorInterval = getMonitorInterval()

log.Info().Dur("interval", monitorInterval).Strs("queueUrls", queueUrls).Str("port", port).Msg("Starting queue monitors")

svc = getSqsClient()

go monitorQueues(queueUrls)

http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/healthz", healthcheck)
err := http.ListenAndServe(":" + port, nil)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
log.Error().Str("errorMessage", err.Error()).Msg("Could not start http listener")
os.Exit(1)
Expand Down
78 changes: 78 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package main

import (
"context"
"os"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/service/sqs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

// MockSQSClient is a mock of the SQS client
type MockSQSClient struct {
mock.Mock
}

// GetQueueAttributes mocks the GetQueueAttributes method
func (m *MockSQSClient) GetQueueAttributes(ctx context.Context, params *sqs.GetQueueAttributesInput, optFns ...func(*sqs.Options)) (*sqs.GetQueueAttributesOutput, error) {
args := m.Called(ctx, params, optFns)
return args.Get(0).(*sqs.GetQueueAttributesOutput), args.Error(1)
}

func TestGetMonitorInterval(t *testing.T) {
tests := []struct {
name string
envValue string
expectedResult time.Duration
}{
{"Default value", "", 30 * time.Second},
{"Custom value", "60", 60 * time.Second},
{"Invalid value", "invalid", 30 * time.Second},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
os.Setenv("SQS_MONITOR_INTERVAL_SECONDS", tt.envValue)
defer os.Unsetenv("SQS_MONITOR_INTERVAL_SECONDS")

result := getMonitorInterval()
assert.Equal(t, tt.expectedResult, result)
})
}
}

func TestMonitorQueue(t *testing.T) {
mockClient := new(MockSQSClient)
originalSvc := svc
svc = mockClient
defer func() { svc = originalSvc }()

queueURL := "https://sqs.us-west-2.amazonaws.com/123456789012/MyQueue"
expectedOutput := &sqs.GetQueueAttributesOutput{
Attributes: map[string]string{
"ApproximateNumberOfMessages": "10",
"ApproximateNumberOfMessagesDelayed": "5",
"ApproximateNumberOfMessagesNotVisible": "2",
},
}

mockClient.On("GetQueueAttributes", mock.Anything, mock.Anything, mock.Anything).Return(expectedOutput, nil)

c := make(chan queueResult)
go monitorQueue(queueURL, c)

result := <-c

assert.Equal(t, queueURL, result.QueueURL)
assert.Equal(t, "MyQueue", result.QueueName)
assert.Equal(t, expectedOutput, result.QueueResults)

mockClient.AssertExpectations(t)
}

func TestHealthcheck(t *testing.T) {
assert.NotPanics(t, func() { healthcheck(nil, nil) })
}

0 comments on commit 4d8a005

Please sign in to comment.