1package backup
2
3import (
4 "testing"
5
6 "github.com/bnema/gordon/internal/domain"
7 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/require"
9)
10
11func TestDetectDatabaseFromAttachment_ExtractsPostgresVersion(t *testing.T) {
12 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
13 Name: "postgres",
14 Image: "postgres:17.4-alpine",
15 ContainerID: "abc123",
16 Ports: []int{55432},
17 })
18
19 require.True(t, ok)
20 assert.Equal(t, domain.DBTypePostgreSQL, db.Type)
21 assert.Equal(t, "17", db.Version)
22 assert.Equal(t, 55432, db.Port)
23}
24
25func TestDetectDatabaseFromAttachment_DefaultPort(t *testing.T) {
26 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
27 Name: "postgres",
28 Image: "postgres:16",
29 ContainerID: "xyz789",
30 Ports: []int{},
31 })
32
33 require.True(t, ok)
34 assert.Equal(t, 5432, db.Port)
35 assert.Equal(t, "16", db.Version)
36}
37
38func TestDetectDatabaseFromAttachment_PrefersPostgresPort(t *testing.T) {
39 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
40 Name: "postgres",
41 Image: "postgres:16",
42 ContainerID: "xyz789",
43 Ports: []int{15432, 5432, 25432},
44 })
45
46 require.True(t, ok)
47 assert.Equal(t, 5432, db.Port)
48}
49
50func TestDetectDatabaseFromAttachment_UsesFirstPositivePortWhen5432Missing(t *testing.T) {
51 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
52 Name: "postgres",
53 Image: "postgres:16",
54 ContainerID: "xyz789",
55 Ports: []int{0, -1, 15432, 25432},
56 })
57
58 require.True(t, ok)
59 assert.Equal(t, 15432, db.Port)
60}
61
62func TestPostgresVersionFromImage(t *testing.T) {
63 assert.Equal(t, "18", postgresVersionFromImage("postgres:18"))
64 assert.Equal(t, "17", postgresVersionFromImage("postgres:17.4-alpine"))
65 assert.Equal(t, "", postgresVersionFromImage("postgres:latest"))
66 assert.Equal(t, "", postgresVersionFromImage("postgres:alpine"))
67 assert.Equal(t, "", postgresVersionFromImage("postgres"))
68}
69
70func TestDetectDatabaseFromAttachment_NonPostgres(t *testing.T) {
71 _, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
72 Name: "mysql",
73 Image: "mysql:8.0",
74 ContainerID: "def456",
75 Ports: []int{3306},
76 })
77 assert.False(t, ok)
78}
79
80func TestDetectDatabaseFromAttachment_PgsqlImage(t *testing.T) {
81 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
82 Name: "pgsql",
83 Image: "pgsql:16",
84 ContainerID: "pgsql-1",
85 Ports: []int{5432},
86 })
87
88 require.True(t, ok)
89 assert.Equal(t, domain.DBTypePostgreSQL, db.Type)
90 assert.Equal(t, "16", db.Version)
91 assert.Equal(t, 5432, db.Port)
92}
93
94func TestDetectDatabaseFromAttachment_PgsqlInCompositeName(t *testing.T) {
95 db, ok := detectDatabaseFromAttachment("mon-fauteuil.fr", domain.Attachment{
96 Name: "mon-fauteuil-prod-pgsql",
97 Image: "mon-fauteuil-prod-pgsql:v18",
98 ContainerID: "pgsql-2",
99 Ports: []int{5432},
100 })
101
102 require.True(t, ok)
103 assert.Equal(t, domain.DBTypePostgreSQL, db.Type)
104 assert.Equal(t, "", db.Version) // v18 tag starts with non-digit, no version extracted
105}
106
107func TestDetectDatabaseFromAttachment_PostgresqlFullName(t *testing.T) {
108 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
109 Name: "postgresql",
110 Image: "postgresql:15",
111 ContainerID: "pg-full-1",
112 Ports: []int{5432},
113 })
114
115 require.True(t, ok)
116 assert.Equal(t, domain.DBTypePostgreSQL, db.Type)
117 assert.Equal(t, "15", db.Version)
118}
119
120func TestDetectDatabaseFromAttachment_PostgisImage(t *testing.T) {
121 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
122 Name: "postgis",
123 Image: "postgis/postgis:16-3.4",
124 ContainerID: "postgis-1",
125 Ports: []int{5432},
126 })
127
128 require.True(t, ok)
129 assert.Equal(t, domain.DBTypePostgreSQL, db.Type)
130 assert.Equal(t, "16", db.Version)
131}
132
133func TestDetectDatabaseFromAttachment_Port5432Fallback(t *testing.T) {
134 db, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
135 Name: "custom-db",
136 Image: "custom-db:latest",
137 ContainerID: "fallback-1",
138 Ports: []int{5432},
139 })
140
141 require.True(t, ok, "port 5432 should trigger PostgreSQL fallback detection")
142 assert.Equal(t, domain.DBTypePostgreSQL, db.Type)
143 assert.Equal(t, 5432, db.Port)
144}
145
146func TestDetectDatabaseFromAttachment_UnknownImageNoPostgresPort(t *testing.T) {
147 _, ok := detectDatabaseFromAttachment("app.example.com", domain.Attachment{
148 Name: "custom-db",
149 Image: "custom-db:latest",
150 ContainerID: "unknown-1",
151 Ports: []int{3306},
152 })
153 assert.False(t, ok, "non-postgres port with unknown image should not match")
154}
155
156func TestLooksLikePostgres(t *testing.T) {
157 tests := []struct {
158 name string
159 image string
160 want bool
161 }{
162 {name: "postgres base image", image: "postgres", want: true},
163 {name: "postgres with version tag", image: "postgres:16", want: true},
164 {name: "name contains postgres", image: "my-postgres-db", want: true},
165 {name: "postgresql alias", image: "postgresql", want: true},
166 {name: "pgsql alias", image: "pgsql", want: true},
167 {name: "project specific pgsql alias", image: "mon-fauteuil-prod-pgsql", want: true},
168 {name: "postgis alias", image: "postgis/postgis", want: true},
169 {name: "mysql negative", image: "mysql", want: false},
170 {name: "redis negative", image: "redis", want: false},
171 {name: "custom negative", image: "custom-db", want: false},
172 {name: "empty negative", image: "", want: false},
173 }
174
175 for _, tc := range tests {
176 t.Run(tc.name, func(t *testing.T) {
177 assert.Equal(t, tc.want, looksLikePostgres(tc.image))
178 })
179 }
180}