Files
Dušan Borovčanin 09a56575c1
Property Based Tests / api-test (push) Has been cancelled
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 - Use Atom access tokens (#3540)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-07-01 19:41:01 +02:00

96 lines
2.5 KiB
Go

// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Command atom-migration migrates a Magistrala v0.30.0 deployment (per-service
// Postgres databases) into a single Atom IAM Postgres database.
//
// It is offline and idempotent: every write upserts on a preserved/derived
// primary key, so the tool is safe to re-run. Default mode is --dry-run, which
// reads, transforms, validates and reports without writing anything.
//
// See PLAN.md in this directory for the full mapping and runbook.
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"time"
)
func main() {
os.Exit(runMain())
}
func runMain() int {
var (
envPath = flag.String("env", "docker/.env", "path to Magistrala docker/.env (DB hosts/creds)")
atomDSN = flag.String("atom-dsn", envOr("ATOM_DATABASE_URL", ""), "Atom Postgres DSN (overrides --env atom block)")
apply = flag.Bool("apply", false, "perform the load (default is dry-run: read+validate+report only)")
reportDir = flag.String("report-dir", "tools/atom-migration/report", "directory for the JSON+markdown report")
fromHost = flag.Bool("from-host", false, "connect to source DBs via localhost mapped ports instead of compose service names")
unmappedOK = flag.String("unmapped-action", "manage", "fallback Atom action for unmapped Magistrala actions: manage|skip")
verify = flag.Bool("verify", false, "verify a completed migration (reconcile source vs Atom); read-only, no load")
)
flag.Parse()
cfg, err := loadConfig(*envPath, *atomDSN, *fromHost)
if err != nil {
log.Printf("config: %v", err)
return 1
}
cfg.UnmappedAction = *unmappedOK
mode := "DRY-RUN"
switch {
case *verify:
mode = "VERIFY"
case *apply:
mode = "APPLY"
}
log.Printf("atom-migration starting (%s)", mode)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Hour)
defer cancel()
m, err := newMigrator(ctx, cfg, *apply)
if err != nil {
log.Printf("init: %v", err)
return 1
}
defer m.Close()
rep := newReport(mode)
run := m.Run
if *verify {
run = m.Verify
}
if err := run(ctx, rep); err != nil {
rep.Errorf("fatal: %v", err)
if writeErr := rep.Write(*reportDir); writeErr != nil {
log.Printf("report: %v", writeErr)
}
log.Printf("%s: %v", mode, err)
return 1
}
if err := rep.Write(*reportDir); err != nil {
log.Printf("report: %v", err)
return 1
}
fmt.Print(rep.Summary())
if rep.HasBlocking() && *apply {
return 2
}
return 0
}
func envOr(k, def string) string {
if v := os.Getenv(k); v != "" {
return v
}
return def
}