forked from toolshed/abra
.gitea
cli
cmd
pkg
app
autocomplete
catalogue
client
compose
config
app.go
app_test.go
env.go
env_test.go
container
context
dns
git
limit
recipe
secret
server
ssh
upstream
web
scripts
tests
.drone.yml
.envrc.sample
.gitignore
.goreleaser.yml
Makefile
README.md
go.mod
go.sum
renovate.json
168 lines
3.9 KiB
Go
168 lines
3.9 KiB
Go
package config
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io/fs"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/Autonomic-Cooperative/godotenv"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var ABRA_DIR = os.ExpandEnv("$HOME/.abra")
|
|
var ABRA_SERVER_FOLDER = path.Join(ABRA_DIR, "servers")
|
|
var APPS_JSON = path.Join(ABRA_DIR, "apps.json")
|
|
var APPS_DIR = path.Join(ABRA_DIR, "apps")
|
|
var REPOS_BASE_URL = "https://git.coopcloud.tech/coop-cloud"
|
|
|
|
// GetServers retrieves all servers.
|
|
func GetServers() ([]string, error) {
|
|
var servers []string
|
|
|
|
servers, err := getAllFoldersInDirectory(ABRA_SERVER_FOLDER)
|
|
if err != nil {
|
|
return servers, err
|
|
}
|
|
|
|
logrus.Debugf("retrieved '%v' servers: '%s'", len(servers), servers)
|
|
|
|
return servers, nil
|
|
}
|
|
|
|
// ReadEnv loads an app envivornment into a map.
|
|
func ReadEnv(filePath string) (AppEnv, error) {
|
|
var envFile AppEnv
|
|
|
|
envFile, err := godotenv.Read(filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
logrus.Debugf("read '%s' from '%s'", envFile, filePath)
|
|
|
|
return envFile, nil
|
|
}
|
|
|
|
// ReadServerNames retrieves all server names.
|
|
func ReadServerNames() ([]string, error) {
|
|
serverNames, err := getAllFoldersInDirectory(ABRA_SERVER_FOLDER)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
logrus.Debugf("read '%s' from '%s'", strings.Join(serverNames, ","), ABRA_SERVER_FOLDER)
|
|
|
|
return serverNames, nil
|
|
}
|
|
|
|
// getAllFilesInDirectory returns filenames of all files in directory
|
|
func getAllFilesInDirectory(directory string) ([]fs.FileInfo, error) {
|
|
var realFiles []fs.FileInfo
|
|
|
|
files, err := ioutil.ReadDir(directory)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, file := range files {
|
|
// Follow any symlinks
|
|
filePath := path.Join(directory, file.Name())
|
|
|
|
if filepath.Ext(strings.TrimSpace(filePath)) != ".env" {
|
|
continue
|
|
}
|
|
|
|
realPath, err := filepath.EvalSymlinks(filePath)
|
|
if err != nil {
|
|
logrus.Warningf("broken symlink in your abra config folders: '%s'", filePath)
|
|
} else {
|
|
realFile, err := os.Stat(realPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !realFile.IsDir() {
|
|
realFiles = append(realFiles, file)
|
|
}
|
|
}
|
|
}
|
|
|
|
return realFiles, nil
|
|
}
|
|
|
|
// getAllFoldersInDirectory returns both folder and symlink paths
|
|
func getAllFoldersInDirectory(directory string) ([]string, error) {
|
|
var folders []string
|
|
|
|
files, err := ioutil.ReadDir(directory)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(files) == 0 {
|
|
return nil, fmt.Errorf("directory is empty: '%s'", directory)
|
|
}
|
|
|
|
for _, file := range files {
|
|
// Check if file is directory or symlink
|
|
if file.IsDir() || file.Mode()&fs.ModeSymlink != 0 {
|
|
filePath := path.Join(directory, file.Name())
|
|
realDir, err := filepath.EvalSymlinks(filePath)
|
|
if err != nil {
|
|
logrus.Warningf("broken symlink in your abra config folders: '%s'", filePath)
|
|
} else if stat, err := os.Stat(realDir); err == nil && stat.IsDir() {
|
|
// path is a directory
|
|
folders = append(folders, file.Name())
|
|
}
|
|
}
|
|
}
|
|
|
|
return folders, nil
|
|
}
|
|
|
|
// EnsureAbraDirExists checks for the abra config folder and throws error if not
|
|
func EnsureAbraDirExists() error {
|
|
if _, err := os.Stat(ABRA_DIR); os.IsNotExist(err) {
|
|
logrus.Debugf("'%s' does not exist, creating it", ABRA_DIR)
|
|
if err := os.Mkdir(ABRA_DIR, 0777); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ReadAbraShEnvVars reads env vars from an abra.sh recipe file.
|
|
func ReadAbraShEnvVars(abraSh string) (map[string]string, error) {
|
|
envVars := make(map[string]string)
|
|
|
|
file, err := os.Open(abraSh)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return envVars, nil
|
|
}
|
|
return envVars, err
|
|
}
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if strings.Contains(line, "export") {
|
|
splitVals := strings.Split(line, "export ")
|
|
envVarDef := splitVals[len(splitVals)-1]
|
|
keyVal := strings.Split(envVarDef, "=")
|
|
if len(keyVal) != 2 {
|
|
return envVars, fmt.Errorf("couldn't parse %s", line)
|
|
}
|
|
envVars[keyVal[0]] = keyVal[1]
|
|
}
|
|
}
|
|
|
|
logrus.Debugf("read '%s' from '%s'", envVars, abraSh)
|
|
|
|
return envVars, nil
|
|
}
|