Files
Arvindh d840aeb1b9
Continuous Delivery / lint-and-build (push) Has been cancelled
Deploy GitHub Pages / swagger-ui (push) Has been cancelled
CI Pipeline / Lint Proto (push) Has been cancelled
CI Pipeline / Detect Changes (push) Has been cancelled
Continuous Delivery / Build and Push Docker Images (push) Has been cancelled
CI Pipeline / lint-and-build (push) Has been cancelled
CI Pipeline / Test ${{ matrix.module }} (push) Has been cancelled
CI Pipeline / Upload Coverage (push) Has been cancelled
NOISSUE - Add migration scripts for Rules, Alarms and Reports (#3482)
Signed-off-by: Arvindh <arvindh91@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Co-authored-by: nyagamunene <stevenyaga2014@gmail.com>
2026-04-30 08:46:50 +02:00

14 KiB
Raw Permalink Blame History

Backfill Roles — Testing Guide

This document covers end-to-end testing of the migration scripts on the migrations branch:

Script Purpose
scripts/re-backfill-roles/ Backfills missing built-in admin roles for rules (RE service)
scripts/reports-backfill-roles/ Backfills missing built-in admin roles for reports
scripts/seed-test-data/ Seeds all required test data across databases and SpiceDB
domains/postgres/init.go Migration adding alarm_* and report_* actions to the domain admin role

Prerequisites

Infrastructure

Start the required containers:

cd docker
docker compose up -d \
    spicedb-db spicedb-migrate spicedb \
    auth-db auth \
    domains-db domains \
    re-db re \
    reports-db reports \
    alarms-db alarms

Wait until all services are healthy. Each service applies its own Postgres migrations on startup, creating the required schemas. The auth service is required because it writes the SpiceDB schema on startup — without it, the seed script and backfill scripts fail with object definition not found.

Connection Details (docker-compose defaults)

Service Host Port User Password Database
Domains DB localhost 6003 magistrala magistrala domains
RE DB localhost 6009 magistrala magistrala rules_engine
Reports DB localhost 6020 magistrala magistrala reports
Alarms DB localhost 6019 magistrala magistrala alarms
SpiceDB gRPC localhost 50051 12345678 (pre-shared key)

Fix Hard-Coded Configs (if needed)

The backfill scripts have hard-coded database configs. Before running, verify they match your environment:

scripts/re-backfill-roles/main.go (lines 4855):

dbConfig = pgclient.Config{
    Host:    "localhost",
    Port:    "6009",        // docker-compose: 6009 (NOT 15432)
    User:    "magistrala",  // docker-compose: magistrala (NOT postgres)
    Pass:    "magistrala",  // docker-compose: magistrala (NOT supermq)
    Name:    "rules_engine",
    SSLMode: "disable",
}

scripts/reports-backfill-roles/main.go (lines 4956):

dbConfig = pgclient.Config{
    Host:    "localhost",
    Port:    "6020",        // docker-compose: 6020 (NOT 15432)
    User:    "magistrala",  // docker-compose: magistrala (NOT postgres)
    Pass:    "magistrala",  // docker-compose: magistrala (NOT supermq)
    Name:    "reports",
    SSLMode: "disable",
}

Both scripts — SpiceDB schema file (line 47):

spicedbSchemaFile = "docker/spicedb/schema.zed"  // NOT combined-schema.zed

Step 1 — Seed Test Data

go run ./scripts/seed-test-data/

This inserts deterministic test data across all four databases and SpiceDB. It is idempotent (uses ON CONFLICT DO NOTHING), so re-running is safe.

What Gets Created

Domain:

ID Name
d0000000-0000-0000-0000-000000000001 seed-test-domain

Users:

ID Domain Membership
u0000000-0000-0000-0000-000000000001 (user1) Member of domain (in domains_role_members)
u0000000-0000-0000-0000-000000000002 (user2) NOT a domain member

Rules (RE DB) — 6 rules, 4 orphans:

Rule ID Name Scenario
r0000000-...-000000000001 rule-1-member-creator Orphan. created_by=user1 (domain member). Backfill should create role with member.
r0000000-...-000000000002 rule-2-nonmember-creator Orphan. created_by=user2 (NOT member). Backfill should create role without member.
r0000000-...-000000000003 rule-3-spicedb-exists Orphan. created_by=user1. SpiceDB parent relation pre-seeded. Tests policyExists check.
r0000000-...-000000000004 rule-4-null-creator Orphan. created_by=NULL. Should be skipped.
r0000000-...-000000000005 rule-5-no-domain Orphan. domain_id="". Should be skipped.
r0000000-...-000000000006 rule-6-has-role-already Has rules_roles entry. Should NOT appear in orphan list.

Reports (Reports DB) — 5 reports, 3 orphans:

Report ID Name Scenario
rp000000-...-000000000001 report-1-member-creator Orphan. created_by=user1. Backfill should create role with member.
rp000000-...-000000000002 report-2-nonmember-creator Orphan. created_by=user2. Backfill should create role without member.
rp000000-...-000000000003 report-3-spicedb-exists Orphan. created_by=user1. SpiceDB parent pre-seeded. Tests policyExists.
rp000000-...-000000000004 report-4-null-creator Orphan. created_by=NULL. Should be skipped.
rp000000-...-000000000005 report-5-has-role-already Has reports_roles entry. Should NOT appear.

Alarms (Alarms DB) — 2 alarms:

Alarm ID Linked Rule
a0000000-...-000000000001 rule-1
a0000000-...-000000000002 rule-2

SpiceDB (pre-seeded parent relations):

rule:r0000000-...-000000000003#domain@domain:d0000000-...-000000000001
report:rp000000-...-000000000003#domain@domain:d0000000-...-000000000001

Step 2 — Verify Seed Data

Check orphan rules in RE DB

psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  SELECT r.id, r.name, r.domain_id, r.created_by
  FROM rules r
  WHERE NOT EXISTS (SELECT 1 FROM rules_roles rr WHERE rr.entity_id = r.id)
  ORDER BY r.name;"

Expected: 5 rows (rule-1 through rule-5). rule-6 should NOT appear (it has a role).

Check orphan reports in Reports DB

psql -h localhost -p 6020 -U magistrala -d reports -c "
  SELECT rc.id, rc.name, rc.domain_id, rc.created_by
  FROM report_config rc
  WHERE NOT EXISTS (SELECT 1 FROM reports_roles rr WHERE rr.entity_id = rc.id)
  ORDER BY rc.name;"

Expected: 4 rows (report-1 through report-4). report-5 should NOT appear.

Check domain membership

psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  SELECT * FROM domains_role_members
  WHERE entity_id = 'd0000000-0000-0000-0000-000000000001';"

Expected: 1 row for user1. user2 should NOT be present.

Check SpiceDB pre-seeded relationships

zed relationship read rule \
  --insecure --endpoint localhost:50051 --token 12345678

Expected: At least one relationship for rule:r0000000-...-000000000003#domain@domain:d0000000-...-000000000001.


Step 3 — Test RE Backfill (Dry Run)

Set dryRun = true in scripts/re-backfill-roles/main.go, then:

go run ./scripts/re-backfill-roles/

Expected Log Output

Rule Expected Log
rule-1 "dry run: would provision missing built-in role" with created_by_exists_in_domain=true
rule-2 "created_by user is not a member of the domain" + "dry run: would provision missing built-in role without member"
rule-3 "dry run: spicedb policy already exists, will not be re-added" + "dry run: would provision" with new_optional_policies=0, existing_optional_policies=1
rule-4 "skipping rule without created_by and no default member override"
rule-5 "skipping rule without domain_id"
rule-6 Does NOT appear at all

Verify No Side Effects

# Postgres: no new roles created
psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  SELECT COUNT(*) FROM rules_roles
  WHERE entity_id IN (
    'r0000000-0000-0000-0000-000000000001',
    'r0000000-0000-0000-0000-000000000002',
    'r0000000-0000-0000-0000-000000000003'
  );"

Expected: 0 (dry run should not write anything).


Step 4 — Test RE Backfill (Real Run)

Set dryRun = false in scripts/re-backfill-roles/main.go, then:

go run ./scripts/re-backfill-roles/

Expected Log Output

Rule Expected Log
rule-1 "provisioned missing built-in role" with member_added=true
rule-2 "provisioned missing built-in role" with member_added=false
rule-3 "spicedb policy already exists, skipping re-add" + "provisioned missing built-in role" with new_optional_policies=0
rule-4 "skipping rule without created_by"
rule-5 "skipping rule without domain_id"

Final summary should show: processed=3, skipped=2, failed=0.

Verify in Postgres

# New roles exist for rules 1, 2, 3
psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  SELECT rr.id, rr.entity_id, rr.name, rr.created_by
  FROM rules_roles rr
  ORDER BY rr.entity_id;"

# Role members: rule-1 should have user1; rule-2 and rule-3 check based on domain membership
psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  SELECT rrm.role_id, rrm.member_id, rrm.entity_id
  FROM rules_role_members rrm
  ORDER BY rrm.entity_id;"

Verify in SpiceDB

zed relationship read rule \
  --insecure --endpoint localhost:50051 --token 12345678

Expected: Parent relations for rule-1 and rule-2 are newly created. Rule-3 already had one (no duplicate).


Step 5 — Test Idempotency (Re-Run)

Run the same backfill again without any changes:

go run ./scripts/re-backfill-roles/

Expected: "loaded rules without roles" count=2 and "backfill finished" processed=0, skipped=2, failed=0. The two remaining rows are rule-4 (created_by=NULL) and rule-5 (no domain_id), which always re-appear in the orphan query and are skipped each run. The idempotency signal is processed=0 — no roles or SpiceDB writes are duplicated.


Step 6 — Test Partial State (policyExists Path)

This specifically validates the SpiceDB pre-check. Simulate a scenario where Postgres lost the role but SpiceDB still has the parent relation:

# Delete just the Postgres role for rule-1
psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  DELETE FROM rules_roles
  WHERE entity_id = 'r0000000-0000-0000-0000-000000000001';"

# Re-run backfill
go run ./scripts/re-backfill-roles/

Expected

  • "loaded rules without roles" count=1 (only rule-1 reappears)
  • "spicedb policy already exists, skipping re-add" — the parent relation is detected and filtered out
  • "provisioned missing built-in role" with new_optional_policies=0, existing_optional_policies=1
  • The role row is re-created in Postgres without a duplicate SpiceDB write

Verify

# Postgres: role restored
psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  SELECT * FROM rules_roles
  WHERE entity_id = 'r0000000-0000-0000-0000-000000000001';"

# SpiceDB: still exactly one parent relation (no duplicate)
zed relationship read rule:r0000000-0000-0000-0000-000000000001 \
  --insecure --endpoint localhost:50051 --token 12345678

Step 7 — Test Reports Backfill

Repeat Steps 36 for the reports backfill script:

# Dry run (set dryRun = true first)
go run ./scripts/reports-backfill-roles/

# Real run (set dryRun = false)
go run ./scripts/reports-backfill-roles/

Expected behavior

Report Expected
report-1 Role provisioned with member (user1 is domain member)
report-2 Role provisioned without member (user2 not in domain)
report-3 "spicedb policy already exists" + role provisioned with new_optional_policies=0
report-4 Skipped (NULL created_by)
report-5 Does not appear (already has role)

Verify

psql -h localhost -p 6020 -U magistrala -d reports -c "
  SELECT rr.id, rr.entity_id, rr.name
  FROM reports_roles rr
  ORDER BY rr.entity_id;"

zed relationship read report \
  --insecure --endpoint localhost:50051 --token 12345678

Step 8 — Verify Domains Migration

The domains/postgres/init.go change adds alarm_* and report_* actions to the domain admin role. This is applied by the domains service on startup.

psql -h localhost -p 6003 -U magistrala -d domains -c "
  SELECT action FROM domains_role_actions
  WHERE role_id IN (SELECT id FROM domains_roles WHERE name = 'admin')
  ORDER BY action;"

Expected: The result should include all of these new actions:

alarm_acknowledge
alarm_assign
alarm_delete
alarm_read
alarm_resolve
alarm_update
report_add_role_users
report_create
report_delete
report_manage_role
report_read
report_remove_role_users
report_update
report_view_role_users

Step 9 — Cleanup (Optional)

To reset and re-test from scratch:

# Remove all seeded data from RE DB
psql -h localhost -p 6009 -U magistrala -d rules_engine -c "
  DELETE FROM rules WHERE id LIKE 'r0000000-%';
  DELETE FROM domains WHERE id = 'd0000000-0000-0000-0000-000000000001';"

# Remove all seeded data from Reports DB
psql -h localhost -p 6020 -U magistrala -d reports -c "
  DELETE FROM report_config WHERE id LIKE 'rp000000-%';
  DELETE FROM domains WHERE id = 'd0000000-0000-0000-0000-000000000001';"

# Remove all seeded data from Alarms DB
psql -h localhost -p 6019 -U magistrala -d alarms -c "
  DELETE FROM alarms WHERE id LIKE 'a0000000-%';
  DELETE FROM domains WHERE id = 'd0000000-0000-0000-0000-000000000001';"

# Remove SpiceDB relationships
zed relationship delete rule --insecure --endpoint localhost:50051 --token 12345678
zed relationship delete report --insecure --endpoint localhost:50051 --token 12345678

Then re-run go run ./scripts/seed-test-data/ to start fresh.


Troubleshooting

Problem Solution
failed to connect to postgres Verify containers are running: docker compose ps. Check ports with docker compose port re-db 5432.
failed to read spicedb relationships Ensure SpiceDB is running and schema is loaded. Check: zed schema read --insecure --endpoint localhost:50051 --token 12345678
failed to load built-in role actions Verify spicedbSchemaFile points to docker/spicedb/schema.zed (not combined-schema.zed).
no such table errors during seed Services haven't run yet to apply migrations. Start the full service (re, reports, alarms) at least once.
Script exits with count=0 unexpectedly All rules/reports already have roles. Check with the orphan queries from Step 2.