Files
knowledge-governance/cmd/qa-org-import/main.go
T

63 lines
2.1 KiB
Go

package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"knowledge-governance/internal/qaopsorg"
)
func main() {
if err := run(os.Args[1:], os.Getenv, os.Stdout); err != nil {
fmt.Fprintln(os.Stderr, "directory import failed; check private input and governance connection (details withheld)")
os.Exit(1)
}
}
func run(args []string, getenv func(string) string, out io.Writer) error {
if len(args) != 1 || getenv("QAOPS_CONFIRM_DIRECTORY_IMPORT") != "import-governance-directory" || getenv("DOBOTAI_OPS_TENANT_KEY") == "" || getenv("DATABASE_URL") == "" {
return errors.New("explicit input, tenant, governance database and confirmation required")
}
info, err := os.Lstat(args[0])
if err != nil || !info.Mode().IsRegular() || info.Mode().Perm()&0077 != 0 || info.Size() > 16<<20 {
return errors.New("input must be a private regular JSON file")
}
file, err := os.Open(args[0])
if err != nil {
return errors.New("input unavailable")
}
defer file.Close()
decoder := json.NewDecoder(io.LimitReader(file, (16<<20)+1))
decoder.DisallowUnknownFields()
var input qaopsorg.Import
if decoder.Decode(&input) != nil || decoder.Decode(&struct{}{}) != io.EOF {
return errors.New("input invalid")
}
if !input.Complete {
return qaopsorg.ErrInvalid
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
pool, err := pgxpool.New(ctx, getenv("DATABASE_URL"))
if err != nil {
return qaopsorg.ErrUnavailable
}
defer pool.Close()
store := qaopsorg.NewStore(pool, getenv("DOBOTAI_OPS_TENANT_KEY"))
saved, err := store.ReplaceDirectory(ctx, input)
if err != nil {
return err
}
active, err := store.GetView(ctx)
if err != nil || active.DirectoryID != saved.DirectoryID {
return qaopsorg.ErrConflict
}
return json.NewEncoder(out).Encode(map[string]any{"directory_id": active.DirectoryID, "source": active.DirectorySource, "synced_at": active.DirectorySyncedAt, "departments": len(active.View.Departments), "people": active.View.TotalPeople, "readback_verified": true})
}