From 49240bf47e5f0b2bffb05e3a957d58d6c9993d56 Mon Sep 17 00:00:00 2001 From: Pavel Date: Tue, 22 Oct 2024 17:31:58 +0300 Subject: [PATCH 01/10] prepare toml --- cmd/video_server/main.go | 3 +- configuration/configuration.go | 3 +- configuration/prepare.go | 41 ++++++++ configuration/prepare_toml.go | 170 +++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + 6 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 configuration/prepare.go create mode 100644 configuration/prepare_toml.go diff --git a/cmd/video_server/main.go b/cmd/video_server/main.go index b7e8267..3edb729 100644 --- a/cmd/video_server/main.go +++ b/cmd/video_server/main.go @@ -48,11 +48,12 @@ func main() { } defer pprof.StopCPUProfile() } - appCfg, err := configuration.PrepareConfiguration(*conf) + appCfg, err := configuration.PrepareConfiguration(conf) if err != nil { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application configuration") return } + app, err := videoserver.NewApplication(appCfg) if err != nil { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application") diff --git a/configuration/configuration.go b/configuration/configuration.go index 383edc9..089831e 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -105,8 +105,7 @@ const ( defaultHlsWindowSize = 5 ) -// PrepareConfiguration -func PrepareConfiguration(fname string) (*Configuration, error) { +func PrepareConfigurationJSON(fname string) (*Configuration, error) { configFile, err := os.ReadFile(fname) if err != nil { return nil, err diff --git a/configuration/prepare.go b/configuration/prepare.go new file mode 100644 index 0000000..08cbb9a --- /dev/null +++ b/configuration/prepare.go @@ -0,0 +1,41 @@ +package configuration + +import ( + "fmt" + "strings" + + "github.com/pkg/errors" +) + +func PrepareConfiguration(confName *string) (*Configuration, error) { + var err error + if confName == nil || *confName == "" { + errReason := "Empty file name" + return nil, errors.Wrap(err, errReason) + } + + fileNames := strings.Split(*confName, ".") + if len(fileNames) != 2 { + errReason := fmt.Sprintf("Bad file name '%s'", *confName) + return nil, errors.Wrap(err, errReason) + } + fileFormat := fileNames[1] + + switch fileFormat { + case "json": + mainCfg, err := PrepareConfigurationJSON(*confName) + if err != nil { + return nil, err + } + return mainCfg, nil + case "toml": + mainCfg, err := PrepareConfigurationTOML(*confName) + if err != nil { + return nil, err + } + return mainCfg, nil + default: + errReason := fmt.Sprintf("Not supported file format '%s'", fileFormat) + return nil, errors.Wrap(err, errReason) + } +} diff --git a/configuration/prepare_toml.go b/configuration/prepare_toml.go new file mode 100644 index 0000000..0f22b75 --- /dev/null +++ b/configuration/prepare_toml.go @@ -0,0 +1,170 @@ +package configuration + +import ( + "github.com/BurntSushi/toml" +) + +func PrepareConfigurationTOML(fname string) (*Configuration, error) { + cfg := Configuration{} + + var confToml map[string]map[string]any + _, err := toml.DecodeFile(fname, &confToml) + if err != nil { + return nil, err + } + + if confToml["api"] != nil { + cfg.APICfg = APIConfiguration{} + for k, v := range confToml["api"] { + switch k { + case "enabled": + cfg.APICfg.Enabled = v.(bool) + case "host": + cfg.APICfg.Host = v.(string) + case "port": + cfg.APICfg.Port = int32(v.(int64)) + case "mode": + cfg.APICfg.Mode = v.(string) + case "verbose": + cfg.APICfg.Verbose = v.(string) + default: + continue + } + } + } + + if confToml["video"] != nil { + cfg.VideoServerCfg = VideoConfiguration{} + for k, v := range confToml["video"] { + switch k { + case "host": + cfg.VideoServerCfg.Host = v.(string) + case "port": + cfg.VideoServerCfg.Port = int32(v.(int64)) + case "mode": + cfg.VideoServerCfg.Mode = v.(string) + case "verbose": + cfg.VideoServerCfg.Verbose = v.(string) + default: + continue + } + } + } + + if confToml["hls"] != nil { + cfg.HLSCfg = HLSConfiguration{} + for k, v := range confToml["hls"] { + switch k { + case "ms_per_segment": + cfg.HLSCfg.MsPerSegment = v.(int64) + case "directory": + cfg.HLSCfg.Directory = v.(string) + case "window_size": + cfg.HLSCfg.WindowSize = uint(v.(int64)) + case "window_capacity": + cfg.HLSCfg.Capacity = uint(v.(int64)) + default: + continue + } + } + } + + if confToml["archive"] != nil { + cfg.ArchiveCfg = ArchiveConfiguration{} + for k, v := range confToml["archive"] { + switch k { + case "enabled": + cfg.ArchiveCfg.Enabled = v.(bool) + case "directory": + cfg.ArchiveCfg.Directory = v.(string) + case "ms_per_file": + cfg.ArchiveCfg.MsPerSegment = v.(int64) + default: + continue + } + } + } + + if confToml["cors"] != nil { + cfg.CorsConfig = CORSConfiguration{} + for k, v := range confToml["cors"] { + switch k { + case "enabled": + cfg.CorsConfig.Enabled = v.(bool) + case "allow_origins": + allowOrigins := make([]string, len(v.([]interface{}))) + for i, allowOrigin := range v.([]interface{}) { + allowOrigins[i] = allowOrigin.(string) + } + cfg.CorsConfig.AllowOrigins = allowOrigins + case "allow_methods": + allowMethods := make([]string, len(v.([]interface{}))) + for i, allowMethod := range v.([]interface{}) { + allowMethods[i] = allowMethod.(string) + } + cfg.CorsConfig.AllowMethods = allowMethods + case "allow_headers": + allowHeaders := make([]string, len(v.([]interface{}))) + for i, allowHeader := range v.([]interface{}) { + allowHeaders[i] = allowHeader.(string) + } + cfg.CorsConfig.AllowHeaders = allowHeaders + case "expose_headers": + exposeHeaders := make([]string, len(v.([]interface{}))) + for i, exposeHeader := range v.([]interface{}) { + exposeHeaders[i] = exposeHeader.(string) + } + cfg.CorsConfig.ExposeHeaders = exposeHeaders + default: + continue + } + } + } + + if confToml["rtsp_streams"] != nil { + cfg.RTSPStreams = make([]SingleStreamConfiguration, 0, len(confToml["rtsp_streams"])) + for _, v := range confToml["rtsp_streams"] { + singleStream := SingleStreamConfiguration{} + stream := v.(map[string]any) + for sk, sv := range stream { + switch sk { + case "guid": + singleStream.GUID = sv.(string) + case "type": + singleStream.Type = sv.(string) + case "url": + singleStream.URL = sv.(string) + case "output_types": + types := make([]string, len(sv.([]interface{}))) + for i, stype := range sv.([]interface{}) { + types[i] = stype.(string) + } + singleStream.OutputTypes = types + case "verbose": + singleStream.Verbose = sv.(string) + case "archive": + archive := sv.(map[string]any) + for ak, av := range archive { + switch ak { + case "enabled": + singleStream.Archive.Enabled = av.(bool) + case "ms_per_file": + singleStream.Archive.MsPerSegment = av.(int64) + case "type": + singleStream.Archive.TypeArchive = av.(string) + case "directory": + singleStream.Archive.Directory = av.(string) + default: + continue + } + } + default: + continue + } + } + cfg.RTSPStreams = append(cfg.RTSPStreams, singleStream) + } + } + + return &cfg, nil +} diff --git a/go.mod b/go.mod index 6569124..71925c7 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21.0 toolchain go1.22.5 require ( + github.com/BurntSushi/toml v1.4.0 github.com/deepch/vdk v0.0.27 github.com/gin-contrib/cors v1.7.2 github.com/gin-contrib/pprof v1.5.0 diff --git a/go.sum b/go.sum index d6fd8f3..a9c5d86 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg= github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= From 851cf554426d8ad1a62d5e7ff1d4034304ab11c2 Mon Sep 17 00:00:00 2001 From: Pavel Date: Tue, 22 Oct 2024 17:35:46 +0300 Subject: [PATCH 02/10] prepare toml --- configuration/prepare_toml.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configuration/prepare_toml.go b/configuration/prepare_toml.go index 0f22b75..5dcdf3f 100644 --- a/configuration/prepare_toml.go +++ b/configuration/prepare_toml.go @@ -154,6 +154,10 @@ func PrepareConfigurationTOML(fname string) (*Configuration, error) { singleStream.Archive.TypeArchive = av.(string) case "directory": singleStream.Archive.Directory = av.(string) + case "minio_bucket": + singleStream.Archive.MinioBucket = av.(string) + case "minio_path": + singleStream.Archive.MinioPath = av.(string) default: continue } From ea020d79df081574796c995953da2742c0d6fb85 Mon Sep 17 00:00:00 2001 From: Pavel Date: Tue, 22 Oct 2024 17:51:12 +0300 Subject: [PATCH 03/10] prepare toml --- configuration/prepare_toml.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/configuration/prepare_toml.go b/configuration/prepare_toml.go index 5dcdf3f..e177838 100644 --- a/configuration/prepare_toml.go +++ b/configuration/prepare_toml.go @@ -79,6 +79,27 @@ func PrepareConfigurationTOML(fname string) (*Configuration, error) { cfg.ArchiveCfg.Directory = v.(string) case "ms_per_file": cfg.ArchiveCfg.MsPerSegment = v.(int64) + case "minio_settings": + cfg.ArchiveCfg.Minio = MinioSettings{} + settings := v.(map[string]any) + for sk, sv := range settings { + switch sk { + case "host": + cfg.ArchiveCfg.Minio.Host = sv.(string) + case "port": + cfg.ArchiveCfg.Minio.Port = int32(sv.(int64)) + case "user": + cfg.ArchiveCfg.Minio.User = sv.(string) + case "password": + cfg.ArchiveCfg.Minio.Password = sv.(string) + case "default_bucket": + cfg.ArchiveCfg.Minio.DefaultBucket = sv.(string) + case "default_path": + cfg.ArchiveCfg.Minio.DefaultPath = sv.(string) + default: + continue + } + } default: continue } From 3d78abe3d9479be8f2bdd30c5f3de34697aa14fb Mon Sep 17 00:00:00 2001 From: Pavel Date: Tue, 22 Oct 2024 18:02:49 +0300 Subject: [PATCH 04/10] prepare toml --- cmd/video_server/main.go | 4 +++- configuration/prepare_toml.go | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cmd/video_server/main.go b/cmd/video_server/main.go index 3edb729..d80aeb4 100644 --- a/cmd/video_server/main.go +++ b/cmd/video_server/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "fmt" "os" "os/signal" "runtime" @@ -53,7 +54,8 @@ func main() { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application configuration") return } - + fmt.Println(appCfg) + return app, err := videoserver.NewApplication(appCfg) if err != nil { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application") diff --git a/configuration/prepare_toml.go b/configuration/prepare_toml.go index e177838..b75b031 100644 --- a/configuration/prepare_toml.go +++ b/configuration/prepare_toml.go @@ -187,6 +187,31 @@ func PrepareConfigurationTOML(fname string) (*Configuration, error) { continue } } + // Default common settings for archive + if singleStream.Archive.MsPerSegment <= 0 { + if cfg.ArchiveCfg.MsPerSegment > 0 { + singleStream.Archive.MsPerSegment = cfg.ArchiveCfg.MsPerSegment + } else { + singleStream.Archive.MsPerSegment = 30 + } + } + + // Default filesystem settigs + if singleStream.Archive.Directory == "" { + if cfg.ArchiveCfg.Directory != "" { + singleStream.Archive.Directory = cfg.ArchiveCfg.Directory + } else { + singleStream.Archive.Directory = "./mp4" + } + } + + // Default minio settings + if singleStream.Archive.MinioBucket == "" { + singleStream.Archive.MinioBucket = cfg.ArchiveCfg.Minio.DefaultBucket + } + if singleStream.Archive.MinioPath == "" { + singleStream.Archive.MinioPath = cfg.ArchiveCfg.Minio.DefaultPath + } cfg.RTSPStreams = append(cfg.RTSPStreams, singleStream) } } From 2e07196653779098a6e762c975083da4cc34e1d1 Mon Sep 17 00:00:00 2001 From: Pavel Date: Tue, 22 Oct 2024 18:05:14 +0300 Subject: [PATCH 05/10] fix --- cmd/video_server/main.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/video_server/main.go b/cmd/video_server/main.go index d80aeb4..3edb729 100644 --- a/cmd/video_server/main.go +++ b/cmd/video_server/main.go @@ -2,7 +2,6 @@ package main import ( "flag" - "fmt" "os" "os/signal" "runtime" @@ -54,8 +53,7 @@ func main() { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application configuration") return } - fmt.Println(appCfg) - return + app, err := videoserver.NewApplication(appCfg) if err != nil { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application") From 1eb16d8900b091d78912727ff18b6df1cd90f905 Mon Sep 17 00:00:00 2001 From: LdDl Date: Tue, 22 Oct 2024 18:20:42 +0300 Subject: [PATCH 06/10] TOML tags --- configuration/configuration.go | 94 +++++++++++++++++----------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/configuration/configuration.go b/configuration/configuration.go index 089831e..03fb1a2 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -10,57 +10,57 @@ import ( // Configuration represents user defined settings for video server type Configuration struct { - APICfg APIConfiguration `json:"api"` - VideoServerCfg VideoConfiguration `json:"video"` - HLSCfg HLSConfiguration `json:"hls"` - ArchiveCfg ArchiveConfiguration `json:"archive"` - CorsConfig CORSConfiguration `json:"cors"` - RTSPStreams []SingleStreamConfiguration `json:"rtsp_streams"` + APICfg APIConfiguration `json:"api" toml:"api"` + VideoServerCfg VideoConfiguration `json:"video" toml:"video"` + HLSCfg HLSConfiguration `json:"hls" toml:"hls"` + ArchiveCfg ArchiveConfiguration `json:"archive" toml:"archive"` + CorsConfig CORSConfiguration `json:"cors" toml:"cors"` + RTSPStreams []SingleStreamConfiguration `json:"rtsp_streams" toml:"rtsp_streams"` } // APIConfiguration is needed for configuring REST API part type APIConfiguration struct { - Enabled bool `json:"enabled"` - Host string `json:"host"` - Port int32 `json:"port"` + Enabled bool `json:"enabled" toml:"enabled"` + Host string `json:"host" toml:"host"` + Port int32 `json:"port" toml:"port"` // 'release' or 'debug' for GIN - Mode string `json:"mode"` - Verbose string `json:"verbose"` + Mode string `json:"mode" toml:"mode"` + Verbose string `json:"verbose" toml:"verbose"` } // VideoConfiguration is needed for configuring actual video server part type VideoConfiguration struct { - Host string `json:"host"` - Port int32 `json:"port"` + Host string `json:"host" toml:"host"` + Port int32 `json:"port" toml:"port"` // 'release' or 'debug' for GIN - Mode string `json:"mode"` - Verbose string `json:"verbose"` + Mode string `json:"mode" toml:"mode"` + Verbose string `json:"verbose" toml:"verbose"` } // HLSConfiguration is a HLS configuration for every stream with provided "hls" type in 'output_types' field of 'rtsp_streams' objects type HLSConfiguration struct { - MsPerSegment int64 `json:"ms_per_segment"` - Directory string `json:"directory"` - WindowSize uint `json:"window_size"` - Capacity uint `json:"window_capacity"` + MsPerSegment int64 `json:"ms_per_segment" toml:"ms_per_segment"` + Directory string `json:"directory" toml:"directory"` + WindowSize uint `json:"window_size" toml:"window_size"` + Capacity uint `json:"window_capacity" toml:"window_capacity"` } // ArchiveConfiguration is a archive configuration for every stream with enabled archive option type ArchiveConfiguration struct { - Enabled bool `json:"enabled"` - MsPerSegment int64 `json:"ms_per_file"` - Directory string `json:"directory"` - Minio MinioSettings `json:"minio_settings"` + Enabled bool `json:"enabled" toml:"enabled"` + MsPerSegment int64 `json:"ms_per_file" toml:"ms_per_file"` + Directory string `json:"directory" toml:"directory"` + Minio MinioSettings `json:"minio_settings" toml:"minio_settings"` } // MinioSettings type MinioSettings struct { - Host string `json:"host"` - Port int32 `json:"port"` - User string `json:"user"` - Password string `json:"password"` - DefaultBucket string `json:"default_bucket"` - DefaultPath string `json:"default_path"` + Host string `json:"host" toml:"host"` + Port int32 `json:"port" toml:"port"` + User string `json:"user" toml:"user"` + Password string `json:"password" toml:"password"` + DefaultBucket string `json:"default_bucket" toml:"default_bucket"` + DefaultPath string `json:"default_path" toml:"default_path"` } func (ms *MinioSettings) String() string { @@ -69,33 +69,33 @@ func (ms *MinioSettings) String() string { // CORSConfiguration is settings for CORS type CORSConfiguration struct { - Enabled bool `json:"enabled"` - AllowOrigins []string `json:"allow_origins"` - AllowMethods []string `json:"allow_methods"` - AllowHeaders []string `json:"allow_headers"` - ExposeHeaders []string `json:"expose_headers"` - AllowCredentials bool `json:"allow_credentials"` + Enabled bool `json:"enabled" toml:"enabled"` + AllowOrigins []string `json:"allow_origins" toml:"allow_origins"` + AllowMethods []string `json:"allow_methods" toml:"allow_methods"` + AllowHeaders []string `json:"allow_headers" toml:"allow_headers"` + ExposeHeaders []string `json:"expose_headers" toml:"expose_headers"` + AllowCredentials bool `json:"allow_credentials" toml:"allow_credentials"` } // SingleStreamConfiguration is needed for configuring certain RTSP stream type SingleStreamConfiguration struct { - GUID string `json:"guid"` - URL string `json:"url"` - Type string `json:"type"` - OutputTypes []string `json:"output_types"` - Archive StreamArchiveConfiguration `json:"archive"` + GUID string `json:"guid" toml:"guid"` + URL string `json:"url" toml:"url"` + Type string `json:"type" toml:"type"` + OutputTypes []string `json:"output_types" toml:"output_types"` + Archive StreamArchiveConfiguration `json:"archive" toml:"archive"` // Level of verbose. Pick 'v' or 'vvv' (or leave it empty) - Verbose string `json:"verbose"` + Verbose string `json:"verbose" toml:"verbose"` } // StreamArchiveConfiguration is a archive configuration for cpecific stream. I can overwrite parent archive options in needed type StreamArchiveConfiguration struct { - Enabled bool `json:"enabled"` - MsPerSegment int64 `json:"ms_per_file"` - Directory string `json:"directory"` - TypeArchive string `json:"type"` - MinioBucket string `json:"minio_bucket"` - MinioPath string `json:"minio_path"` + Enabled bool `json:"enabled" toml:"enabled"` + MsPerSegment int64 `json:"ms_per_file" toml:"ms_per_file"` + Directory string `json:"directory" toml:"directory"` + TypeArchive string `json:"type" toml:"type"` + MinioBucket string `json:"minio_bucket" toml:"minio_bucket"` + MinioPath string `json:"minio_path" toml:"minio_path"` } const ( From f219de011817d6f0b12613e3018967130f1b2509 Mon Sep 17 00:00:00 2001 From: LdDl Date: Tue, 22 Oct 2024 18:26:51 +0300 Subject: [PATCH 07/10] toml reduce --- configuration/prepare_toml.go | 232 ++++++---------------------------- 1 file changed, 37 insertions(+), 195 deletions(-) diff --git a/configuration/prepare_toml.go b/configuration/prepare_toml.go index b75b031..99ee5ec 100644 --- a/configuration/prepare_toml.go +++ b/configuration/prepare_toml.go @@ -6,215 +6,57 @@ import ( func PrepareConfigurationTOML(fname string) (*Configuration, error) { cfg := Configuration{} - - var confToml map[string]map[string]any - _, err := toml.DecodeFile(fname, &confToml) + _, err := toml.DecodeFile(fname, &cfg) if err != nil { return nil, err } - - if confToml["api"] != nil { - cfg.APICfg = APIConfiguration{} - for k, v := range confToml["api"] { - switch k { - case "enabled": - cfg.APICfg.Enabled = v.(bool) - case "host": - cfg.APICfg.Host = v.(string) - case "port": - cfg.APICfg.Port = int32(v.(int64)) - case "mode": - cfg.APICfg.Mode = v.(string) - case "verbose": - cfg.APICfg.Verbose = v.(string) - default: - continue - } - } + if cfg.HLSCfg.Directory == "" { + cfg.HLSCfg.Directory = defaultHlsDir } - - if confToml["video"] != nil { - cfg.VideoServerCfg = VideoConfiguration{} - for k, v := range confToml["video"] { - switch k { - case "host": - cfg.VideoServerCfg.Host = v.(string) - case "port": - cfg.VideoServerCfg.Port = int32(v.(int64)) - case "mode": - cfg.VideoServerCfg.Mode = v.(string) - case "verbose": - cfg.VideoServerCfg.Verbose = v.(string) - default: - continue - } - } + if cfg.HLSCfg.MsPerSegment == 0 { + cfg.HLSCfg.MsPerSegment = defaultHlsMsPerSegment } - - if confToml["hls"] != nil { - cfg.HLSCfg = HLSConfiguration{} - for k, v := range confToml["hls"] { - switch k { - case "ms_per_segment": - cfg.HLSCfg.MsPerSegment = v.(int64) - case "directory": - cfg.HLSCfg.Directory = v.(string) - case "window_size": - cfg.HLSCfg.WindowSize = uint(v.(int64)) - case "window_capacity": - cfg.HLSCfg.Capacity = uint(v.(int64)) - default: - continue - } - } + if cfg.HLSCfg.Capacity == 0 { + cfg.HLSCfg.Capacity = defaultHlsCapacity } - - if confToml["archive"] != nil { - cfg.ArchiveCfg = ArchiveConfiguration{} - for k, v := range confToml["archive"] { - switch k { - case "enabled": - cfg.ArchiveCfg.Enabled = v.(bool) - case "directory": - cfg.ArchiveCfg.Directory = v.(string) - case "ms_per_file": - cfg.ArchiveCfg.MsPerSegment = v.(int64) - case "minio_settings": - cfg.ArchiveCfg.Minio = MinioSettings{} - settings := v.(map[string]any) - for sk, sv := range settings { - switch sk { - case "host": - cfg.ArchiveCfg.Minio.Host = sv.(string) - case "port": - cfg.ArchiveCfg.Minio.Port = int32(sv.(int64)) - case "user": - cfg.ArchiveCfg.Minio.User = sv.(string) - case "password": - cfg.ArchiveCfg.Minio.Password = sv.(string) - case "default_bucket": - cfg.ArchiveCfg.Minio.DefaultBucket = sv.(string) - case "default_path": - cfg.ArchiveCfg.Minio.DefaultPath = sv.(string) - default: - continue - } - } - default: - continue - } - } + if cfg.HLSCfg.WindowSize == 0 { + cfg.HLSCfg.WindowSize = defaultHlsWindowSize } - - if confToml["cors"] != nil { - cfg.CorsConfig = CORSConfiguration{} - for k, v := range confToml["cors"] { - switch k { - case "enabled": - cfg.CorsConfig.Enabled = v.(bool) - case "allow_origins": - allowOrigins := make([]string, len(v.([]interface{}))) - for i, allowOrigin := range v.([]interface{}) { - allowOrigins[i] = allowOrigin.(string) - } - cfg.CorsConfig.AllowOrigins = allowOrigins - case "allow_methods": - allowMethods := make([]string, len(v.([]interface{}))) - for i, allowMethod := range v.([]interface{}) { - allowMethods[i] = allowMethod.(string) - } - cfg.CorsConfig.AllowMethods = allowMethods - case "allow_headers": - allowHeaders := make([]string, len(v.([]interface{}))) - for i, allowHeader := range v.([]interface{}) { - allowHeaders[i] = allowHeader.(string) - } - cfg.CorsConfig.AllowHeaders = allowHeaders - case "expose_headers": - exposeHeaders := make([]string, len(v.([]interface{}))) - for i, exposeHeader := range v.([]interface{}) { - exposeHeaders[i] = exposeHeader.(string) - } - cfg.CorsConfig.ExposeHeaders = exposeHeaders - default: - continue - } - } + if cfg.HLSCfg.WindowSize > cfg.HLSCfg.Capacity { + cfg.HLSCfg.WindowSize = cfg.HLSCfg.Capacity } + for i := range cfg.RTSPStreams { + stream := cfg.RTSPStreams[i] + archiveCfg := stream.Archive + if !archiveCfg.Enabled { + continue + } - if confToml["rtsp_streams"] != nil { - cfg.RTSPStreams = make([]SingleStreamConfiguration, 0, len(confToml["rtsp_streams"])) - for _, v := range confToml["rtsp_streams"] { - singleStream := SingleStreamConfiguration{} - stream := v.(map[string]any) - for sk, sv := range stream { - switch sk { - case "guid": - singleStream.GUID = sv.(string) - case "type": - singleStream.Type = sv.(string) - case "url": - singleStream.URL = sv.(string) - case "output_types": - types := make([]string, len(sv.([]interface{}))) - for i, stype := range sv.([]interface{}) { - types[i] = stype.(string) - } - singleStream.OutputTypes = types - case "verbose": - singleStream.Verbose = sv.(string) - case "archive": - archive := sv.(map[string]any) - for ak, av := range archive { - switch ak { - case "enabled": - singleStream.Archive.Enabled = av.(bool) - case "ms_per_file": - singleStream.Archive.MsPerSegment = av.(int64) - case "type": - singleStream.Archive.TypeArchive = av.(string) - case "directory": - singleStream.Archive.Directory = av.(string) - case "minio_bucket": - singleStream.Archive.MinioBucket = av.(string) - case "minio_path": - singleStream.Archive.MinioPath = av.(string) - default: - continue - } - } - default: - continue - } - } - // Default common settings for archive - if singleStream.Archive.MsPerSegment <= 0 { - if cfg.ArchiveCfg.MsPerSegment > 0 { - singleStream.Archive.MsPerSegment = cfg.ArchiveCfg.MsPerSegment - } else { - singleStream.Archive.MsPerSegment = 30 - } + // Default common settings for archive + if archiveCfg.MsPerSegment <= 0 { + if cfg.ArchiveCfg.MsPerSegment > 0 { + cfg.RTSPStreams[i].Archive.MsPerSegment = cfg.ArchiveCfg.MsPerSegment + } else { + cfg.RTSPStreams[i].Archive.MsPerSegment = 30 } + } - // Default filesystem settigs - if singleStream.Archive.Directory == "" { - if cfg.ArchiveCfg.Directory != "" { - singleStream.Archive.Directory = cfg.ArchiveCfg.Directory - } else { - singleStream.Archive.Directory = "./mp4" - } + // Default filesystem settigs + if archiveCfg.Directory == "" { + if cfg.ArchiveCfg.Directory != "" { + cfg.RTSPStreams[i].Archive.Directory = cfg.ArchiveCfg.Directory + } else { + cfg.RTSPStreams[i].Archive.Directory = "./mp4" } + } - // Default minio settings - if singleStream.Archive.MinioBucket == "" { - singleStream.Archive.MinioBucket = cfg.ArchiveCfg.Minio.DefaultBucket - } - if singleStream.Archive.MinioPath == "" { - singleStream.Archive.MinioPath = cfg.ArchiveCfg.Minio.DefaultPath - } - cfg.RTSPStreams = append(cfg.RTSPStreams, singleStream) + // Default minio settings + if archiveCfg.MinioBucket == "" { + cfg.RTSPStreams[i].Archive.MinioBucket = cfg.ArchiveCfg.Minio.DefaultBucket + } + if archiveCfg.MinioPath == "" { + cfg.RTSPStreams[i].Archive.MinioPath = cfg.ArchiveCfg.Minio.DefaultPath } } - return &cfg, nil } From dab36d0b7378a8b74ae38408575e066328332e38 Mon Sep 17 00:00:00 2001 From: LdDl Date: Tue, 22 Oct 2024 18:30:45 +0300 Subject: [PATCH 08/10] reuse defaults code --- configuration/configuration.go | 70 -------------------------------- configuration/postprocess_cfg.go | 59 +++++++++++++++++++++++++++ configuration/prepare_json.go | 20 +++++++++ configuration/prepare_toml.go | 55 ++----------------------- 4 files changed, 83 insertions(+), 121 deletions(-) create mode 100644 configuration/postprocess_cfg.go create mode 100644 configuration/prepare_json.go diff --git a/configuration/configuration.go b/configuration/configuration.go index 03fb1a2..9c1ce06 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -1,9 +1,7 @@ package configuration import ( - "encoding/json" "fmt" - "os" ) // @todo: can we switch to TOML? Any benefits? @@ -97,71 +95,3 @@ type StreamArchiveConfiguration struct { MinioBucket string `json:"minio_bucket" toml:"minio_bucket"` MinioPath string `json:"minio_path" toml:"minio_path"` } - -const ( - defaultHlsDir = "./hls" - defaultHlsMsPerSegment = 10000 - defaultHlsCapacity = 10 - defaultHlsWindowSize = 5 -) - -func PrepareConfigurationJSON(fname string) (*Configuration, error) { - configFile, err := os.ReadFile(fname) - if err != nil { - return nil, err - } - cfg := &Configuration{} - err = json.Unmarshal(configFile, &cfg) - if err != nil { - return nil, err - } - if cfg.HLSCfg.Directory == "" { - cfg.HLSCfg.Directory = defaultHlsDir - } - if cfg.HLSCfg.MsPerSegment == 0 { - cfg.HLSCfg.MsPerSegment = defaultHlsMsPerSegment - } - if cfg.HLSCfg.Capacity == 0 { - cfg.HLSCfg.Capacity = defaultHlsCapacity - } - if cfg.HLSCfg.WindowSize == 0 { - cfg.HLSCfg.WindowSize = defaultHlsWindowSize - } - if cfg.HLSCfg.WindowSize > cfg.HLSCfg.Capacity { - cfg.HLSCfg.WindowSize = cfg.HLSCfg.Capacity - } - for i := range cfg.RTSPStreams { - stream := cfg.RTSPStreams[i] - archiveCfg := stream.Archive - if !archiveCfg.Enabled { - continue - } - - // Default common settings for archive - if archiveCfg.MsPerSegment <= 0 { - if cfg.ArchiveCfg.MsPerSegment > 0 { - cfg.RTSPStreams[i].Archive.MsPerSegment = cfg.ArchiveCfg.MsPerSegment - } else { - cfg.RTSPStreams[i].Archive.MsPerSegment = 30 - } - } - - // Default filesystem settigs - if archiveCfg.Directory == "" { - if cfg.ArchiveCfg.Directory != "" { - cfg.RTSPStreams[i].Archive.Directory = cfg.ArchiveCfg.Directory - } else { - cfg.RTSPStreams[i].Archive.Directory = "./mp4" - } - } - - // Default minio settings - if archiveCfg.MinioBucket == "" { - cfg.RTSPStreams[i].Archive.MinioBucket = cfg.ArchiveCfg.Minio.DefaultBucket - } - if archiveCfg.MinioPath == "" { - cfg.RTSPStreams[i].Archive.MinioPath = cfg.ArchiveCfg.Minio.DefaultPath - } - } - return cfg, nil -} diff --git a/configuration/postprocess_cfg.go b/configuration/postprocess_cfg.go new file mode 100644 index 0000000..2dc1cfd --- /dev/null +++ b/configuration/postprocess_cfg.go @@ -0,0 +1,59 @@ +package configuration + +const ( + defaultHlsDir = "./hls" + defaultHlsMsPerSegment = 10000 + defaultHlsCapacity = 10 + defaultHlsWindowSize = 5 +) + +func postProcessDefaults(cfg *Configuration) { + if cfg.HLSCfg.Directory == "" { + cfg.HLSCfg.Directory = defaultHlsDir + } + if cfg.HLSCfg.MsPerSegment == 0 { + cfg.HLSCfg.MsPerSegment = defaultHlsMsPerSegment + } + if cfg.HLSCfg.Capacity == 0 { + cfg.HLSCfg.Capacity = defaultHlsCapacity + } + if cfg.HLSCfg.WindowSize == 0 { + cfg.HLSCfg.WindowSize = defaultHlsWindowSize + } + if cfg.HLSCfg.WindowSize > cfg.HLSCfg.Capacity { + cfg.HLSCfg.WindowSize = cfg.HLSCfg.Capacity + } + for i := range cfg.RTSPStreams { + stream := cfg.RTSPStreams[i] + archiveCfg := stream.Archive + if !archiveCfg.Enabled { + continue + } + + // Default common settings for archive + if archiveCfg.MsPerSegment <= 0 { + if cfg.ArchiveCfg.MsPerSegment > 0 { + cfg.RTSPStreams[i].Archive.MsPerSegment = cfg.ArchiveCfg.MsPerSegment + } else { + cfg.RTSPStreams[i].Archive.MsPerSegment = 30 + } + } + + // Default filesystem settigs + if archiveCfg.Directory == "" { + if cfg.ArchiveCfg.Directory != "" { + cfg.RTSPStreams[i].Archive.Directory = cfg.ArchiveCfg.Directory + } else { + cfg.RTSPStreams[i].Archive.Directory = "./mp4" + } + } + + // Default minio settings + if archiveCfg.MinioBucket == "" { + cfg.RTSPStreams[i].Archive.MinioBucket = cfg.ArchiveCfg.Minio.DefaultBucket + } + if archiveCfg.MinioPath == "" { + cfg.RTSPStreams[i].Archive.MinioPath = cfg.ArchiveCfg.Minio.DefaultPath + } + } +} diff --git a/configuration/prepare_json.go b/configuration/prepare_json.go new file mode 100644 index 0000000..c6b668b --- /dev/null +++ b/configuration/prepare_json.go @@ -0,0 +1,20 @@ +package configuration + +import ( + "encoding/json" + "os" +) + +func PrepareConfigurationJSON(fname string) (*Configuration, error) { + configFile, err := os.ReadFile(fname) + if err != nil { + return nil, err + } + cfg := &Configuration{} + err = json.Unmarshal(configFile, &cfg) + if err != nil { + return nil, err + } + postProcessDefaults(cfg) + return cfg, nil +} diff --git a/configuration/prepare_toml.go b/configuration/prepare_toml.go index 99ee5ec..69f5c6b 100644 --- a/configuration/prepare_toml.go +++ b/configuration/prepare_toml.go @@ -5,58 +5,11 @@ import ( ) func PrepareConfigurationTOML(fname string) (*Configuration, error) { - cfg := Configuration{} - _, err := toml.DecodeFile(fname, &cfg) + cfg := &Configuration{} + _, err := toml.DecodeFile(fname, cfg) if err != nil { return nil, err } - if cfg.HLSCfg.Directory == "" { - cfg.HLSCfg.Directory = defaultHlsDir - } - if cfg.HLSCfg.MsPerSegment == 0 { - cfg.HLSCfg.MsPerSegment = defaultHlsMsPerSegment - } - if cfg.HLSCfg.Capacity == 0 { - cfg.HLSCfg.Capacity = defaultHlsCapacity - } - if cfg.HLSCfg.WindowSize == 0 { - cfg.HLSCfg.WindowSize = defaultHlsWindowSize - } - if cfg.HLSCfg.WindowSize > cfg.HLSCfg.Capacity { - cfg.HLSCfg.WindowSize = cfg.HLSCfg.Capacity - } - for i := range cfg.RTSPStreams { - stream := cfg.RTSPStreams[i] - archiveCfg := stream.Archive - if !archiveCfg.Enabled { - continue - } - - // Default common settings for archive - if archiveCfg.MsPerSegment <= 0 { - if cfg.ArchiveCfg.MsPerSegment > 0 { - cfg.RTSPStreams[i].Archive.MsPerSegment = cfg.ArchiveCfg.MsPerSegment - } else { - cfg.RTSPStreams[i].Archive.MsPerSegment = 30 - } - } - - // Default filesystem settigs - if archiveCfg.Directory == "" { - if cfg.ArchiveCfg.Directory != "" { - cfg.RTSPStreams[i].Archive.Directory = cfg.ArchiveCfg.Directory - } else { - cfg.RTSPStreams[i].Archive.Directory = "./mp4" - } - } - - // Default minio settings - if archiveCfg.MinioBucket == "" { - cfg.RTSPStreams[i].Archive.MinioBucket = cfg.ArchiveCfg.Minio.DefaultBucket - } - if archiveCfg.MinioPath == "" { - cfg.RTSPStreams[i].Archive.MinioPath = cfg.ArchiveCfg.Minio.DefaultPath - } - } - return &cfg, nil + postProcessDefaults(cfg) + return cfg, nil } From 32cedea54b03262983afd1df094bf66372e78dc2 Mon Sep 17 00:00:00 2001 From: LdDl Date: Tue, 22 Oct 2024 19:15:12 +0300 Subject: [PATCH 09/10] toml docs and default --- .gitignore | 4 +- README.md | 76 ++++++++++++++------------------------ cmd/video_server/conf.toml | 55 +++++++++++++++++++++++++++ cmd/video_server/main.go | 2 +- streams.go | 8 ++-- 5 files changed, 90 insertions(+), 55 deletions(-) create mode 100644 cmd/video_server/conf.toml diff --git a/.gitignore b/.gitignore index 4e1c1d8..35c16c9 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ cmd/video_server/linux-video_server.zip cmd/video_server/windows-video_server.zip cmd/video_server/conf_token.json video-server-ui -video_server +./video_server linux-amd64-video_server.tar.gz -video_server.exe +./video_server.exe windows-video_server.zip diff --git a/README.md b/README.md index 68219c9..e317ce9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ video_server -h ``` ```shell -conf string - Path to configuration JSON-file (default "conf.json") + Path to configuration either TOML-file or JSON-file (default "conf.toml") -cpuprofile file write cpu profile to file -memprofile file @@ -58,7 +58,7 @@ video_server -h ### Start server Prepare configuration file (example [here](cmd/video_server/conf.json)). Then run binary: ```shell -video_server --conf=conf.json +video_server --conf=conf.toml ``` ### Test Client-Server For HLS-based player go to [hls-subdirectory](example_client/hls_example). @@ -85,59 +85,39 @@ Paste link to the browser and check if video loaded successfully. You can configure application to write MP4 chunks of custom duration (but not less than first keyframe duration) to the filesystem or [S3 MinIO](https://min.io/) - For storing archive to the filesystem. Point default directory for storing MP4 files and duration: - ```json - "archive": { - "enabled": true, - "directory": "./mp4", - "ms_per_file": 30000 - } + ```toml + [archive] + enabled = true + directory = "./mp4" + ms_per_file = 30000 ``` + For each stream configuration you can override default directory and duration. Field "type" should have value "filesystem": - ```json - { - /// - // Some other single stream props... - /// - "archive": { - "enabled": true, - "ms_per_file": 20000, - "type": "filesystem", - "directory": "custom_folder" - } - } + ```toml + [[rtsp_streams]] + # ... + # Some other single stream props + # ... + archive = { enabled = true, ms_per_file = 20000, type = "filesystem", directory = "custom_folder" } ``` + - For storing archive to the S3 MinIO: Modify configuration file to have both filesystem and minio configuration (filesystem will be picked for storing temporary files before moving it to the MinIO), e.g.: - ```json - "archive": { - "directory": "./mp4", - "ms_per_file": 30000, - "minio_settings": { - "host": "localhost", - "port": 29199, - "user": "minio_secret_login", - "password": "minio_secret_password", - "default_bucket": "archive_bucket", - "default_path": "/var/archive_data" - } - } + ```toml + [archive] + enabled = true + directory = "./mp4" + ms_per_file = 30000 + minio_settings = { host = "localhost", port = 29199, user = "minio_secret_login", password = "minio_secret_password", default_bucket = "archive-bucket", default_path = "/var/archive_data" } ``` + For each stream configuration you can override default directory for temporary files, MinIO bucket and path in it and chunk duration. Field "type" should have value "minio": - ```json - { - /// - // Some other single stream props... - /// - "archive": { - "enabled": true, - "ms_per_file": 20000, - "type": "filesystem", - "directory": "custom_folder", - "type": "minio", - "minio_bucket": "vod-bucket", - "minio_path": "/var/archive_data_custom" - } - } + ```toml + [[rtsp_streams]] + # ... + # Some other single stream props + # ... + archive = { enabled = true, ms_per_file = 20000, type = "minio", "directory": "custom_folder", minio_bucket = "vod-bucket", minio_path = "/var/archive_data_custom" } ``` - If you want disable archive for specified stream, just set value of the field `enabled` to `false` in streams array. For disabling archive at all you can do the same but in the main configuration (where default values are set) diff --git a/cmd/video_server/conf.toml b/cmd/video_server/conf.toml new file mode 100644 index 0000000..083323b --- /dev/null +++ b/cmd/video_server/conf.toml @@ -0,0 +1,55 @@ +[api] +enabled = true +host = "localhost" +port = 8091 +mode = "release" +verbose = "v" + +[video] +host = "localhost" +port = 8090 +mode = "release" +verbose = "v" + +[hls] +ms_per_segment = 10000 +directory = "./hls" +window_size = 5 +window_capacity = 10 + +[archive] +enabled = true +directory = "./mp4" +ms_per_file = 30000 +minio_settings = { host = "localhost", port = 29199, user = "minio_secret_login", password = "minio_secret_password", default_bucket = "archive-bucket", default_path = "/var/archive_data" } + +[cors] +enabled = true +allow_origins = ["*"] +allow_methods = ["GET", "PUT", "POST", "DELETE"] +allow_headers = [ + "Origin", + "Authorization", + "Content-Type", + "Content-Length", + "Accept", + "Accept-Encoding", + "X-HttpRequest", +] +expose_headers = ["Content-Length"] + +[[rtsp_streams]] +guid = "0742091c-19cd-4658-9b4f-5320da160f45" +type = "rtsp" +url = "rtsp://localhost:45666/live" +output_types = ["mse"] +verbose = "v" +archive = { enabled = true, ms_per_file = 10000, type = "filesystem", directory = "custom_folder" } + +[[rtsp_streams]] +guid = "566bfe72-1f85-4e7d-9c0a-424e6c3b29f3" +type = "rtsp" +url = "rtsp://localhost:45664/live" +output_types = ["mse"] +verbose = "v" +archive = { enabled = true, ms_per_file = 15000, type = "minio", minio_bucket = "vod-bucket", minio_path = "/var/archive_data_custom" } diff --git a/cmd/video_server/main.go b/cmd/video_server/main.go index 3edb729..92fc160 100644 --- a/cmd/video_server/main.go +++ b/cmd/video_server/main.go @@ -20,7 +20,7 @@ import ( var ( cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`") memprofile = flag.String("memprofile", "", "write memory profile to `file`") - conf = flag.String("conf", "conf.json", "Path to configuration JSON-file") + conf = flag.String("conf", "conf.toml", "Path to configuration either TOML-file or JSON-file") EVENT_CPU = "cpu_profile" EVENT_MEMORY = "memory_profile" EVENT_APP_START = "app_start" diff --git a/streams.go b/streams.go index ba53302..d40acd4 100644 --- a/streams.go +++ b/streams.go @@ -52,19 +52,19 @@ func (app *Application) startLoop(ctx context.Context, streamID uuid.UUID, url s select { case <-ctx.Done(): if streamVerboseLevel > VERBOSE_NONE { - log.Info().Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_DONE).Str("stream_id", streamID.String()).Str("stream_url", url).Msg("Stream is done") + log.Info().Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_DONE).Str("stream_id", streamID.String()).Str("stream_url", url).Bool("hls_enabled", hlsEnabled).Bool("archive_enabled", archiveEnabled).Msg("Stream is done") } return default: if streamVerboseLevel > VERBOSE_NONE { - log.Info().Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_START).Str("stream_id", streamID.String()).Str("stream_url", url).Msg("Stream must be establishment") + log.Info().Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_START).Str("stream_id", streamID.String()).Str("stream_url", url).Bool("hls_enabled", hlsEnabled).Bool("archive_enabled", archiveEnabled).Msg("Stream must be establishment") } err := app.runStream(streamID, url, hlsEnabled, archiveEnabled, streamVerboseLevel) if err != nil { - log.Error().Err(err).Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_RESTART).Str("stream_id", streamID.String()).Str("stream_url", url).Msg("Can't start stream") + log.Error().Err(err).Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_RESTART).Str("stream_id", streamID.String()).Str("stream_url", url).Bool("hls_enabled", hlsEnabled).Bool("archive_enabled", archiveEnabled).Msg("Can't start stream") } if streamVerboseLevel > VERBOSE_NONE { - log.Info().Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_RESTART).Str("stream_id", streamID.String()).Str("stream_url", url).Dur("restart_duration", restartStreamDuration).Msg("Stream must be re-establishment") + log.Info().Str("scope", SCOPE_STREAMING).Str("event", EVENT_STREAMING_RESTART).Str("stream_id", streamID.String()).Str("stream_url", url).Dur("restart_duration", restartStreamDuration).Bool("hls_enabled", hlsEnabled).Bool("archive_enabled", archiveEnabled).Msg("Stream must be re-establishment") } } time.Sleep(restartStreamDuration) From c15d963f16cc7c9c83ad2e0d4a402a94716b4b82 Mon Sep 17 00:00:00 2001 From: LdDl Date: Tue, 22 Oct 2024 19:19:32 +0300 Subject: [PATCH 10/10] pointer in main only --- cmd/video_server/main.go | 2 +- configuration/prepare.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/video_server/main.go b/cmd/video_server/main.go index 92fc160..e810a1d 100644 --- a/cmd/video_server/main.go +++ b/cmd/video_server/main.go @@ -48,7 +48,7 @@ func main() { } defer pprof.StopCPUProfile() } - appCfg, err := configuration.PrepareConfiguration(conf) + appCfg, err := configuration.PrepareConfiguration(*conf) if err != nil { log.Error().Err(err).Str("scope", videoserver.SCOPE_CONFIGURATION).Msg("Could not prepare application configuration") return diff --git a/configuration/prepare.go b/configuration/prepare.go index 08cbb9a..c6db5dd 100644 --- a/configuration/prepare.go +++ b/configuration/prepare.go @@ -7,29 +7,29 @@ import ( "github.com/pkg/errors" ) -func PrepareConfiguration(confName *string) (*Configuration, error) { +func PrepareConfiguration(confName string) (*Configuration, error) { var err error - if confName == nil || *confName == "" { + if confName == "" { errReason := "Empty file name" return nil, errors.Wrap(err, errReason) } - fileNames := strings.Split(*confName, ".") + fileNames := strings.Split(confName, ".") if len(fileNames) != 2 { - errReason := fmt.Sprintf("Bad file name '%s'", *confName) + errReason := fmt.Sprintf("Bad file name '%s'", confName) return nil, errors.Wrap(err, errReason) } fileFormat := fileNames[1] switch fileFormat { case "json": - mainCfg, err := PrepareConfigurationJSON(*confName) + mainCfg, err := PrepareConfigurationJSON(confName) if err != nil { return nil, err } return mainCfg, nil case "toml": - mainCfg, err := PrepareConfigurationTOML(*confName) + mainCfg, err := PrepareConfigurationTOML(confName) if err != nil { return nil, err }