mirror of https://github.com/curusarn/resh
parent
439e60dab8
commit
bafb244588
@ -0,0 +1,46 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"os" |
||||||
|
|
||||||
|
"github.com/curusarn/resh/internal/cfg" |
||||||
|
"github.com/curusarn/resh/internal/logger" |
||||||
|
"go.uber.org/zap" |
||||||
|
) |
||||||
|
|
||||||
|
// info passed during build
|
||||||
|
var version string |
||||||
|
var commit string |
||||||
|
var developement bool |
||||||
|
|
||||||
|
func main() { |
||||||
|
errDo := doConfigSetup() |
||||||
|
config, errCfg := cfg.New() |
||||||
|
logger, _ := logger.New("config-setup", config.LogLevel, developement) |
||||||
|
defer logger.Sync() // flushes buffer, if any
|
||||||
|
|
||||||
|
if errDo != nil { |
||||||
|
logger.Error("Config setup failed", zap.Error(errDo)) |
||||||
|
// TODO: better error message for people
|
||||||
|
fmt.Fprintf(os.Stderr, "ERROR: %v\n", errDo) |
||||||
|
} |
||||||
|
if errCfg != nil { |
||||||
|
logger.Error("Error while getting configuration", zap.Error(errCfg)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func doConfigSetup() error { |
||||||
|
err := cfg.Touch() |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not touch config file: %w", err) |
||||||
|
} |
||||||
|
changes, err := cfg.Migrate() |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not migrate config file version: %v", err) |
||||||
|
} |
||||||
|
if changes { |
||||||
|
fmt.Printf("Config file format has changed - your config was updated to reflect the changes.\n") |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
@ -0,0 +1,110 @@ |
|||||||
|
package cfg |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"os" |
||||||
|
|
||||||
|
"github.com/BurntSushi/toml" |
||||||
|
) |
||||||
|
|
||||||
|
// Touch config file
|
||||||
|
func Touch() error { |
||||||
|
path, err := getConfigPath() |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not get config file path: %w", err) |
||||||
|
} |
||||||
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666) |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not open/create config file: %w", err) |
||||||
|
} |
||||||
|
err = file.Close() |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not close config file: %w", err) |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// Migrate old config versions to current config version
|
||||||
|
// returns true if any changes were made to the config
|
||||||
|
func Migrate() (bool, error) { |
||||||
|
path, err := getConfigPath() |
||||||
|
if err != nil { |
||||||
|
return false, fmt.Errorf("could not get config file path: %w", err) |
||||||
|
} |
||||||
|
configF, err := readConfig(path) |
||||||
|
if err != nil { |
||||||
|
return false, fmt.Errorf("could not read config: %w", err) |
||||||
|
} |
||||||
|
const current = "v1" |
||||||
|
if configF.ConfigVersion != nil && *configF.ConfigVersion == current { |
||||||
|
return false, nil |
||||||
|
} |
||||||
|
|
||||||
|
if configF.ConfigVersion == nil { |
||||||
|
configF, err = legacyToV1(configF) |
||||||
|
if err != nil { |
||||||
|
return true, fmt.Errorf("error converting config from version 'legacy' to 'v1': %w", err) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if *configF.ConfigVersion != current { |
||||||
|
return false, fmt.Errorf("unrecognized config version: '%s'", *configF.ConfigVersion) |
||||||
|
} |
||||||
|
err = writeConfig(configF, path) |
||||||
|
if err != nil { |
||||||
|
return true, fmt.Errorf("could not write migrated config: %w", err) |
||||||
|
} |
||||||
|
return true, nil |
||||||
|
} |
||||||
|
|
||||||
|
func writeConfig(config *configFile, path string) error { |
||||||
|
file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0666) |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not open config for writing: %w", err) |
||||||
|
} |
||||||
|
defer file.Close() |
||||||
|
err = toml.NewEncoder(file).Encode(config) |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not encode config: %w", err) |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func legacyToV1(config *configFile) (*configFile, error) { |
||||||
|
if config.ConfigVersion != nil { |
||||||
|
return nil, fmt.Errorf("config version is not 'legacy': '%s'", *config.ConfigVersion) |
||||||
|
} |
||||||
|
version := "v1" |
||||||
|
newConf := configFile{ |
||||||
|
ConfigVersion: &version, |
||||||
|
} |
||||||
|
// Remove defaults
|
||||||
|
if config.Port != nil && *config.Port != 2627 { |
||||||
|
newConf.Port = config.Port |
||||||
|
} |
||||||
|
if config.SesswatchPeriodSeconds != nil && *config.SesswatchPeriodSeconds != 120 { |
||||||
|
newConf.SesswatchPeriodSeconds = config.SesswatchPeriodSeconds |
||||||
|
} |
||||||
|
if config.SesshistInitHistorySize != nil && *config.SesshistInitHistorySize != 1000 { |
||||||
|
newConf.SesshistInitHistorySize = config.SesshistInitHistorySize |
||||||
|
} |
||||||
|
if config.BindControlR != nil && *config.BindControlR != true { |
||||||
|
newConf.BindControlR = config.BindControlR |
||||||
|
} |
||||||
|
if config.Debug != nil && *config.Debug != false { |
||||||
|
newConf.Debug = config.Debug |
||||||
|
} |
||||||
|
return &newConf, nil |
||||||
|
} |
||||||
|
|
||||||
|
// func v1ToV2(config *configFile) (*configFile, error) {
|
||||||
|
// if *config.ConfigVersion != "v1" {
|
||||||
|
// return nil, fmt.Errorf("config version is not 'legacy': '%s'", *config.ConfigVersion)
|
||||||
|
// }
|
||||||
|
// version := "v2"
|
||||||
|
// newConf := configFile{
|
||||||
|
// ConfigVersion: &version,
|
||||||
|
// // Here goes all config fields - no need to prune defaults like we do for legacy
|
||||||
|
// }
|
||||||
|
// return &newConf, nil
|
||||||
|
// }
|
||||||
Loading…
Reference in new issue