Skip to content

Commit

Permalink
implements config migration
Browse files Browse the repository at this point in the history
Signed-off-by: Bruno Calza <brunoangelicalza@gmail.com>
  • Loading branch information
brunocalza committed Dec 15, 2023
1 parent f0e1bee commit 711e06c
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 15 deletions.
30 changes: 15 additions & 15 deletions cmd/vaults/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func newVaultCreateCommand() *cli.Command {
return fmt.Errorf("parse config: %s", err)
}

dir, err := defaultConfigLocation(cCtx.String("dir"))
dir, _, err := defaultConfigLocationV2(cCtx.String("dir"))
if err != nil {
return fmt.Errorf("default config location: %s", err)
}
Expand All @@ -106,12 +106,12 @@ func newVaultCreateCommand() *cli.Command {
_ = f.Close()
}()

cfg, err := loadConfig(path.Join(dir, "config.yaml"))
cfg, err := loadConfigV2(path.Join(dir, "config.yaml"))
if err != nil {
return fmt.Errorf("load config: %s", err)
}

cfg.Publications[pub] = publication{
cfg.Vaults[pub] = vault{
Host: pgConfig.Host,
Port: int(pgConfig.Port),
User: pgConfig.User,
Expand Down Expand Up @@ -170,22 +170,22 @@ func newStreamCommand() *cli.Command {
return err
}

dir, err := defaultConfigLocation(cCtx.String("dir"))
dir, _, err := defaultConfigLocationV2(cCtx.String("dir"))
if err != nil {
return fmt.Errorf("default config location: %s", err)
}

cfg, err := loadConfig(path.Join(dir, "config.yaml"))
cfg, err := loadConfigV2(path.Join(dir, "config.yaml"))
if err != nil {
return fmt.Errorf("load config: %s", err)
}

connString := fmt.Sprintf("postgres://%s:%s@%s:%d/%s",
cfg.Publications[vault].User,
cfg.Publications[vault].Password,
cfg.Publications[vault].Host,
cfg.Publications[vault].Port,
cfg.Publications[vault].Database,
cfg.Vaults[vault].User,
cfg.Vaults[vault].Password,
cfg.Vaults[vault].Host,
cfg.Vaults[vault].Port,
cfg.Vaults[vault].Database,
)

r, err := pgrepl.New(connString, pgrepl.Publication(rel))
Expand All @@ -198,7 +198,7 @@ func newStreamCommand() *cli.Command {
return err
}

bp := vaultsprovider.New(cfg.Publications[vault].ProviderHost)
bp := vaultsprovider.New(cfg.Vaults[vault].ProviderHost)

pgxConn, err := pgx.Connect(cCtx.Context, connString)
if err != nil {
Expand All @@ -225,7 +225,7 @@ func newStreamCommand() *cli.Command {

// Creates a new db manager when replication starts
dbDir := path.Join(dir, vault)
winSize := time.Duration(cfg.Publications[vault].WindowSize) * time.Second
winSize := time.Duration(cfg.Vaults[vault].WindowSize) * time.Second
uploader := app.NewVaultsUploader(ns, rel, bp, privateKey)
dbm := app.NewDBManager(dbDir, rel, cols, winSize, uploader)

Expand Down Expand Up @@ -284,17 +284,17 @@ func newWriteCommand() *cli.Command {
return err
}

dir, err := defaultConfigLocation(cCtx.String("dir"))
dir, _, err := defaultConfigLocationV2(cCtx.String("dir"))
if err != nil {
return fmt.Errorf("default config location: %s", err)
}

cfg, err := loadConfig(path.Join(dir, "config.yaml"))
cfg, err := loadConfigV2(path.Join(dir, "config.yaml"))
if err != nil {
return fmt.Errorf("load config: %s", err)
}

bp := vaultsprovider.New(cfg.Publications[vaultName].ProviderHost)
bp := vaultsprovider.New(cfg.Vaults[vaultName].ProviderHost)

filepath := cCtx.Args().First()

Expand Down
115 changes: 115 additions & 0 deletions cmd/vaults/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package main

import (
"errors"
"fmt"
"os"
"path"

"github.com/mitchellh/go-homedir"
"golang.org/x/exp/slog"
"gopkg.in/yaml.v3"
)

Expand All @@ -20,6 +22,10 @@ type config struct {
Publications map[string]publication `yaml:"publications"`
}

type configV2 struct {
Vaults map[string]vault `yaml:"vaults"`
}

type publication struct {
User string `yaml:"user"`
Password string `yaml:"password"`
Expand All @@ -30,12 +36,28 @@ type publication struct {
WindowSize int64 `yaml:"window_size"`
}

type vault struct {
User string `yaml:"user"`
Password string `yaml:"password"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Database string `yaml:"database"`
ProviderHost string `yaml:"provider_host"`
WindowSize int64 `yaml:"window_size"`
}

func newConfig() *config {
return &config{
Publications: make(map[string]publication),
}
}

func newConfigV2() *configV2 {
return &configV2{
Vaults: make(map[string]vault),
}
}

func loadConfig(path string) (*config, error) {
buf, err := os.ReadFile(path)
if err != nil {
Expand All @@ -50,6 +72,20 @@ func loadConfig(path string) (*config, error) {
return conf, nil
}

func loadConfigV2(path string) (*configV2, error) {
buf, err := os.ReadFile(path)
if err != nil {
return &configV2{}, err
}

conf := newConfigV2()
if err := yaml.Unmarshal(buf, conf); err != nil {
return &configV2{}, err
}

return conf, nil
}

func defaultConfigLocation(dir string) (string, error) {
if dir == "" {
// the default directory is home
Expand All @@ -73,3 +109,82 @@ func defaultConfigLocation(dir string) (string, error) {

return dir, nil
}

func defaultConfigLocationV2(dir string) (string, bool, error) {
if dir == "" {
// the default directory is home
var err error
dir, err = homedir.Dir()
if err != nil {
return "", false, fmt.Errorf("home dir: %s", err)
}

dir = path.Join(dir, ".vaults")
}

_, err := os.Stat(dir)
doesNotExist := os.IsNotExist(err)
if doesNotExist {
if err := os.Mkdir(dir, 0o755); err != nil {
return "", doesNotExist, fmt.Errorf("mkdir: %s", err)
}
} else if err != nil {
return "", doesNotExist, fmt.Errorf("is not exist: %s", err)
}

return dir, !doesNotExist, nil
}

func migrateConfigV1ToV2() {
dirV1, err := defaultConfigLocation("")
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}

dirV2, exists, err := defaultConfigLocationV2("")
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}

// create v2 config.yaml if necessary
f, err := os.OpenFile(path.Join(dirV2, "config.yaml"), os.O_RDWR|os.O_CREATE, 0o666)
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}
defer func() {
_ = f.Close()
}()

if exists {
return
}

// .basin/config.yaml does not exist, there's nothing to migrate
if _, err := os.Stat(path.Join(dirV1, "config.yaml")); errors.Is(err, os.ErrNotExist) {
return
}

cfgV1, err := loadConfig(path.Join(dirV1, "config.yaml"))
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}

cfgV2, err := loadConfigV2(path.Join(dirV2, "config.yaml"))
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}

for name, item := range cfgV1.Publications {
cfgV2.Vaults[name] = vault(item)
}

if err := yaml.NewEncoder(f).Encode(cfgV2); err != nil {
slog.Error(err.Error())
os.Exit(1)
}
}
3 changes: 3 additions & 0 deletions cmd/vaults/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
)

func main() {
// migrate v1 config to v2 config
migrateConfigV1ToV2()

cliApp := &cli.App{
Name: "vaults",
Usage: "Continuously publish data from your database to the Textile Vaults network.",
Expand Down

0 comments on commit 711e06c

Please sign in to comment.