Skip to content

Commit 77dbad7

Browse files
committed
Integration tests
Signed-off-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com>
1 parent 4ecdffb commit 77dbad7

4 files changed

Lines changed: 244 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Integration Tests
2+
on:
3+
pull_request:
4+
paths-ignore:
5+
- "docs/**"
6+
- "*.md"
7+
jobs:
8+
integration:
9+
name: Integration Tests
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-go@v5
14+
with:
15+
go-version: 1.22
16+
- name: Start Cortex
17+
run: |
18+
docker run -d --name cortex \
19+
-p 9009:9009 \
20+
-v ${{ github.workspace }}/integration/cortex-config.yaml:/etc/cortex/config.yaml \
21+
cortexproject/cortex:v1.18.1 \
22+
-config.file=/etc/cortex/config.yaml \
23+
-target=all,alertmanager
24+
- name: Wait for Cortex
25+
run: |
26+
for i in $(seq 1 30); do
27+
if wget -qO- http://localhost:9009/ready > /dev/null 2>&1; then
28+
echo "Cortex is ready"
29+
exit 0
30+
fi
31+
echo "Waiting for Cortex... ($i)"
32+
sleep 2
33+
done
34+
echo "Cortex failed to start"
35+
docker logs cortex
36+
exit 1
37+
- name: Run Integration Tests
38+
env:
39+
CORTEX_ADDRESS: http://localhost:9009
40+
run: go test -mod=vendor -tags=integration -v -count=1 ./integration/...
41+
- name: Cortex Logs
42+
if: failure()
43+
run: docker logs cortex
44+
- name: Cleanup
45+
if: always()
46+
run: docker stop cortex && docker rm cortex
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
route:
2+
receiver: default
3+
receivers:
4+
- name: default

integration/cortex-config.yaml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
auth_enabled: false
2+
3+
server:
4+
http_listen_port: 9009
5+
grpc_server_max_recv_msg_size: 104857600
6+
grpc_server_max_send_msg_size: 104857600
7+
grpc_server_max_concurrent_streams: 1000
8+
9+
distributor:
10+
shard_by_all_labels: true
11+
pool:
12+
health_check_ingesters: true
13+
14+
ingester_client:
15+
grpc_client_config:
16+
max_recv_msg_size: 104857600
17+
max_send_msg_size: 104857600
18+
grpc_compression: gzip
19+
20+
ingester:
21+
lifecycler:
22+
min_ready_duration: 0s
23+
final_sleep: 0s
24+
num_tokens: 512
25+
ring:
26+
kvstore:
27+
store: inmemory
28+
replication_factor: 1
29+
30+
blocks_storage:
31+
tsdb:
32+
dir: /tmp/cortex/tsdb
33+
bucket_store:
34+
sync_dir: /tmp/cortex/tsdb-sync
35+
backend: filesystem
36+
filesystem:
37+
dir: /tmp/cortex/data/tsdb
38+
39+
compactor:
40+
data_dir: /tmp/cortex/compactor
41+
sharding_ring:
42+
kvstore:
43+
store: inmemory
44+
45+
frontend_worker:
46+
match_max_concurrent: true
47+
48+
ruler:
49+
enable_api: true
50+
51+
ruler_storage:
52+
backend: filesystem
53+
filesystem:
54+
dir: /tmp/cortex/rules
55+
56+
alertmanager:
57+
enable_api: true
58+
external_url: http://localhost:9009/alertmanager
59+
sharding_ring:
60+
kvstore:
61+
store: inmemory
62+
replication_factor: 1
63+
64+
alertmanager_storage:
65+
backend: filesystem
66+
filesystem:
67+
dir: /tmp/cortex/alerts

