148 lines
3.6 KiB
Go
148 lines
3.6 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
const (
|
|
BaseDir string = "/etc/sunhpc"
|
|
LogDir string = "/var/log/sunhpc"
|
|
TmplDir string = BaseDir + "/tmpl.d"
|
|
appName string = "sunhpc"
|
|
defaultDBPath string = "/var/lib/sunhpc"
|
|
defaultDBName string = "sunhpc.db"
|
|
)
|
|
|
|
type Config struct {
|
|
DB DBConfig `yaml:"db"`
|
|
Log LogConfig `yaml:"log"`
|
|
Cluster ClusterConfig `yaml:"cluster"`
|
|
}
|
|
|
|
type DBConfig struct {
|
|
Type string `yaml:"type"`
|
|
Path string `yaml:"path"` // SQLite: 目录路径
|
|
Name string `yaml:"name"` // SQLite: 文件名
|
|
User string `yaml:"user"`
|
|
Password string `yaml:"password"`
|
|
Host string `yaml:"host"`
|
|
Port int `yaml:"port"`
|
|
Socket string `yaml:"socket"`
|
|
Verbose bool `yaml:"verbose"`
|
|
}
|
|
|
|
type LogConfig struct {
|
|
Level string `yaml:"level"`
|
|
Format string `yaml:"format"`
|
|
Output string `yaml:"output"`
|
|
FilePath string `yaml:"file_path"`
|
|
}
|
|
|
|
type ClusterConfig struct {
|
|
Name string `yaml:"name"`
|
|
AdminEmail string `yaml:"admin_email"`
|
|
TimeZone string `yaml:"time_zone"`
|
|
NodePrefix string `yaml:"node_prefix"`
|
|
}
|
|
|
|
// LoadConfig loads configuration with the following precedence:
|
|
// 优先级排序:
|
|
// 1. 环境变量 (prefix: SUNHPC_)
|
|
// 2. ~/.sunhpc.yaml
|
|
// 3. ./sunhpc.yaml
|
|
// 4. /etc/sunhpc/sunhpc.yaml
|
|
// 5. Default values
|
|
/*
|
|
示例配置文件:
|
|
```yaml
|
|
db:
|
|
type: sqlite
|
|
name: sunhpc.db
|
|
path: /var/lib/sunhpc
|
|
socket: /var/lib/sunhpc/mysql/mysqld.sock
|
|
user: root
|
|
password: ""
|
|
host: localhost
|
|
```
|
|
|
|
环境变量配置示例:
|
|
```bash
|
|
export SUNHPC_DATABASE_TYPE=mysql
|
|
export SUNHPC_DATABASE_NAME=sunhpc
|
|
export SUNHPC_DATABASE_USER=root
|
|
export SUNHPC_DATABASE_PASSWORD=123456
|
|
export SUNHPC_DATABASE_HOST=localhost
|
|
```
|
|
*/
|
|
func LoadConfig() (*Config, error) {
|
|
v := viper.New()
|
|
|
|
// Step 1: 设置默认值(最低优先级)
|
|
v.SetDefault("db.type", "sqlite")
|
|
v.SetDefault("db.name", "sunhpc.db")
|
|
v.SetDefault("db.path", "/var/lib/sunhpc")
|
|
v.SetDefault("db.socket", "/var/lib/sunhpc/mysql/mysqld.sock")
|
|
v.SetDefault("db.user", "")
|
|
v.SetDefault("db.password", "")
|
|
v.SetDefault("db.host", "localhost")
|
|
v.SetDefault("db.port", 3306)
|
|
v.SetDefault("db.verbose", false)
|
|
|
|
// Step 2: 启用环境变量(高优先级)
|
|
v.SetEnvPrefix("SUNHPC") // e.g., SUNHPC_DATABASE_NAME
|
|
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // db.type -> SUNHPC_DB_TYPE
|
|
v.AutomaticEnv() // Auto bind env vars matching config keys
|
|
|
|
// Step 3: 按优先级从高到低加载配置文件
|
|
// 优先级: env > ./sunhpc.yaml > ~/.sunhpc.yaml > /etc/sunhpc/sunhpc.yaml > defaults
|
|
configFiles := []string{
|
|
"./sunhpc.yaml",
|
|
filepath.Join(os.Getenv("HOME"), ".sunhpc.yaml"),
|
|
filepath.Join(BaseDir, "sunhpc.yaml"),
|
|
}
|
|
|
|
var configFile string
|
|
for _, cfgFile := range configFiles {
|
|
if _, err := os.Stat(cfgFile); err == nil {
|
|
configFile = cfgFile
|
|
break // 找到第一个就停止.
|
|
}
|
|
}
|
|
|
|
// 如果找到配置文件,就加载它.
|
|
if configFile != "" {
|
|
v.SetConfigFile(configFile)
|
|
if err := v.ReadInConfig(); err != nil {
|
|
return nil, fmt.Errorf("加载配置文件 %s 失败: %w", configFile, err)
|
|
}
|
|
}
|
|
|
|
// 解码到结构体
|
|
var cfg Config
|
|
if err := v.Unmarshal(&cfg); err != nil {
|
|
return nil, fmt.Errorf("解码配置到结构体失败: %w", err)
|
|
}
|
|
|
|
return &cfg, nil
|
|
}
|
|
|
|
// InitDirs 创建所有必需目录
|
|
func InitDirs() error {
|
|
dirs := []string{
|
|
BaseDir,
|
|
TmplDir,
|
|
LogDir,
|
|
}
|
|
for _, d := range dirs {
|
|
if err := os.MkdirAll(d, 0755); err != nil {
|
|
return fmt.Errorf("创建目录 %s 失败: %w", d, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|