Skip to content

Commit 16056da

Browse files
committed
fix: error parsing time.duration parameters
refactor!: centralize cli configuration, breaking change for config files and env vars
1 parent a9c05a6 commit 16056da

File tree

16 files changed

+269
-320
lines changed

16 files changed

+269
-320
lines changed

cmd/cmd.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"time"
6+
server "transcoder/server/config"
7+
"transcoder/server/web"
8+
"transcoder/version"
9+
worker "transcoder/worker/config"
10+
)
11+
12+
type CommandLineConfig struct {
13+
NoUpdateMode bool `mapstructure:"noUpdateMode"`
14+
NoUpdates bool `mapstructure:"noUpdates"`
15+
UpdateCheckInterval *time.Duration `mapstructure:"updateCheckInterval"`
16+
Verbose bool `mapstructure:"verbose"`
17+
Version bool `mapstructure:"version"`
18+
Web *web.Config `mapstructure:"web"`
19+
Server *server.Config `mapstructure:"server"`
20+
Worker *worker.Config `mapstructure:"worker"`
21+
}
22+
23+
func (opts *CommandLineConfig) PrintVersion() {
24+
if opts.Version {
25+
version.LogVersion()
26+
os.Exit(0)
27+
}
28+
}

cmd/flags.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
package cmd
22

33
import (
4+
"fmt"
45
"github.com/spf13/pflag"
6+
"os"
7+
"transcoder/update"
58
)
69

