added means of locating config files in standard places per operating system

This commit is contained in:
2026-03-03 23:12:38 -07:00
parent dee77d6f71
commit 7ccbbe2099
4 changed files with 105 additions and 8 deletions
+40 -8
View File
@@ -14,7 +14,9 @@ import (
_ "embed"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"regexp"
"strconv"
@@ -30,6 +32,9 @@ const AMSTERDAM_VERSION = "0.0.1"
// AMSTERDAM_COPYRIGHT contains the copyright dates for Amsterdam.
const AMSTERDAM_COPYRIGHT = "2025-2026"
// CONFIGFILE_NAME is the name of the standard configuration file.
const CONFIGFILE_NAME = "amsterdam.yaml"
// AmCLI is the command-line interface arguments structure.
type AmCLI struct {
ConfigFile string `arg:"-C,--config,env:AMSTERDAM_CONFIG" help:"Location of the configuration file."`
@@ -126,9 +131,10 @@ type AmConfig struct {
} `yaml:"tuning"`
}
// AmConfigComputed is the configuration values which are "computed" based only on values in AmConfig.
type AmConfigComputed struct {
UploadMaxSize int32
UploadNoCompress map[string]bool
UploadMaxSize int32 // maximum upload size in bytes
UploadNoCompress map[string]bool // which upload types are not compressed?
}
//go:embed default.yaml
@@ -150,6 +156,28 @@ func init() {
}
}
// locateConfigFile locates and opens the Amsterdam configuration file, if it exists.
func locateConfigFile() (string, *os.File) {
// first, check the one on the command line (or in the environment)
if CommandLine.ConfigFile != "" {
f, err := os.Open(CommandLine.ConfigFile)
if err == nil {
return CommandLine.ConfigFile, f
}
}
// now, check the OS-specific configuration file directories
dirs := configFileDirs()
for _, d := range dirs {
p := filepath.Join(d, CONFIGFILE_NAME)
f, err := os.Open(p)
if err == nil {
return p, f
}
}
// finally, punt and just use the defaults
return "", nil
}
// overlayStructValue overlays the "loaded" and "defaults" structure onto the "dest" structure. All parameters are AmConfig structures.
func overlayStructValue(dest, loaded, defaults reflect.Value) {
typ := dest.Type()
@@ -211,7 +239,7 @@ func parseDataSize(s string) (int32, error) {
}
m := re.FindStringSubmatch(s)
if m == nil {
return -1, errors.New("invalid value spacified")
return -1, errors.New("invalid value specified")
}
rc, err := strconv.Atoi(m[1])
if err != nil {
@@ -236,18 +264,22 @@ func SetupConfig() {
log.Warn("WARNING: --buggy-attachments flag set - NOT recommended for production usage")
}
if CommandLine.ConfigFile != "" {
// load the data and use it to unmarshal the loaded configuration
data, err := os.ReadFile(CommandLine.ConfigFile)
// Locate and read the Amsterdam configuration file.
name, file := locateConfigFile()
if file != nil {
log.Infof("SetupConfig(): using config file %s", name)
data, err := io.ReadAll(file)
file.Close()
if err != nil {
panic(fmt.Sprintf("unable to load configuration file %s: %v", CommandLine.ConfigFile, err))
panic(fmt.Sprintf("unable to load configuration file %s: %v", name, err))
}
var loadedConfig AmConfig
if err = yaml.Unmarshal(data, &loadedConfig); err != nil {
panic(fmt.Sprintf("unable to load configuration file %s: %v", CommandLine.ConfigFile, err))
panic(fmt.Sprintf("unable to load configuration file %s: %v", name, err))
}
overlayStructValue(reflect.ValueOf(&GlobalConfig).Elem(), reflect.ValueOf(&loadedConfig).Elem(), reflect.ValueOf(&defaultConfig).Elem())
} else {
log.Info("SetupConfig(): using default configs only")
GlobalConfig = defaultConfig // just copy over the defaults
}
+21
View File
@@ -0,0 +1,21 @@
//go:build darwin
/*
* Amsterdam Web Communities System
* Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// Package config contains support for Amsterdam site-wide configuration data.
package config
// configFileDirs returns the directories where an Amsterdam config file may be located.
func configFileDirs() []string {
// this variant is for Apple macOS
rc := make([]string, 0, 2)
rc = append(rc, "/usr/local/etc/amsterdam", "/Library/Application Support/Amsterdam")
return rc
}
+21
View File
@@ -0,0 +1,21 @@
//go:build unix && !darwin
/*
* Amsterdam Web Communities System
* Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// Package config contains support for Amsterdam site-wide configuration data.
package config
// configFileDirs returns the directories where an Amsterdam config file may be located.
func configFileDirs() []string {
// this variant is for non-macOS Unix systems (Linux, *BSD, etc.)
rc := make([]string, 0, 3)
rc = append(rc, "/usr/local/etc/amsterdam", "/etc/amsterdam", "/etc/xdg/amsterdam")
return rc
}
+23
View File
@@ -0,0 +1,23 @@
//go:build windows
/*
* Amsterdam Web Communities System
* Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// Package config contains support for Amsterdam site-wide configuration data.
package config
import "os"
// configFileDirs returns the directories where an Amsterdam config file may be located.
func configFileDirs() []string {
// this variant is for Micro$oft Windows
rc := make([]string, 0, 1)
rc = append(rc, os.ExpandEnv("${PROGRAMDATA}\\\\amsterdam"))
return rc
}