Skip to content

Commit 0b88106

Browse files
committed
Test host runtime updates & document some helper functions
1 parent b164b6c commit 0b88106

File tree

1 file changed

+129
-56
lines changed

1 file changed

+129
-56
lines changed

tests/object_sync_test.go

Lines changed: 129 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func TestObjectSync(t *testing.T) {
173173
t.Run("SlaLifeCycle", func(t *testing.T) {
174174
t.Parallel()
175175

176-
slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())}
176+
createTime := types.UnixMilli(time.Now())
177177

178178
t.Run("Hosts", func(t *testing.T) {
179179
t.Parallel()
@@ -182,8 +182,14 @@ func TestObjectSync(t *testing.T) {
182182
t.Run("Verify-Host-"+fmt.Sprint(hostId), func(t *testing.T) {
183183
t.Parallel()
184184

185+
slinfo := &SlaLifecycle{CreateTime: createTime}
186+
185187
eventually.Assert(t, func(t require.TestingT) {
186-
verifySlaLifeCycleRow(t, db, slinfo, host.Name, "")
188+
// We can't join on the host table, as the sla lifecycle entries may reference hosts that have
189+
// already been deleted. So fetch the host id from DB before performing the actual test.
190+
require.NoError(t, fetchCheckableId(db, slinfo, host.Name, ""))
191+
192+
verifySlaLifecycleRow(t, db, slinfo, false)
187193
}, 20*time.Second, 1*time.Second)
188194
})
189195
}
@@ -196,8 +202,14 @@ func TestObjectSync(t *testing.T) {
196202
t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) {
197203
t.Parallel()
198204

205+
slinfo := &SlaLifecycle{CreateTime: createTime}
206+
199207
eventually.Assert(t, func(t require.TestingT) {
200-
verifySlaLifeCycleRow(t, db, slinfo, *service.HostName, service.Name)
208+
// We can't join on the service table, as the sla lifecycle entries may reference services that
209+
// have already been deleted. So fetch the service id from DB before performing the actual test.
210+
require.NoError(t, fetchCheckableId(db, slinfo, *service.HostName, service.Name))
211+
212+
verifySlaLifecycleRow(t, db, slinfo, false)
201213
}, 20*time.Second, 1*time.Second)
202214
})
203215
}
@@ -452,29 +464,71 @@ func TestObjectSync(t *testing.T) {
452464
t.Run("SlaLifeCycle", func(t *testing.T) {
453465
t.Parallel()
454466

455-
for serviceId, service := range makeTestSyncServices(t) {
456-
//service.Name += fmt.Sprint(serviceId)
467+
assertCheckableFunc := func(checkable any, objType string, objName string, host string, service string) {
468+
client.CreateObject(t, objType, objName, map[string]any{
469+
"attrs": makeIcinga2ApiAttributes(checkable, false),
470+
})
457471

458-
t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) {
459-
t.Parallel()
472+
slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())}
473+
eventually.Assert(t, func(t require.TestingT) {
474+
// We can't join on the host/service tables, as the sla lifecycle entries may reference checkables
475+
// that have already been deleted. So fetch the host/service id from DB before performing the actual test.
476+
require.NoError(t, fetchCheckableId(db, slinfo, host, service))
460477

461-
client.CreateObject(t, "services", *service.HostName+"!"+service.Name, map[string]interface{}{
462-
"attrs": makeIcinga2ApiAttributes(service, false),
463-
})
478+
verifySlaLifecycleRow(t, db, slinfo, false)
479+
}, 20*time.Second, 1*time.Second)
464480

465-
slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())}
466-
eventually.Assert(t, func(t require.TestingT) {
467-
verifySlaLifeCycleRow(t, db, slinfo, *service.HostName, service.Name)
468-
}, 20*time.Second, 1*time.Second)
481+
client.DeleteObject(t, objType, objName, false)
469482

470-
client.DeleteObject(t, "services", *service.HostName+"!"+service.Name, false)
483+
slinfo.DeleteTime = types.UnixMilli(time.Now())
484+
eventually.Assert(t, func(t require.TestingT) {
485+
verifySlaLifecycleRow(t, db, slinfo, false)
486+
}, 20*time.Second, 1*time.Second)
471487

472-
slinfo.DeleteTime = types.UnixMilli(time.Now())
473-
eventually.Assert(t, func(t require.TestingT) {
474-
verifySlaLifeCycleRow(t, db, slinfo, "", "")
475-
}, 20*time.Second, 1*time.Second)
488+
client.CreateObject(t, objType, objName, map[string]interface{}{
489+
"attrs": makeIcinga2ApiAttributes(checkable, false),
476490
})
491+
492+
// We are recreating this checkable, so we only have to change the timestamps as the
493+
// checkable id will remain the same.
494+
slinfo.CreateTime = types.UnixMilli(time.Now())
495+
slinfo.DeleteTime = types.UnixMilli(time.Time{})
496+
497+
eventually.Assert(t, func(t require.TestingT) {
498+
verifySlaLifecycleRow(t, db, slinfo, true)
499+
}, 20*time.Second, 1*time.Second)
500+
501+
client.DeleteObject(t, objType, objName, false)
502+
503+
slinfo.DeleteTime = types.UnixMilli(time.Now())
504+
eventually.Assert(t, func(t require.TestingT) {
505+
verifySlaLifecycleRow(t, db, slinfo, true)
506+
}, 20*time.Second, 1*time.Second)
477507
}
508+
509+
t.Run("Host", func(t *testing.T) {
510+
t.Parallel()
511+
512+
for hostId, host := range makeTestSyncHosts(t) {
513+
t.Run("Verify-Host-"+fmt.Sprint(hostId), func(t *testing.T) {
514+
t.Parallel()
515+
516+
assertCheckableFunc(host, "hosts", host.Name, host.Name, "")
517+
})
518+
}
519+
})
520+
521+
t.Run("Service", func(t *testing.T) {
522+
t.Parallel()
523+
524+
for serviceId, service := range makeTestSyncServices(t) {
525+
t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) {
526+
t.Parallel()
527+
528+
assertCheckableFunc(service, "services", *service.HostName+"!"+service.Name, *service.HostName, service.Name)
529+
})
530+
}
531+
})
478532
})
479533

