From 7c1c56b2fe3c903e3ecc3838a3c7e5d102700e8f Mon Sep 17 00:00:00 2001 From: Motalleb Fallahnezhad Date: Sun, 26 May 2024 00:32:45 +0330 Subject: [PATCH] init: config structure --- cmd/root.go | 33 ++++++++++++++-------------- config.example.yaml | 52 +++++++++++++++++++++++++++++++++++++++++++++ config/config.go | 51 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 4 ++++ logger/logger.go | 14 ++++++++++++ main.go | 10 ++++++++- 7 files changed, 147 insertions(+), 18 deletions(-) create mode 100644 config.example.yaml create mode 100644 config/config.go create mode 100644 logger/logger.go diff --git a/cmd/root.go b/cmd/root.go index 12506a7..9e774f3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,23 +7,27 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/FMotalleb/crontab-go/config" ) -var cfgFile string +var ( + cfgFile string + Config *config.Config = &config.Config{} +) // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "crontab-go", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, + Short: "Crontab replacement for containers", + Long: `Cronjob-go is a powerful, lightweight, and highly configurable Golang application +designed to replace the traditional crontab in Docker environments. +With its seamless integration and easy-to-use YAML configuration, +Cronjob-go simplifies the process of scheduling and managing recurring tasks +within your containerized applications.`, // Uncomment the following line if your bare application // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + Run: func(cmd *cobra.Command, args []string) {}, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -42,7 +46,7 @@ func init() { // Cobra supports persistent flags, which, if defined here, // will be global for your application. - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.crontab-go.yaml)") + rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is config.yaml)") // Cobra also supports local flags, which will only run // when this action is called directly. @@ -55,14 +59,8 @@ func initConfig() { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { - // Find home directory. - home, err := os.UserHomeDir() - cobra.CheckErr(err) - - // Search config in home directory with name ".crontab-go" (without extension). - viper.AddConfigPath(home) + viper.SetConfigName("config") viper.SetConfigType("yaml") - viper.SetConfigName(".crontab-go") } viper.AutomaticEnv() // read in environment variables that match @@ -71,4 +69,5 @@ func initConfig() { if err := viper.ReadInConfig(); err == nil { fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) } + viper.Unmarshal(Config) } diff --git a/config.example.yaml b/config.example.yaml new file mode 100644 index 0000000..74391fd --- /dev/null +++ b/config.example.yaml @@ -0,0 +1,52 @@ +#TODO: unix/tcp socket controller +#TODO: prometheus exporter + +log: + timestamp_format: "2006-01-02T15:04:05.000Z" + format: json + file: ./cron.log + stdout: true + level: debug + +jobs: + backup-database: + description: Backup the production database + enabled: true + exe: + command: /app/backup.sh + scheduler: + cron: "0 0 2 * * *" + retry_delay: 123s + retries: 3 + on_failure: + webhooks: + - address: http://google.com/ + headers: + test: test1 + data: { "job": "@job", "status": "failed" } + env: + DB_HOST: 10.0.0.5 + DB_USER: myuser + DB_PASS: mypassword + metadata: + owner: john.doe@company.com + team: database-team + + # cleanup-logs: + # description: Clean up old log files + # enabled: true + # exe: + # command: /app/cleanup.sh + # scheduler: + # interval: 1h # Run every hour + # retries: 1 + # on_failure: + # exit: true + # webhooks: + # - address: http://google.com/ + # headers: + # test: test1 + # data: { "job": "@job", "status": "failed" } + # metadata: + # owner: jane.smith@company.com + # team: devops-team diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..935606a --- /dev/null +++ b/config/config.go @@ -0,0 +1,51 @@ +// Package config contains structured representation of config.yaml file +package config + +import "time" + +type Config struct { + Log LogConfig `yaml:"log"` + Jobs map[string]JobConfig `yaml:"jobs"` +} + +type LogConfig struct { + TimeStampFormat string `yaml:"timestamp_format"` + Format string `yaml:"format"` + File string `yaml:"file"` + Stdout bool `yaml:"stdout"` + Level string `yaml:"level"` +} + +type JobConfig struct { + Description string `yaml:"description"` + Enabled bool `yaml:"enabled"` + Exe JobExe `yaml:"exe"` + Scheduler JobScheduler `yaml:"scheduler"` + Retries int `yaml:"retries"` + RetryDelay time.Duration `yaml:"retry_delay"` + OnFailure JobOnFailure `yaml:"on_failure"` + Env map[string]string `yaml:"env"` + Metadata JobMetadata `yaml:"metadata"` +} + +type JobExe struct { + Command string `yaml:"command"` + Args []string `yaml:"args"` +} + +type JobScheduler struct { + Cron string `yaml:"cron"` + Interval string `yaml:"interval"` +} + +type JobOnFailure struct { + Webhooks []WebHook `yaml:"webhooks"` + ShouldExit bool `yaml:"exit"` +} +type WebHook struct { + Address string `yaml:"address"` + Headers map[string]string `yaml:"headers"` + Data map[string]any `yaml:"data"` +} + +type JobMetadata = map[string]string diff --git a/go.mod b/go.mod index f7683b0..80239a9 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/FMotalleb/crontab-go go 1.22 require ( + github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.2 ) diff --git a/go.sum b/go.sum index b6a7dcc..8c76228 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -49,6 +51,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= @@ -61,6 +64,7 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..0ecf31c --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,14 @@ +// Package logger contains basic logging logic of the application +package logger + +import ( + "fmt" + + "github.com/sirupsen/logrus" +) + +func SetupLogger(parent logrus.Entry, section string) *logrus.Entry { + parentSection := parent.Data["section"] + sectionValue := fmt.Sprintf("%s/%s", parentSection, section) + return parent.WithField("section", sectionValue) +} diff --git a/main.go b/main.go index ec0d1ef..6c2c122 100644 --- a/main.go +++ b/main.go @@ -16,8 +16,16 @@ along with this program. If not, see . */ package main -import "github.com/FMotalleb/crontab-go/cmd" +import ( + "encoding/json" + + "github.com/sirupsen/logrus" + + "github.com/FMotalleb/crontab-go/cmd" +) func main() { cmd.Execute() + j, _ := json.Marshal(cmd.Config) + logrus.Infoln(string(j)) }