refactor: refactor project structure to use golang best practices
This commit is contained in:
parent
5b16cef525
commit
4ed6a61b1d
10 changed files with 617 additions and 702 deletions
97
internal/config/config.go
Normal file
97
internal/config/config.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/zalando/go-keyring"
|
||||
)
|
||||
|
||||
const (
|
||||
serviceName = "workctl"
|
||||
keySSHPassword = "ssh-password"
|
||||
keyRDPPassword = "rdp-password"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
SSHUser string `mapstructure:"SSH_USER"`
|
||||
SSHPassword string `mapstructure:"SSH_PASSWORD"`
|
||||
SSHHost string `mapstructure:"SSH_HOST"`
|
||||
JumpUser string `mapstructure:"JUMP_USER"`
|
||||
JumpHost string `mapstructure:"JUMP_HOST"`
|
||||
WorkstationHost string `mapstructure:"WORKSTATION_HOST"`
|
||||
WorkstationUser string `mapstructure:"WORKSTATION_USER"`
|
||||
WorkstationMac string `mapstructure:"WORKSTATION_MAC"`
|
||||
RDPUser string `mapstructure:"RDP_USER"`
|
||||
RDPPassword string `mapstructure:"RDP_PASSWORD"`
|
||||
WorkstationIP string `mapstructure:"WORKSTATION_IP"`
|
||||
SSHPort int `mapstructure:"SSH_PORT"`
|
||||
}
|
||||
|
||||
func Load() (Config, error) {
|
||||
var cfg Config
|
||||
configPath, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return cfg, fmt.Errorf("could not get user config dir: %w", err)
|
||||
}
|
||||
|
||||
workConfigPath := filepath.Join(configPath, "work")
|
||||
configFile := filepath.Join(workConfigPath, "config.toml")
|
||||
|
||||
if err := os.MkdirAll(workConfigPath, 0o750); err != nil {
|
||||
return cfg, fmt.Errorf("could not create config directory '%s': %w", workConfigPath, err)
|
||||
}
|
||||
|
||||
viper.SetConfigFile(configFile)
|
||||
viper.SetConfigType("toml")
|
||||
viper.AutomaticEnv()
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
||||
return cfg, fmt.Errorf("error reading config file '%s': %w", configFile, err)
|
||||
}
|
||||
slog.Debug(fmt.Sprintf("Config file '%s' not found, using defaults/env vars.", configFile))
|
||||
}
|
||||
|
||||
if err := viper.UnmarshalKey("default", &cfg); err != nil {
|
||||
if err := viper.Unmarshal(&cfg); err != nil {
|
||||
return cfg, fmt.Errorf("error decoding config from '%s': %w", configFile, err)
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.SSHPort == 0 {
|
||||
cfg.SSHPort = 22
|
||||
}
|
||||
|
||||
if cfg.SSHPassword == "" {
|
||||
if secret, err := GetSecret(keySSHPassword); err == nil {
|
||||
cfg.SSHPassword = secret
|
||||
slog.Debug("Loaded SSH password from keyring.")
|
||||
}
|
||||
}
|
||||
if cfg.RDPPassword == "" {
|
||||
if secret, err := GetSecret(keyRDPPassword); err == nil {
|
||||
cfg.RDPPassword = secret
|
||||
slog.Debug("Loaded RDP password from keyring.")
|
||||
}
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func GetSecret(key string) (string, error) {
|
||||
return keyring.Get(serviceName, key)
|
||||
}
|
||||
|
||||
func SetSecret(key, value string) error {
|
||||
if value == "" {
|
||||
return fmt.Errorf("secret cannot be empty")
|
||||
}
|
||||
return keyring.Set(serviceName, key, value)
|
||||
}
|
||||
|
||||
func KeySSHPassword() string { return keySSHPassword }
|
||||
func KeyRDPPassword() string { return keyRDPPassword }
|
||||
Loading…
Add table
Add a link
Reference in a new issue