7-
func WebFlags() {
10+
func CommonFlags() {
11+
pflag.Usage = func() {
12+
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", os.Args[0])
13+
pflag.PrintDefaults()
14+
os.Exit(0)
15+
}
16+
pflag.Bool("version", false, "Print version and exit")
17+
pflag.Bool("verbose", false, "Enable verbose logging")
818
pflag.Int("web.port", 8080, "WebServer Port")
919
pflag.String("web.token", "admin", "WebServer Port")
1020
pflag.String("web.domain", "http://localhost:8080", "Base domain where workers will try to download upload videos")
11-
21+
update.PFlags()
1222
}

cmd/viper.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package cmd
2+
3+
import (
4+
"errors"
5+
log "github.com/sirupsen/logrus"
6+
"github.com/spf13/pflag"
7+
"github.com/spf13/viper"
8+
"net/url"
9+
"reflect"
10+
"time"
11+
)
12+
13+
func ViperConfig(opts *CommandLineConfig) {
14+
15+
viper.SetConfigType("yaml")
16+
viper.AddConfigPath("/etc/transcoderd/")
17+
viper.AddConfigPath("$HOME/.transcoderd/")
18+
viper.AddConfigPath(".")
19+
viper.AutomaticEnv()
20+
viper.SetEnvPrefix("TR")
21+
err := viper.ReadInConfig()
22+
if err != nil {
23+
var configFileNotFoundError viper.ConfigFileNotFoundError
24+
switch {
25+
case errors.As(err, &configFileNotFoundError):
26+
log.Warnf("No Config File Found")
27+
default:
28+
log.Panic(err)
29+
}
30+
}
31+
pflag.Parse()
32+
log.SetFormatter(&log.TextFormatter{
33+
ForceColors: true,
34+
EnvironmentOverrideColors: true,
35+
})
36+
37+
err = viper.BindPFlags(pflag.CommandLine)
38+
if err != nil {
39+
log.Panic(err)
40+
}
41+
42+
err = viper.Unmarshal(opts, decodeHook())
43+
if err != nil {
44+
log.Panic(err)
45+
}
46+
if opts.Verbose {
47+
log.SetLevel(log.DebugLevel)
48+
} else {
49+
log.SetLevel(log.InfoLevel)
50+
}
51+
}
52+
func decodeHook() viper.DecoderConfigOption {
53+
return viper.DecodeHook(func(source reflect.Type, target reflect.Type, data interface{}) (interface{}, error) {
54+
if source.Kind() != reflect.String {
55+
return data, nil
56+
}
57+
58+
if target == reflect.TypeOf(url.URL{}) {
59+
return url.Parse(data.(string))
60+
}
61+
62+
if target == reflect.TypeOf(time.Duration(5)) {
63+
return time.ParseDuration(data.(string))
64+
}
65+
return data, nil
66+
})
67+
}

server/config/config.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package config
2+
3+
import (
4+
"transcoder/server/repository"
5+
"transcoder/server/scheduler"
6+
)
7+
8+
type Config struct {
9+
Database *repository.SQLServerConfig `mapstructure:"database"`
10+
Scheduler *scheduler.SchedulerConfig `mapstructure:"scheduler"`
11+
}

server/main.go

Lines changed: 23 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@ package main
22

33
import (
44
"context"
5-
"fmt"
65
log "github.com/sirupsen/logrus"
76
"github.com/spf13/pflag"
8-
"github.com/spf13/viper"
9-
"net/url"
107
"os"
118
"os/signal"
129
"path/filepath"
13-
"reflect"
1410
"sync"
1511
"syscall"
1612
"time"
@@ -23,110 +19,36 @@ import (
2319
"transcoder/version"
2420
)
2521

26-
type CmdLineOpts struct {
27-
Database repository.SQLServerConfig `mapstructure:"database"`
28-
Web web.WebServerConfig `mapstructure:"web"`
29-
Scheduler scheduler.SchedulerConfig `mapstructure:"scheduler"`
30-
NoUpdateMode bool `mapstructure:"noUpdateMode"`
31-
NoUpdates bool `mapstructure:"noUpdates"`
32-
UpdateCheckInterval time.Duration `mapstructure:"updateCheckInterval"`
33-
}
34-
3522
var (
3623
ApplicationName = "transcoderd-server"
37-
showVersion = false
38-
opts CmdLineOpts
24+
opts cmd.CommandLineConfig
3925
)
4026

4127
func init() {
42-
//Scheduler
43-
var verbose bool
44-
pflag.BoolVar(&showVersion, "version", false, "Print version and exit")
45-
pflag.BoolVar(&verbose, "verbose", false, "Enable verbose logging")
46-
pflag.Duration("updateCheckInterval", time.Minute*15, "Check for updates every X duration")
47-
48-
pflag.Duration("scheduler.scheduleTime", time.Minute*5, "Execute the scheduling loop every X seconds")
49-
pflag.Duration("scheduler.jobTimeout", time.Hour*24, "Requeue jobs that are running for more than X minutes")
50-
pflag.String("scheduler.sourcePath", "/data/current", "Download path")
51-
pflag.Int64("scheduler.minFileSize", 1e+8, "Min File Size")
52-
53-
//WebConfig Config
54-
55-
cmd.WebFlags()
56-
57-
//DB Config
58-
pflag.String("database.Driver", "postgres", "DB Driver")
59-
pflag.String("database.Host", "localhost", "DB Host")
60-
pflag.Int("database.port", 5432, "DB Port")
61-
pflag.String("database.User", "postgres", "DB User")
62-
pflag.String("database.Password", "postgres", "DB Password")
63-
pflag.String("database.Scheme", "server", "DB Scheme")
64-
update.PFlags()
65-
pflag.Usage = usage
66-
67-
//pflag.Parse()
68-
//viper.SetConfigFile("config")
69-
viper.SetConfigType("yaml")
70-
viper.AddConfigPath("/etc/transcoderd/")
71-
viper.AddConfigPath("$HOME/.transcoderd/")
72-
viper.AddConfigPath(".")
73-
viper.AutomaticEnv()
74-
viper.SetEnvPrefix("TR")
75-
err := viper.ReadInConfig()
76-
if err != nil {
77-
switch err.(type) {
78-
case viper.ConfigFileNotFoundError:
79-
log.Warnf("No Config File Found")
80-
default:
81-
log.Panic(err)
82-
}
83-
}
84-
pflag.Parse()
85-
log.SetFormatter(&log.TextFormatter{
86-
ForceColors: true,
87-
EnvironmentOverrideColors: true,
88-
})
89-
if verbose {
90-
log.SetLevel(log.DebugLevel)
91-
} else {
92-
log.SetLevel(log.InfoLevel)
93-
}
94-
viper.BindPFlags(pflag.CommandLine)
95-
96-
urlAndDurationDecoder := viper.DecodeHook(func(source reflect.Type, target reflect.Type, data interface{}) (interface{}, error) {
97-
if source.Kind() != reflect.String {
98-
return data, nil
99-
}
100-
if target == reflect.TypeOf(url.URL{}) {
101-
url, err := url.Parse(data.(string))
102-
return url, err
103-
} else if target == reflect.TypeOf(time.Duration(5)) {
104-
return time.ParseDuration(data.(string))
105-
}
106-
return data, nil
107-
108-
})
109-
err = viper.Unmarshal(&opts, urlAndDurationDecoder)
110-
if err != nil {
111-
log.Panic(err)
112-
}
28+
cmd.CommonFlags()
11329

114-
//Fix Paths
115-
opts.Scheduler.SourcePath = filepath.Clean(opts.Scheduler.SourcePath)
116-
helper.CheckPath(opts.Scheduler.SourcePath)
117-
}
30+
pflag.Duration("server.scheduler.scheduleTime", time.Minute*5, "Execute the scheduling loop every X seconds")
31+
pflag.Duration("server.scheduler.jobTimeout", time.Hour*24, "Requeue jobs that are running for more than X minutes")
32+
pflag.String("server.scheduler.sourcePath", "/data/current", "Download path")
33+
pflag.Int64("server.scheduler.minFileSize", 1e+8, "Min File Size")
34+
pflag.String("server.database.Driver", "postgres", "DB Driver")
35+
pflag.String("server.database.Host", "localhost", "DB Host")
36+
pflag.Int("server.database.port", 5432, "DB Port")
37+
pflag.String("server.database.User", "postgres", "DB User")
38+
pflag.String("server.database.Password", "postgres", "DB Password")
39+
pflag.String("server.database.Scheme", "server", "DB Scheme")
11840

119-
func usage() {
120-
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", os.Args[0])
121-
pflag.PrintDefaults()
122-
os.Exit(0)
41+
cmd.ViperConfig(&opts)
42+
43+
//Fix Paths
44+
serverConfig := opts.Server
45+
serverConfig.Scheduler.SourcePath = filepath.Clean(serverConfig.Scheduler.SourcePath)
46+
helper.CheckPath(serverConfig.Scheduler.SourcePath)
12347
}
12448

12549
func main() {
126-
if showVersion {
127-
version.LogVersion()
128-
os.Exit(0)
129-
}
50+
opts.PrintVersion()
51+
13052
wg := &sync.WaitGroup{}
13153
ctx, cancel := context.WithCancel(context.Background())
13254
sigs := make(chan os.Signal, 1)
@@ -159,7 +81,7 @@ func main() {
15981
func applicationRun(wg *sync.WaitGroup, ctx context.Context, updater *update.Updater) {
16082
//Repository persist
16183
var repo repository.Repository
162-
repo, err := repository.NewSQLRepository(opts.Database)
84+
repo, err := repository.NewSQLRepository(opts.Server.Database)
16385
if err != nil {
16486
log.Panic(err)
16587
}
@@ -169,14 +91,14 @@ func applicationRun(wg *sync.WaitGroup, ctx context.Context, updater *update.Upd
16991
}
17092

17193
//Scheduler
172-
scheduler, err := scheduler.NewScheduler(opts.Scheduler, repo)
94+
scheduler, err := scheduler.NewScheduler(opts.Server.Scheduler, repo)
17395
if err != nil {
17496
log.Panic(err)
17597
}
17698
scheduler.Run(wg, ctx)
17799

178100
//WebConfig Server
179-
var webServer *web.WebServer
101+
var webServer *web.Server
180102
webServer = web.NewWebServer(opts.Web, scheduler, updater)
181103
webServer.Run(wg, ctx)
182104
}

server/repository/repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ type SQLServerConfig struct {
134134
Driver string `mapstructure:"driver", envconfig:"DB_DRIVER"`
135135
}
136136

137-
func NewSQLRepository(config SQLServerConfig) (*SQLRepository, error) {
137+
func NewSQLRepository(config *SQLServerConfig) (*SQLRepository, error) {
138138
connectionString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", config.Host, config.Port, config.User, config.Password, config.Scheme)
139139
db, err := sql.Open(config.Driver, connectionString)
140140
if err != nil {

server/scheduler/scheduler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type SchedulerConfig struct {
4444
}
4545

4646
type RuntimeScheduler struct {
47-
config SchedulerConfig
47+
config *SchedulerConfig
4848
repo repository.Repository
4949
checksumChan chan PathChecksum
5050
pathChecksumMap map[string]string
@@ -175,7 +175,7 @@ func (R *RuntimeScheduler) completeJob(ctx context.Context, jobEvent *model.Task
175175
return nil
176176
}
177177

178-
func NewScheduler(config SchedulerConfig, repo repository.Repository) (*RuntimeScheduler, error) {
178+
func NewScheduler(config *SchedulerConfig, repo repository.Repository) (*RuntimeScheduler, error) {
179179
runtimeScheduler := &RuntimeScheduler{
180180
config: config,
181181
repo: repo,

0 commit comments

Comments
 (0)