integration/integration_test.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//go:build integration
2+
3+
package integration
4+
5+
import (
6+
"context"
7+
"errors"
8+
"os"
9+
"testing"
10+
11+
"github.com/prometheus/prometheus/model/rulefmt"
12+
"github.com/stretchr/testify/require"
13+
"gopkg.in/yaml.v3"
14+
15+
"github.com/cortexproject/cortex-tools/pkg/client"
16+
"github.com/cortexproject/cortex-tools/pkg/rules/rwrulefmt"
17+
)
18+
19+
func cortexAddress() string {
20+
if addr := os.Getenv("CORTEX_ADDRESS"); addr != "" {
21+
return addr
22+
}
23+
return "http://localhost:9009"
24+
}
25+
26+
func newClient(t *testing.T) *client.CortexClient {
27+
t.Helper()
28+
c, err := client.New(client.Config{
29+
Address: cortexAddress(),
30+
ID: "fake",
31+
})
32+
require.NoError(t, err)
33+
return c
34+
}
35+
36+
func ruleNode(record, expr string) rulefmt.RuleNode {
37+
return rulefmt.RuleNode{
38+
Record: yaml.Node{Kind: yaml.ScalarNode, Value: record},
39+
Expr: yaml.Node{Kind: yaml.ScalarNode, Value: expr},
40+
}
41+
}
42+
43+
func TestRulesLoadListDelete(t *testing.T) {
44+
ctx := context.Background()
45+
c := newClient(t)
46+
47+
namespace := "test_namespace"
48+
group := rwrulefmt.RuleGroup{}
49+
group.Name = "test_rule_group"
50+
group.Rules = []rulefmt.RuleNode{
51+
ruleNode("summed_up", "sum(up)"),
52+
}
53+
54+
err := c.CreateRuleGroup(ctx, namespace, group)
55+
require.NoError(t, err, "CreateRuleGroup should succeed")
56+
57+
ruleSet, err := c.ListRules(ctx, "")
58+
require.NoError(t, err, "ListRules should succeed")
59+
require.Contains(t, ruleSet, namespace, "namespace should exist")
60+
61+
found := false
62+
for _, g := range ruleSet[namespace] {
63+
if g.Name == "test_rule_group" {
64+
found = true
65+
break
66+
}
67+
}
68+
require.True(t, found, "rule group should be in list")
69+
70+
rg, err := c.GetRuleGroup(ctx, namespace, "test_rule_group")
71+
require.NoError(t, err, "GetRuleGroup should succeed")
72+
require.Equal(t, "test_rule_group", rg.Name)
73+
require.Len(t, rg.Rules, 1)
74+
75+
err = c.DeleteRuleNamespace(ctx, namespace)
76+
require.NoError(t, err, "DeleteRuleNamespace should succeed")
77+
78+
ruleSet, err = c.ListRules(ctx, "")
79+
if err != nil {
80+
require.True(t, errors.Is(err, client.ErrResourceNotFound), "expected no rules or resource not found, got: %v", err)
81+
} else {
82+
require.NotContains(t, ruleSet, namespace, "namespace should be deleted")
83+
}
84+
}
85+
86+
func TestRulesMultipleGroups(t *testing.T) {
87+
ctx := context.Background()
88+
c := newClient(t)
89+
90+
namespace := "multi_group_namespace"
91+
groups := []rwrulefmt.RuleGroup{
92+
{RuleGroup: rulefmt.RuleGroup{Name: "group_a", Rules: []rulefmt.RuleNode{ruleNode("metric_a", "sum(up)")}}},
93+
{RuleGroup: rulefmt.RuleGroup{Name: "group_b", Rules: []rulefmt.RuleNode{ruleNode("metric_b", "count(up)")}}},
94+
{RuleGroup: rulefmt.RuleGroup{Name: "group_c", Rules: []rulefmt.RuleNode{ruleNode("metric_c", "avg(up)")}}},
95+
}
96+
97+
for _, g := range groups {
98+
err := c.CreateRuleGroup(ctx, namespace, g)
99+
require.NoError(t, err, "CreateRuleGroup %s should succeed", g.Name)
100+
}
101+
102+
ruleSet, err := c.ListRules(ctx, namespace)
103+
require.NoError(t, err)
104+
require.Contains(t, ruleSet, namespace)
105+
require.Len(t, ruleSet[namespace], 3, "should have 3 rule groups")
106+
107+
err = c.DeleteRuleNamespace(ctx, namespace)
108+
require.NoError(t, err)
109+
}
110+
111+
func TestAlertmanagerLoadGet(t *testing.T) {
112+
ctx := context.Background()
113+
c := newClient(t)
114+
115+
amConfig := "route:\n receiver: default\nreceivers:\n - name: default\n"
116+
117+
err := c.CreateAlertmanagerConfig(ctx, amConfig, nil)
118+
require.NoError(t, err, "CreateAlertmanagerConfig should succeed")
119+
120+
cfg, templates, err := c.GetAlertmanagerConfig(ctx)
121+
require.NoError(t, err, "GetAlertmanagerConfig should succeed")
122+
require.Contains(t, cfg, "receiver: default")
123+
require.Empty(t, templates)
124+
125+
err = c.DeleteAlermanagerConfig(ctx)
126+
require.NoError(t, err, "DeleteAlermanagerConfig should succeed")
127+
}

0 commit comments

Comments
 (0)