Wersja inicjalna

This commit is contained in:
Arkadiusz Rychliński
2022-11-08 11:16:29 +01:00
commit 3d21c4f1c2
11 changed files with 522 additions and 0 deletions

75
cfg/config.go Normal file
View File

@ -0,0 +1,75 @@
package cfg
import (
"encoding/json"
"fmt"
"os"
)
type Connection struct {
Host string `json:"Host,omitempty"`
User string `json:"User,omitempty"`
Port uint `json:"Port,omitempty"`
DbName string `json:"DbName,omitempty"`
}
type Config struct {
PassFile string `json:"Passfile"`
PsqlExec string `json:"PsqlExec"`
SqlDir string `json:"SqlDir"`
Defaults Connection `json:"Defaults"`
Connections []Connection `json:"Connections"`
}
func GetConfig(params Parameters) (config Config, err error) {
bytes, err := os.ReadFile(params.ConfigFile)
if err != nil {
return config, fmt.Errorf("błąd odczytu pliku konfiguracji: %w", err)
}
err = json.Unmarshal(bytes, &config)
if err != nil {
return config, fmt.Errorf("błąd parsowania pliku konfiguracji: %w", err)
}
if config.PassFile == "" && params.Passfile != "" {
config.PassFile = params.Passfile
}
if config.PassFile == "" {
return config, fmt.Errorf("nie podano Passfile (dodaj w konfiguracji lub użyj flag --passfile)")
}
if config.SqlDir == "" && params.SqlDir != "" {
config.SqlDir = params.SqlDir
}
err = fixConnections(&config)
return config, err
}
func fixConnections(config *Config) error {
def := config.Defaults
for i := range config.Connections {
con := &config.Connections[i]
if con.DbName == "" {
con.DbName = def.DbName
}
if con.User == "" {
con.User = def.User
}
if con.Host == "" {
con.Host = def.Host
}
if con.Port == 0 {
if def.Port != 0 {
con.Port = def.Port
} else {
con.Port = 5432 // domyślny dla PostgreSQL
}
}
if con.DbName == "" || con.Host == "" || con.User == "" {
return fmt.Errorf("opis połączenia z pozycji %d jest niekompletny: %#v", i+1, con)
}
}
return nil
}

112
cfg/params.go Normal file
View File

@ -0,0 +1,112 @@
package cfg
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"os"
)
type Parameters struct {
Verbose bool
ConfigFile string
Passfile string
OutDir string
SqlDir string
}
var params Parameters
func init() {
flag.BoolVar(&params.Verbose, "verbose", false, "Dodatkowe komunkaty diagnostyczne")
flag.StringVar(&params.ConfigFile, "config", "multisql.conf", "Plik konfiguracji")
flag.StringVar(&params.Passfile, "passfile", "", "Plik pgpass z hasłami do baz")
flag.StringVar(&params.OutDir, "outdir", "", "Katalog (istniejący i z prawem do zapisu), do którego generowane są wyniki")
flag.StringVar(&params.SqlDir, "sqldir", "scripts", "Katalog, w którym znajdują się skrypty do uruchomienia")
flag.Usage = printUsage
flag.Parse()
}
func GetParams() Parameters {
return params
}
func printUsage() {
fmt.Fprintf(os.Stderr,
`
multisql - uruchamia zestaw skryptów na skonfigurowanej liście baz danych.
Program, dla każdej z baz wskazanych w konfiguracji, uruchamia kolejno każdy
z plików sql wskazanych parametrem lub w pliku konfiguracji poprzez
uruchomienie narzędzia psql:
psql -f skrypt.sql -w -L log.txt _szczegóły_połaczenia_ 2>stderr.txt > stdout.txt
Skrypty mogą mieć dowolne rozszerzenia ale podkatalogi nie są obsługiwane.
Pliki wynikowe zapisywane są do katalogu wskazanego w outdir w strukturze o postaci
output:
-> data-godzina-pid
-> host-port-baza-user
-> skrypt.sql
-> log.txt
-> stdout.txt
-> stderr.txt
Użycie:
multisql -outdir /tmp -sqldir /data/skrypty -passfile ./hasla
Opis flag:
`,
)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr,
`
Plik passfile ma standardowy format .pgpass PostgreSQLa.
Plik multisql.conf ma format JSON, np:
> `,
)
c := Config{
PassFile: "mypgpass",
PsqlExec: "/usr/local/bin/psql",
SqlDir: "/data/skrypty-sql",
Defaults: Connection{
Port: 5433,
User: "myapp",
DbName: "moja-db",
},
Connections: []Connection{
{
Host: "10.20.30.01",
},
{
Host: "10.20.30.02",
DbName: "innadb",
User: "innyuser",
},
},
}
b, _ := json.Marshal(&c)
var out bytes.Buffer
_ = json.Indent(&out, b, "> ", "\t")
_, _ = out.WriteTo(os.Stderr)
fmt.Fprintln(os.Stderr, `
PsqlExec jest opcjonalny - jesli nie zostanie podany wyszukuje się programu psql.exe w PATH.
Każde połączenie w tablicy Connections może zawierać Host, Port, User i DbName.
Brakujące wartości są uzupełniane z sekcji Defaults (która ma taki sam
format jak obiekt w Connections).
Parametry mają pierwszeństwo przed wartościami w konfiguracji.
Format pliku passfile jest następujący:
hostname:port:database:username:password
W szczególach opisano go na https://www.postgresql.org/docs/current/libpq-pgpass.html.`)
}