rename

+2 -1
.gitignore
··· 5 .DS_Store 6 plc_cache\.tmp/* 7 plc_bundles* 8 - config.yaml
··· 5 .DS_Store 6 plc_cache\.tmp/* 7 plc_bundles* 8 + config.yaml 9 + atscand
+38 -7
Makefile
··· 1 - all: run 2 3 - run: 4 - go run cmd/atscanner.go -verbose 5 6 - clean-db: 7 - dropdb -U atscanner atscanner 8 - createdb atscanner -O atscanner 9 10 update-plcbundle: 11 - GOPROXY=direct go get -u github.com/atscan/plcbundle@latest
··· 1 + .PHONY: all build install test clean fmt lint help 2 + 3 + # Binary name 4 + BINARY_NAME=atscand 5 + INSTALL_PATH=$(GOPATH)/bin 6 + 7 + # Go commands 8 + GOCMD=go 9 + GOBUILD=$(GOCMD) build 10 + GOINSTALL=$(GOCMD) install 11 + GOCLEAN=$(GOCMD) clean 12 + GOTEST=$(GOCMD) test 13 + GOGET=$(GOCMD) get 14 + GOFMT=$(GOCMD) fmt 15 + GOMOD=$(GOCMD) mod 16 + GORUN=$(GOCMD) run 17 + 18 + # Default target 19 + all: build 20 + 21 + # Build the CLI tool 22 + build: 23 + @echo "Building $(BINARY_NAME)..." 24 + $(GOBUILD) -o $(BINARY_NAME) ./cmd/atscand 25 26 + # Install the CLI tool globally 27 + install: 28 + @echo "Installing $(BINARY_NAME)..." 29 + $(GOINSTALL) ./cmd/atscand 30 31 + run: 32 + $(GORUN) cmd/atscand/main.go -verbose 33 34 update-plcbundle: 35 + GOPROXY=direct go get -u github.com/atscan/plcbundle@latest 36 + 37 + # Show help 38 + help: 39 + @echo "Available targets:" 40 + @echo " make build - Build the binary" 41 + @echo " make install - Install binary globally" 42 + @echo " make run - Run app"
-159
cmd/atscanner.go
··· 1 - package main 2 - 3 - import ( 4 - "context" 5 - "flag" 6 - "fmt" 7 - "os" 8 - "os/signal" 9 - "syscall" 10 - "time" 11 - 12 - "github.com/atscan/atscanner/internal/api" 13 - "github.com/atscan/atscanner/internal/config" 14 - "github.com/atscan/atscanner/internal/log" 15 - "github.com/atscan/atscanner/internal/pds" 16 - "github.com/atscan/atscanner/internal/plc" 17 - "github.com/atscan/atscanner/internal/storage" 18 - "github.com/atscan/atscanner/internal/worker" 19 - ) 20 - 21 - const VERSION = "1.0.0" 22 - 23 - func main() { 24 - configPath := flag.String("config", "config.yaml", "path to config file") 25 - verbose := flag.Bool("verbose", false, "enable verbose logging") 26 - flag.Parse() 27 - 28 - // Load configuration 29 - cfg, err := config.Load(*configPath) 30 - if err != nil { 31 - fmt.Fprintf(os.Stderr, "Failed to load config: %v\n", err) 32 - os.Exit(1) 33 - } 34 - 35 - // Override verbose setting if flag is provided 36 - if *verbose { 37 - cfg.API.Verbose = true 38 - } 39 - 40 - // Initialize logger 41 - log.Init(cfg.API.Verbose) 42 - 43 - // Print banner 44 - log.Banner(VERSION) 45 - 46 - // Print configuration summary 47 - log.PrintConfig(map[string]string{ 48 - "Database Type": cfg.Database.Type, 49 - "Database Path": cfg.Database.Path, // Will be auto-redacted 50 - "PLC Directory": cfg.PLC.DirectoryURL, 51 - "PLC Scan Interval": cfg.PLC.ScanInterval.String(), 52 - "PLC Bundle Dir": cfg.PLC.BundleDir, 53 - "PLC Cache": fmt.Sprintf("%v", cfg.PLC.UseCache), 54 - "PLC Index DIDs": fmt.Sprintf("%v", cfg.PLC.IndexDIDs), 55 - "PDS Scan Interval": cfg.PDS.ScanInterval.String(), 56 - "PDS Workers": fmt.Sprintf("%d", cfg.PDS.Workers), 57 - "PDS Timeout": cfg.PDS.Timeout.String(), 58 - "API Host": cfg.API.Host, 59 - "API Port": fmt.Sprintf("%d", cfg.API.Port), 60 - "Verbose Logging": fmt.Sprintf("%v", cfg.API.Verbose), 61 - }) 62 - 63 - // Initialize database using factory pattern 64 - db, err := storage.NewDatabase(cfg.Database.Type, cfg.Database.Path) 65 - if err != nil { 66 - log.Fatal("Failed to initialize database: %v", err) 67 - } 68 - defer func() { 69 - log.Info("Closing database connection...") 70 - db.Close() 71 - }() 72 - 73 - // Set scan retention from config 74 - if cfg.PDS.ScanRetention > 0 { 75 - db.SetScanRetention(cfg.PDS.ScanRetention) 76 - log.Verbose("Scan retention set to %d scans per endpoint", cfg.PDS.ScanRetention) 77 - } 78 - 79 - // Run migrations 80 - if err := db.Migrate(); err != nil { 81 - log.Fatal("Failed to run migrations: %v", err) 82 - } 83 - 84 - ctx, cancel := context.WithCancel(context.Background()) 85 - defer cancel() 86 - 87 - // Initialize workers 88 - log.Info("Initializing scanners...") 89 - 90 - bundleManager, err := plc.NewBundleManager(cfg.PLC.BundleDir, cfg.PLC.DirectoryURL, db, cfg.PLC.IndexDIDs) 91 - if err != nil { 92 - log.Fatal("Failed to create bundle manager: %v", err) 93 - } 94 - defer bundleManager.Close() 95 - log.Verbose("✓ Bundle manager initialized (shared)") 96 - 97 - plcScanner := plc.NewScanner(db, cfg.PLC, bundleManager) 98 - defer plcScanner.Close() 99 - log.Verbose("✓ PLC scanner initialized") 100 - 101 - pdsScanner := pds.NewScanner(db, cfg.PDS) 102 - log.Verbose("✓ PDS scanner initialized") 103 - 104 - scheduler := worker.NewScheduler() 105 - 106 - // Schedule PLC directory scan 107 - scheduler.AddJob("plc_scan", cfg.PLC.ScanInterval, func() { 108 - if err := plcScanner.Scan(ctx); err != nil { 109 - log.Error("PLC scan error: %v", err) 110 - } 111 - }) 112 - log.Verbose("✓ PLC scan job scheduled (interval: %s)", cfg.PLC.ScanInterval) 113 - 114 - // Schedule PDS availability checks 115 - scheduler.AddJob("pds_scan", cfg.PDS.ScanInterval, func() { 116 - if err := pdsScanner.ScanAll(ctx); err != nil { 117 - log.Error("PDS scan error: %v", err) 118 - } 119 - }) 120 - log.Verbose("✓ PDS scan job scheduled (interval: %s)", cfg.PDS.ScanInterval) 121 - 122 - // Start API server 123 - log.Info("Starting API server on %s:%d...", cfg.API.Host, cfg.API.Port) 124 - apiServer := api.NewServer(db, cfg.API, cfg.PLC, bundleManager) 125 - go func() { 126 - if err := apiServer.Start(); err != nil { 127 - log.Fatal("API server error: %v", err) 128 - } 129 - }() 130 - 131 - // Give the API server a moment to start 132 - time.Sleep(100 * time.Millisecond) 133 - log.Info("✓ API server started successfully") 134 - log.Info("") 135 - log.Info("🚀 ATScanner is running!") 136 - log.Info(" API available at: http://%s:%d", cfg.API.Host, cfg.API.Port) 137 - log.Info(" Press Ctrl+C to stop") 138 - log.Info("") 139 - 140 - // Start scheduler 141 - scheduler.Start(ctx) 142 - 143 - // Wait for interrupt 144 - sigChan := make(chan os.Signal, 1) 145 - signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) 146 - <-sigChan 147 - 148 - log.Info("") 149 - log.Info("Shutting down gracefully...") 150 - cancel() 151 - 152 - log.Info("Stopping API server...") 153 - apiServer.Shutdown(context.Background()) 154 - 155 - log.Info("Waiting for active tasks to complete...") 156 - time.Sleep(2 * time.Second) 157 - 158 - log.Info("✓ Shutdown complete. Goodbye!") 159 - }
···
+1 -1
config.sample.yaml
··· 1 database: 2 type: "postgres" # or "sqlite" 3 - path: "postgres://atscanner:YOUR_PASSWORD@localhost:5432/atscanner?sslmode=disable" 4 # For SQLite: path: "atscan.db" 5 6 plc:
··· 1 database: 2 type: "postgres" # or "sqlite" 3 + path: "postgres://atscand:YOUR_PASSWORD@localhost:5432/atscand?sslmode=disable" 4 # For SQLite: path: "atscan.db" 5 6 plc:
+1 -1
go.mod
··· 1 - module github.com/atscan/atscanner 2 3 go 1.23.0 4
··· 1 + module github.com/atscan/atscand 2 3 go 1.23.0 4
+4 -4
internal/api/handlers.go
··· 11 "strings" 12 "time" 13 14 - "github.com/atscan/atscanner/internal/log" 15 - "github.com/atscan/atscanner/internal/monitor" 16 - "github.com/atscan/atscanner/internal/plc" 17 - "github.com/atscan/atscanner/internal/storage" 18 "github.com/atscan/plcbundle" 19 "github.com/gorilla/mux" 20 )
··· 11 "strings" 12 "time" 13 14 + "github.com/atscan/atscand/internal/log" 15 + "github.com/atscan/atscand/internal/monitor" 16 + "github.com/atscan/atscand/internal/plc" 17 + "github.com/atscan/atscand/internal/storage" 18 "github.com/atscan/plcbundle" 19 "github.com/gorilla/mux" 20 )
+4 -4
internal/api/server.go
··· 6 "net/http" 7 "time" 8 9 - "github.com/atscan/atscanner/internal/config" 10 - "github.com/atscan/atscanner/internal/log" 11 - "github.com/atscan/atscanner/internal/plc" 12 - "github.com/atscan/atscanner/internal/storage" 13 "github.com/gorilla/handlers" 14 "github.com/gorilla/mux" 15 )
··· 6 "net/http" 7 "time" 8 9 + "github.com/atscan/atscand/internal/config" 10 + "github.com/atscan/atscand/internal/log" 11 + "github.com/atscan/atscand/internal/plc" 12 + "github.com/atscan/atscand/internal/storage" 13 "github.com/gorilla/handlers" 14 "github.com/gorilla/mux" 15 )
+5 -5
internal/pds/scanner.go
··· 9 "time" 10 11 "github.com/acarl005/stripansi" 12 - "github.com/atscan/atscanner/internal/config" 13 - "github.com/atscan/atscanner/internal/ipinfo" 14 - "github.com/atscan/atscanner/internal/log" 15 - "github.com/atscan/atscanner/internal/monitor" 16 - "github.com/atscan/atscanner/internal/storage" 17 ) 18 19 type Scanner struct {
··· 9 "time" 10 11 "github.com/acarl005/stripansi" 12 + "github.com/atscan/atscand/internal/config" 13 + "github.com/atscan/atscand/internal/ipinfo" 14 + "github.com/atscan/atscand/internal/log" 15 + "github.com/atscan/atscand/internal/monitor" 16 + "github.com/atscan/atscand/internal/storage" 17 ) 18 19 type Scanner struct {
+2 -2
internal/plc/manager.go
··· 7 "sort" 8 "time" 9 10 - "github.com/atscan/atscanner/internal/log" 11 - "github.com/atscan/atscanner/internal/storage" 12 plcbundle "github.com/atscan/plcbundle" 13 ) 14
··· 7 "sort" 8 "time" 9 10 + "github.com/atscan/atscand/internal/log" 11 + "github.com/atscan/atscand/internal/storage" 12 plcbundle "github.com/atscan/plcbundle" 13 ) 14
+3 -3
internal/plc/scanner.go
··· 6 "strings" 7 "time" 8 9 - "github.com/atscan/atscanner/internal/config" 10 - "github.com/atscan/atscanner/internal/log" 11 - "github.com/atscan/atscanner/internal/storage" 12 ) 13 14 type Scanner struct {
··· 6 "strings" 7 "time" 8 9 + "github.com/atscan/atscand/internal/config" 10 + "github.com/atscan/atscand/internal/log" 11 + "github.com/atscan/atscand/internal/storage" 12 ) 13 14 type Scanner struct {
+1 -1
internal/storage/postgres.go
··· 7 "fmt" 8 "time" 9 10 - "github.com/atscan/atscanner/internal/log" 11 "github.com/jackc/pgx/v5" 12 "github.com/jackc/pgx/v5/pgxpool" 13 _ "github.com/jackc/pgx/v5/stdlib"
··· 7 "fmt" 8 "time" 9 10 + "github.com/atscan/atscand/internal/log" 11 "github.com/jackc/pgx/v5" 12 "github.com/jackc/pgx/v5/pgxpool" 13 _ "github.com/jackc/pgx/v5/stdlib"
+2 -2
internal/worker/scheduler.go
··· 5 "sync" 6 "time" 7 8 - "github.com/atscan/atscanner/internal/log" 9 - "github.com/atscan/atscanner/internal/monitor" 10 ) 11 12 type Job struct {
··· 5 "sync" 6 "time" 7 8 + "github.com/atscan/atscand/internal/log" 9 + "github.com/atscan/atscand/internal/monitor" 10 ) 11 12 type Job struct {
+2 -2
utils/migrate-ipinfo.sh
··· 4 # Configuration (edit these) 5 DB_HOST="localhost" 6 DB_PORT="5432" 7 - DB_NAME="atscanner" 8 - DB_USER="atscanner" 9 DB_PASSWORD="Noor1kooz5eeFai9leZagh5ua5eihai4" 10 11 # Colors for output
··· 4 # Configuration (edit these) 5 DB_HOST="localhost" 6 DB_PORT="5432" 7 + DB_NAME="atscand" 8 + DB_USER="atscand" 9 DB_PASSWORD="Noor1kooz5eeFai9leZagh5ua5eihai4" 10 11 # Colors for output