package models import ( "encoding/json" "errors" "fmt" "io/fs" "os" "path/filepath" "github.com/rs/zerolog/log" ) const ( MainDir string = ".homeserver" ComposeFile string = "docker-compose.deploy.yml" EnvFile = ".env" NginxFile = "nginx.conf" ConfFile = "hmdeploy.json" ) var ErrProjectConfFile = errors.New("project error") func getFileInfo(baseDir, filePath string) (fs.FileInfo, error) { var fInf fs.FileInfo filePath = filepath.Clean(filePath) filePath = filepath.Join(baseDir, filePath) fileAbsPath, err := filepath.Abs(filePath) if err != nil { return fInf, fmt.Errorf("%w, file=%s, err=%v", ErrProjectConfFile, fileAbsPath, err) } fInf, err = os.Stat(fileAbsPath) if err != nil { return fInf, fmt.Errorf("%w, unable to stat file=%s, err=%v", ErrProjectConfFile, fileAbsPath, err) } return fInf, nil } type Project struct { Name string `json:"name"` Dir string ImageName string `json:"image"` Deps struct { EnvFile string `json:"env"` EnvFileInfo fs.FileInfo ComposeFile string `json:"compose"` ComposeFileInfo fs.FileInfo NginxFile string `json:"nginx"` NginxFileInfo fs.FileInfo } `json:"dependencies"` } func (p *Project) validate() error { cfs, err := getFileInfo(p.Dir, p.Deps.ComposeFile) if err != nil { return err } p.Deps.ComposeFileInfo = cfs if p.Deps.EnvFile != "" { efs, err := getFileInfo(p.Dir, p.Deps.EnvFile) if err != nil { return err } p.Deps.EnvFileInfo = efs } else { log.Warn().Msg("no .env file provided, hoping one it's set elsewhere...") } nfs, err := getFileInfo(p.Dir, p.Deps.NginxFile) if err != nil { return err } p.Deps.NginxFileInfo = nfs return nil } func ProjectFromDir(dir string) (Project, error) { var p Project dir = filepath.Join(dir, MainDir) p.Dir = dir content, err := os.ReadFile(filepath.Join(dir, ConfFile)) if err != nil { return p, fmt.Errorf("%w, unable to read conf file=%s, err=%v", ErrProjectConfFile, ConfFile, err) } if err := json.Unmarshal(content, &p); err != nil { return p, fmt.Errorf("%w, unable to parse conf file=%s, err=%v", ErrProjectConfFile, ConfFile, err) } if err := p.validate(); err != nil { return p, fmt.Errorf("%w, unable to validate project, name=%s, dir=%s, err=%v", ErrProjectConfFile, p.Name, p.Dir, err) } return p, nil }