480534
t.Run("User", func(t *testing.T) {
@@ -1247,61 +1301,80 @@ func verifyIcingaDbRow(t require.TestingT, db *sqlx.DB, obj interface{}) {
12471301
require.False(t, rows.Next(), "SQL query should return only one row: %s", query)
12481302
}
12491303

1250-
func verifySlaLifeCycleRow(t require.TestingT, db *sqlx.DB, slinfo *SlaLifecycle, host string, service string) {
1251-
query := `SELECT "create_time", "delete_time", "sla_lifecycle"."host_id", "sla_lifecycle"."service_id" FROM "sla_lifecycle"`
1304+
// verifySlaLifecycleRow verifies the sla lifecycle entries matching the given host/service id. It checks the creation
1305+
// and deletion time of the specified checkable. When the provided checkable was recreated, it also additionally requires
1306+
// two sla lifecycle entries to exist that match the checkables id.
1307+
func verifySlaLifecycleRow(t require.TestingT, db *sqlx.DB, slinfo *SlaLifecycle, isRecreated bool) {
1308+
query := `SELECT "create_time", "delete_time" FROM "sla_lifecycle" WHERE "host_id" = ?`
12521309
var args []interface{}
1253-
if !slinfo.HostID.Valid() {
1254-
query += ` INNER JOIN "host" ON "host"."id"="sla_lifecycle"."host_id"`
1255-
where := ` WHERE "host"."name"=?`
1256-
1257-
args = append(args, host)
1258-
if service == "" {
1259-
where += ` AND "service_id" IS NULL`
1260-
} else {
1261-
query += ` INNER JOIN "service" ON "service"."id"="sla_lifecycle"."service_id"`
1262-
where += ` AND "service"."name"=?`
1263-
args = append(args, service)
1264-
}
1265-
1266-
query += where + ` AND "delete_time" = 0`
1310+
args = []interface{}{slinfo.HostID}
1311+
if !slinfo.ServiceID.Valid() {
1312+
query += ` AND "service_id" IS NULL`
12671313
} else {
1268-
query += ` WHERE "host_id"=?`
1269-
args = []interface{}{slinfo.HostID}
1270-
if !slinfo.ServiceID.Valid() {
1271-
query += ` AND "service_id" IS NULL`
1272-
} else {
1273-
query += ` AND "service_id"=?`
1274-
args = append(args, slinfo.ServiceID)
1275-
}
1314+
query += ` AND "service_id" = ?`
1315+
args = append(args, slinfo.ServiceID)
12761316
}
1317+
query += ` ORDER BY "create_time" ASC`
12771318

12781319
var resultSet []SlaLifecycle
12791320
err := db.Select(&resultSet, db.Rebind(query), args...)
12801321
require.NoError(t, err, "querying sla lifecycle should not fail: Query: %q", query)
12811322

1282-
require.Len(t, resultSet, 1, "there should be one sla lifecycle entry")
1283-
1284-
result := resultSet[0]
12851323
zerotimestamp := time.Unix(0, 0)
1324+
var result SlaLifecycle
12861325

1287-
require.NotEqual(t, zerotimestamp, result.CreateTime.Time())
1326+
if isRecreated {
1327+
require.Len(t, resultSet, 2, "there should be two sla lifecycle entry")
1328+
1329+
result = resultSet[1]
1330+
recreated := resultSet[0]
1331+
assert.NotEqual(t, zerotimestamp, recreated.CreateTime.Time())
1332+
assert.NotEqual(t, zerotimestamp, recreated.DeleteTime.Time())
1333+
1334+
assert.Less(t, recreated.CreateTime.Time(), slinfo.CreateTime.Time())
1335+
assert.Less(t, recreated.DeleteTime.Time(), slinfo.CreateTime.Time())
1336+
1337+
if !slinfo.DeleteTime.Time().IsZero() {
1338+
assert.Less(t, recreated.CreateTime.Time(), slinfo.DeleteTime.Time())
1339+
assert.Less(t, recreated.DeleteTime.Time(), slinfo.DeleteTime.Time())
1340+
}
1341+
} else {
1342+
require.Len(t, resultSet, 1, "there should be one sla lifecycle entry")
1343+
1344+
result = resultSet[0]
1345+
}
1346+
1347+
assert.NotEqual(t, zerotimestamp, result.CreateTime.Time())
12881348
assert.WithinDuration(t, slinfo.CreateTime.Time(), result.CreateTime.Time(), time.Minute)
12891349

12901350
if slinfo.DeleteTime.Time().IsZero() {
1291-
// We can't join on the host/service tables, as the sla lifecycle entries may reference entries that have
1292-
// already been deleted. So cache the host/service id to use as a filter when asserting the sla lifecycles
1293-
// delete event.
1294-
slinfo.HostID = result.HostID
1295-
slinfo.ServiceID = result.ServiceID
1296-
1297-
require.Equal(t, zerotimestamp, result.DeleteTime.Time())
1351+
assert.Equal(t, zerotimestamp, result.DeleteTime.Time())
12981352
} else {
1299-
require.NotEqual(t, zerotimestamp, result.DeleteTime.Time())
1300-
require.Less(t, result.CreateTime.Time(), result.DeleteTime.Time())
1353+
assert.NotEqual(t, zerotimestamp, result.DeleteTime.Time())
1354+
assert.Less(t, result.CreateTime.Time(), result.DeleteTime.Time())
13011355
assert.WithinDuration(t, slinfo.DeleteTime.Time(), result.DeleteTime.Time(), time.Minute)
13021356
}
13031357
}
13041358

1359+
// fetchCheckableId retrieves host/service id from the database matching the given host/service
1360+
// name and scans to the provided slinfo. Returns an error on any database failure.
1361+
func fetchCheckableId(db *sqlx.DB, slinfo *SlaLifecycle, host string, service string) error {
1362+
query := `SELECT "sla_lifecycle"."host_id", "sla_lifecycle"."service_id"
1363+
FROM "sla_lifecycle" INNER JOIN "host" ON "host"."id"="sla_lifecycle"."host_id"`
1364+
1365+
where := ` WHERE "host"."name" = ?`
1366+
args := []interface{}{host}
1367+
if service == "" {
1368+
where += ` AND "service_id" IS NULL`
1369+
} else {
1370+
query += ` INNER JOIN "service" ON "service"."id"="sla_lifecycle"."service_id"`
1371+
where += ` AND "service"."name" = ?`
1372+
args = append(args, service)
1373+
}
1374+
1375+
return db.QueryRowx(db.Rebind(query+where), args...).StructScan(slinfo)
1376+
}
1377+
13051378
type SlaLifecycle struct {
13061379
CreateTime types.UnixMilli `db:"create_time"`
13071380
DeleteTime types.UnixMilli `db:"delete_time"`

0 commit comments

Comments
 (0)