mirror of
https://github.com/bluenviron/mediamtx
synced 2025-02-17 03:56:55 +00:00
search for configuration file in various paths, print paths if configuration is not found (#1993) (#2276) (#2357)
This commit is contained in:
parent
64d9060560
commit
f2f417e451
@ -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.
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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 ||
|
||||
|
Loading…
Reference in New Issue
Block a user