search for configuration file in various paths, print paths if configuration is not found (#1993) (#2276) (#2357)

This commit is contained in:
Alessandro Ros 2023-09-16 22:14:13 +02:00 committed by GitHub
parent 64d9060560
commit f2f417e451
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 45 deletions

View File

@ -4,7 +4,6 @@ package conf
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"sort"
@ -32,50 +31,53 @@ func getSortedKeys(paths map[string]*PathConf) []string {
return ret
}
func loadFromFile(fpath string, conf *Conf) (bool, error) {
if fpath == "mediamtx.yml" {
// give priority to the legacy configuration file, in order not to break
// existing setups
if _, err := os.Stat("rtsp-simple-server.yml"); err == nil {
fpath = "rtsp-simple-server.yml"
func firstThatExists(paths []string) string {
for _, pa := range paths {
_, err := os.Stat(pa)
if err == nil {
return pa
}
}
return ""
}
// mediamtx.yml is optional
// other configuration files are not
if fpath == "mediamtx.yml" || fpath == "rtsp-simple-server.yml" {
if _, err := os.Stat(fpath); errors.Is(err, os.ErrNotExist) {
// load defaults
func loadFromFile(fpath string, defaultConfPaths []string, conf *Conf) (string, error) {
if fpath == "" {
fpath = firstThatExists(defaultConfPaths)
// when the configuration file is not explicitly set,
// it is optional. Load defaults.
if fpath == "" {
conf.UnmarshalJSON(nil) //nolint:errcheck
return false, nil
return "", nil
}
}
byts, err := os.ReadFile(fpath)
if err != nil {
return true, err
return "", err
}
if key, ok := os.LookupEnv("RTSP_CONFKEY"); ok { // legacy format
byts, err = decrypt.Decrypt(key, byts)
if err != nil {
return true, err
return "", err
}
}
if key, ok := os.LookupEnv("MTX_CONFKEY"); ok {
byts, err = decrypt.Decrypt(key, byts)
if err != nil {
return true, err
return "", err
}
}
err = yaml.Load(byts, conf)
if err != nil {
return true, err
return "", err
}
return true, nil
return fpath, nil
}
func contains(list []headers.AuthMethod, item headers.AuthMethod) bool {
@ -183,30 +185,30 @@ type Conf struct {
}
// Load loads a Conf.
func Load(fpath string) (*Conf, bool, error) {
func Load(fpath string, defaultConfPaths []string) (*Conf, string, error) {
conf := &Conf{}
found, err := loadFromFile(fpath, conf)
fpath, err := loadFromFile(fpath, defaultConfPaths, conf)
if err != nil {
return nil, false, err
return nil, "", err
}
err = env.Load("RTSP", conf) // legacy prefix
if err != nil {
return nil, false, err
return nil, "", err
}
err = env.Load("MTX", conf)
if err != nil {
return nil, false, err
return nil, "", err
}
err = conf.Check()
if err != nil {
return nil, false, err
return nil, "", err
}
return conf, found, nil
return conf, fpath, nil
}
// Clone clones the configuration.

View File

@ -39,9 +39,9 @@ func TestConfFromFile(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
conf, hasFile, err := Load(tmpf)
conf, confPath, err := Load(tmpf, nil)
require.NoError(t, err)
require.Equal(t, true, hasFile)
require.Equal(t, tmpf, confPath)
require.Equal(t, LogLevel(logger.Debug), conf.LogLevel)
@ -73,7 +73,7 @@ func TestConfFromFile(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
_, _, err = Load(tmpf)
_, _, err = Load(tmpf, nil)
require.NoError(t, err)
}()
@ -82,7 +82,7 @@ func TestConfFromFile(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
_, _, err = Load(tmpf)
_, _, err = Load(tmpf, nil)
require.NoError(t, err)
}()
@ -93,7 +93,7 @@ func TestConfFromFile(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
_, _, err = Load(tmpf)
_, _, err = Load(tmpf, nil)
require.NoError(t, err)
}()
}
@ -109,9 +109,9 @@ func TestConfFromFileAndEnv(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
conf, hasFile, err := Load(tmpf)
conf, confPath, err := Load(tmpf, nil)
require.NoError(t, err)
require.Equal(t, true, hasFile)
require.Equal(t, tmpf, confPath)
require.Equal(t, Protocols{Protocol(gortsplib.TransportTCP): {}}, conf.Protocols)
@ -142,9 +142,9 @@ func TestConfFromEnvOnly(t *testing.T) {
os.Setenv("MTX_PATHS_CAM1_SOURCE", "rtsp://testing")
defer os.Unsetenv("MTX_PATHS_CAM1_SOURCE")
conf, hasFile, err := Load("mediamtx.yml")
conf, confPath, err := Load("", nil)
require.NoError(t, err)
require.Equal(t, false, hasFile)
require.Equal(t, "", confPath)
pa, ok := conf.Paths["cam1"]
require.Equal(t, true, ok)
@ -194,9 +194,9 @@ func TestConfEncryption(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
conf, hasFile, err := Load(tmpf)
conf, confPath, err := Load(tmpf, nil)
require.NoError(t, err)
require.Equal(t, true, hasFile)
require.Equal(t, tmpf, confPath)
_, ok := conf.Paths["path1"]
require.Equal(t, true, ok)
@ -283,7 +283,7 @@ func TestConfErrors(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpf)
_, _, err = Load(tmpf)
_, _, err = Load(tmpf, nil)
require.EqualError(t, err, ca.err)
})
}

View File

@ -6,7 +6,9 @@ import (
"fmt"
"os"
"os/signal"
"path/filepath"
"reflect"
"strings"
"time"
"github.com/alecthomas/kong"
@ -23,9 +25,17 @@ import (
var version = "v0.0.0"
var defaultConfPaths = []string{
"rtsp-simple-server.yml",
"mediamtx.yml",
"/usr/local/etc/mediamtx.yml",
"/usr/etc/mediamtx.yml",
"/etc/mediamtx/mediamtx.yml",
}
var cli struct {
Version bool `help:"print version"`
Confpath string `arg:"" default:"mediamtx.yml"`
Confpath string `arg:"" default:""`
}
// Core is an instance of mediamtx.
@ -34,7 +44,6 @@ type Core struct {
ctxCancel func()
confPath string
conf *conf.Conf
confFound bool
logger *logger.Logger
externalCmdPool *externalcmd.Pool
metrics *metrics
@ -89,12 +98,11 @@ func New(args []string) (*Core, bool) {
p := &Core{
ctx: ctx,
ctxCancel: ctxCancel,
confPath: cli.Confpath,
chAPIConfigSet: make(chan *conf.Conf),
done: make(chan struct{}),
}
p.conf, p.confFound, err = conf.Load(p.confPath)
p.conf, p.confPath, err = conf.Load(cli.Confpath, defaultConfPaths)
if err != nil {
fmt.Printf("ERR: %s\n", err)
return nil, false
@ -151,7 +159,7 @@ outer:
case <-confChanged:
p.Log(logger.Info, "reloading configuration (file changed)")
newConf, _, err := conf.Load(p.confPath)
newConf, _, err := conf.Load(p.confPath, nil)
if err != nil {
p.Log(logger.Error, "%s", err)
break outer
@ -202,8 +210,17 @@ func (p *Core) createResources(initial bool) error {
if initial {
p.Log(logger.Info, "MediaMTX %s", version)
if !p.confFound {
p.Log(logger.Warn, "configuration file not found, using an empty configuration")
if p.confPath == "" {
list := make([]string, len(defaultConfPaths))
for i, pa := range defaultConfPaths {
a, _ := filepath.Abs(pa)
list[i] = a
}
p.Log(logger.Warn,
"configuration file not found (looked in %s), using an empty configuration",
strings.Join(list, ", "))
}
// on Linux, try to raise the number of file descriptors that can be opened
@ -490,7 +507,7 @@ func (p *Core) createResources(initial bool) error {
}
}
if initial && p.confFound {
if initial && p.confPath != "" {
p.confWatcher, err = confwatcher.New(p.confPath)
if err != nil {
return err
@ -505,6 +522,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
newConf.LogLevel != p.conf.LogLevel ||
!reflect.DeepEqual(newConf.LogDestinations, p.conf.LogDestinations) ||
newConf.LogFile != p.conf.LogFile
closeMetrics := newConf == nil ||
newConf.Metrics != p.conf.Metrics ||
newConf.MetricsAddress != p.conf.MetricsAddress ||