mirror of
https://github.com/tiennm99/keepalive.git
synced 2026-10-11 03:13:31 +00:00
fix(config): discover mounted yml config
This commit is contained in:
1 parent
9a69030179
commit
08da9dcb84
4 files changed
+68
-4
No files matched your search
@@ -8,7 +8,7 @@ Successor to the `*-keepalive` family: one binary, one image, six datastore adap
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
By default, keepalive reads `keepalive.yaml` from the current working directory. One deployment can keep any number of services alive.
|
By default, keepalive reads the first config file it finds: `keepalive.yaml`, `keepalive.yml`, `/keepalive.yaml`, then `/keepalive.yml`. One deployment can keep any number of services alive.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
interval: 1m
|
interval: 1m
|
||||||
@@ -66,6 +66,8 @@ docker run -d --name keepalive --restart unless-stopped \
|
|||||||
keepalive:local
|
keepalive:local
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If your host config file is named `keepalive.yml`, mount it to `/keepalive.yml` instead.
|
||||||
|
|
||||||
## Quick start (local)
|
## Quick start (local)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -18,6 +19,13 @@ const (
|
|||||||
defaultCounterKey = "counter"
|
defaultCounterKey = "counter"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultConfigFiles = []string{
|
||||||
|
"keepalive.yaml",
|
||||||
|
"keepalive.yml",
|
||||||
|
"/keepalive.yaml",
|
||||||
|
"/keepalive.yml",
|
||||||
|
}
|
||||||
|
|
||||||
type appConfig struct {
|
type appConfig struct {
|
||||||
Interval string `json:"interval" yaml:"interval"`
|
Interval string `json:"interval" yaml:"interval"`
|
||||||
CounterKey string `json:"counter_key" yaml:"counter_key"`
|
CounterKey string `json:"counter_key" yaml:"counter_key"`
|
||||||
@@ -52,6 +60,21 @@ func loadConfigFile(path string) ([]serviceConfig, error) {
|
|||||||
return normalizeConfig(raw)
|
return normalizeConfig(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultConfigFile() (string, error) {
|
||||||
|
return firstExistingConfigFile(defaultConfigFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func firstExistingConfigFile(paths []string) (string, error) {
|
||||||
|
for _, path := range paths {
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
return path, nil
|
||||||
|
} else if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("config file not found (looked for: %s)", strings.Join(paths, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
func normalizeConfig(raw appConfig) ([]serviceConfig, error) {
|
func normalizeConfig(raw appConfig) ([]serviceConfig, error) {
|
||||||
if len(raw.Services) == 0 {
|
if len(raw.Services) == 0 {
|
||||||
return nil, fmt.Errorf("services must contain at least one service")
|
return nil, fmt.Errorf("services must contain at least one service")
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -35,6 +38,39 @@ func TestKeepaliveExampleConfigParses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFirstExistingConfigFileFindsYMLFallback(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
ymlPath := filepath.Join(dir, "keepalive.yml")
|
||||||
|
if err := os.WriteFile(ymlPath, []byte("services: []\n"), 0o600); err != nil {
|
||||||
|
t.Fatalf("write config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := firstExistingConfigFile([]string{
|
||||||
|
filepath.Join(dir, "keepalive.yaml"),
|
||||||
|
ymlPath,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("firstExistingConfigFile returned error: %v", err)
|
||||||
|
}
|
||||||
|
if got != ymlPath {
|
||||||
|
t.Fatalf("firstExistingConfigFile() = %q, want %q", got, ymlPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirstExistingConfigFileReportsCandidates(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
_, err := firstExistingConfigFile([]string{
|
||||||
|
filepath.Join(dir, "keepalive.yaml"),
|
||||||
|
filepath.Join(dir, "keepalive.yml"),
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("firstExistingConfigFile returned nil error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "keepalive.yaml") || !strings.Contains(err.Error(), "keepalive.yml") {
|
||||||
|
t.Fatalf("error %q does not list expected candidates", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNormalizeConfigSuffixesDuplicateGeneratedNames(t *testing.T) {
|
func TestNormalizeConfigSuffixesDuplicateGeneratedNames(t *testing.T) {
|
||||||
services, err := normalizeConfig(appConfig{
|
services, err := normalizeConfig(appConfig{
|
||||||
Services: []serviceFileConfig{
|
Services: []serviceFileConfig{
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ import (
|
|||||||
"github.com/tiennm99/keepalive/adapter"
|
"github.com/tiennm99/keepalive/adapter"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultConfigFile = "keepalive.yaml"
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
services, err := loadConfigFile(defaultConfigFile)
|
configPath, err := defaultConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("load config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
services, err := loadConfigFile(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("load config: %v", err)
|
log.Fatalf("load config: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user