Browse Source

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

pull/2360/head
Alessandro Ros 3 years ago committed by GitHub
parent
commit
f2f417e451
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 52
      internal/conf/conf.go
  2. 24
      internal/conf/conf_test.go
  3. 34
      internal/core/core.go

52
internal/conf/conf.go

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

24
internal/conf/conf_test.go

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

34
internal/core/core.go

@ -6,7 +6,9 @@ import (
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"reflect" "reflect"
"strings"
"time" "time"
"github.com/alecthomas/kong" "github.com/alecthomas/kong"
@ -23,9 +25,17 @@ import (
var version = "v0.0.0" 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 { var cli struct {
Version bool `help:"print version"` Version bool `help:"print version"`
Confpath string `arg:"" default:"mediamtx.yml"` Confpath string `arg:"" default:""`
} }
// Core is an instance of mediamtx. // Core is an instance of mediamtx.
@ -34,7 +44,6 @@ type Core struct {
ctxCancel func() ctxCancel func()
confPath string confPath string
conf *conf.Conf conf *conf.Conf
confFound bool
logger *logger.Logger logger *logger.Logger
externalCmdPool *externalcmd.Pool externalCmdPool *externalcmd.Pool
metrics *metrics metrics *metrics
@ -89,12 +98,11 @@ func New(args []string) (*Core, bool) {
p := &Core{ p := &Core{
ctx: ctx, ctx: ctx,
ctxCancel: ctxCancel, ctxCancel: ctxCancel,
confPath: cli.Confpath,
chAPIConfigSet: make(chan *conf.Conf), chAPIConfigSet: make(chan *conf.Conf),
done: make(chan struct{}), 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 { if err != nil {
fmt.Printf("ERR: %s\n", err) fmt.Printf("ERR: %s\n", err)
return nil, false return nil, false
@ -151,7 +159,7 @@ outer:
case <-confChanged: case <-confChanged:
p.Log(logger.Info, "reloading configuration (file changed)") p.Log(logger.Info, "reloading configuration (file changed)")
newConf, _, err := conf.Load(p.confPath) newConf, _, err := conf.Load(p.confPath, nil)
if err != nil { if err != nil {
p.Log(logger.Error, "%s", err) p.Log(logger.Error, "%s", err)
break outer break outer
@ -202,8 +210,17 @@ func (p *Core) createResources(initial bool) error {
if initial { if initial {
p.Log(logger.Info, "MediaMTX %s", version) 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 // 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) p.confWatcher, err = confwatcher.New(p.confPath)
if err != nil { if err != nil {
return err return err
@ -505,6 +522,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
newConf.LogLevel != p.conf.LogLevel || newConf.LogLevel != p.conf.LogLevel ||
!reflect.DeepEqual(newConf.LogDestinations, p.conf.LogDestinations) || !reflect.DeepEqual(newConf.LogDestinations, p.conf.LogDestinations) ||
newConf.LogFile != p.conf.LogFile newConf.LogFile != p.conf.LogFile
closeMetrics := newConf == nil || closeMetrics := newConf == nil ||
newConf.Metrics != p.conf.Metrics || newConf.Metrics != p.conf.Metrics ||
newConf.MetricsAddress != p.conf.MetricsAddress || newConf.MetricsAddress != p.conf.MetricsAddress ||

Loading…
Cancel
Save