Files
sunhpc-go/data/tmpls/tmpl.go
2026-02-20 18:44:43 +08:00

162 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package tmpls
import (
"embed"
_ "embed"
"errors"
"fmt"
"io/fs"
"path/filepath"
"strings"
)
// 核心:
// 1. 从嵌入的文件系统中读取指定目录下的单个配置文件内容
// 2. 检查文件是否存在
// 3. 读取文件内容
// 通配符说明:
// - db/*/*.yaml : 匹配data/一级子目录下的所有yaml文件.
// - 如需递归匹配子目录(如data/db/sub/*.yaml),用 data/**/*.yaml(Go.18+)
//
//go:embed db/*.yaml services/*.yaml firewall/*.yaml
var ConfigFS embed.FS
// GetConfigFile 获取指定目录下的的单个配置文件内容
//
// 参数:
// - dir : 目录名(db/services/firewall...)
// - name: 文件名(如base.yaml)
//
// 返回值:
// - []byte: YAML 文件的内容
// - error: 如果读取文件失败,返回错误信息
func GetConfigFile(dir, name string) ([]byte, error) {
// 拼接完整路径(基于tmpls.go所在的 data 目录)
fullPath := filepath.Join(dir, name)
// 检查文件是否存在(避免ReadFile直接报错)
_, err := fs.Stat(ConfigFS, fullPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("配置文件不存在: %s", fullPath)
}
return nil, fmt.Errorf("读取配置文件失败: %w", err)
}
// 读取文件内容
content, err := ConfigFS.ReadFile(fullPath)
if err != nil {
return nil, fmt.Errorf("读取配置文件内容失败: %w", err)
}
return content, nil
}
// GetConfigDir 获取指定目录下的所有配置文件内容
//
// 参数:
// - dir : 目录名(db/services/firewall...)
//
// 返回值:
// - map[string][]byte: 键为文件名(如base.yaml), 值为文件内容
// - error: 如果读取文件失败,返回错误信息
func GetConfigDir(dir string) (map[string][]byte, error) {
// 存储结果: key=文件名 value=文件内容
configMap := make(map[string][]byte)
// 遍历指定目录下的所有文件
err := fs.WalkDir(ConfigFS, dir,
func(path string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("遍历目录失败: %w", err)
}
// 跳过目录,只处理文件
if d.IsDir() {
return nil
}
// 只处理yaml文件(双重效验避免非yaml文件)
if !strings.HasSuffix(d.Name(), ".yaml") {
return nil
}
// 读取文件内容
content, err := ConfigFS.ReadFile(path)
if err != nil {
return fmt.Errorf("读取文件内容失败: %w", err)
}
// 存储: key用文件名(如base.yaml),而非完整路径.
configMap[d.Name()] = content
return nil
})
if err != nil {
return nil, err
}
return configMap, nil
}
// GetAllConfigDirs 获取所有嵌入目录(db/services/firewall...)的配置
//
// 返回值:
// - map[目录名]map[文件名]文件内容
// - error: 如果读取文件失败,返回错误信息
func GetAllConfigDirs() (map[string]map[string][]byte, error) {
allConfigs := make(map[string]map[string][]byte)
// 动态获取所有一级子目录(如db/services/firewall)
dirs, err := GetAllSubDirs()
if err != nil {
return nil, err
}
// 遍历所有嵌入目录
for _, dir := range dirs {
dirConfigs, err := GetConfigDir(dir)
if err != nil {
// 可选: 忽略空目录、错误目录,继续处理其他目录
// 如不需要、直接返回错误、return nil, err
continue
}
allConfigs[dir] = dirConfigs
}
return allConfigs, nil
}
// GetAllSubDirs 动态获取data/下的所有一级子目录
//
// 返回值:
// - []string: 所有一级子目录名(如db/services/firewall)
// - error: 如果读取目录失败,返回错误信息
func GetAllSubDirs() ([]string, error) {
var subDirs []string
// 遍历data/目录下的所有一级子目录
err := fs.WalkDir(ConfigFS, "",
func(path string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("遍历目录失败: %w", err)
}
// 过滤条件:
// 1. 是目录(d.IsDir())
// 2. 是一级子目录(path不含/,排除嵌套子目录如db/sub)
// 3. 排除根目录本身(path != "")
if d.IsDir() && !strings.Contains(path, "/") && path != "" {
subDirs = append(subDirs, path)
// 跳过该目录的子目录遍历(提升性能)
return fs.SkipDir
}
return nil
})
if err != nil {
return nil, err
}
return subDirs, nil
}