11package main
22
33import (
4+ "bytes"
45 "fmt"
5- "github.com/cooperspencer/gickup/onedev"
6- "io/ioutil"
6+ "io"
77 "os"
88 "os/user"
99 "path/filepath"
10+ "strconv"
1011 "strings"
1112 "time"
1213
14+ "github.com/cooperspencer/gickup/onedev"
15+
1316 "github.com/alecthomas/kong"
1417 "github.com/cooperspencer/gickup/bitbucket"
1518 "github.com/cooperspencer/gickup/gitea"
@@ -29,36 +32,55 @@ import (
2932)
3033
3134var cli struct {
32- Configfile string `arg name:"conf" help:"Path to the configfile." default:"conf.yml"`
33- Version bool `flag name:"version" help:"Show version."`
34- Dry bool `flag name:"dryrun" help:"Make a dry-run."`
35- Quiet bool `flag name:"quiet" help:"Output only warnings, errors, and fatal messages to stderr log output"`
36- Silent bool `flag name:"silent" help:"Suppress all stderr log output"`
35+ Configfiles [] string `arg name:"conf" help:"Path to the configfile." default:"conf.yml"`
36+ Version bool `flag name:"version" help:"Show version."`
37+ Dry bool `flag name:"dryrun" help:"Make a dry-run."`
38+ Quiet bool `flag name:"quiet" help:"Output only warnings, errors, and fatal messages to stderr log output"`
39+ Silent bool `flag name:"silent" help:"Suppress all stderr log output"`
3740}
3841
3942var version = "unknown"
4043
41- func readConfigFile (configfile string ) * types.Conf {
42- cfgdata , err := ioutil .ReadFile (configfile )
44+ func readConfigFile (configfile string ) []* types.Conf {
45+ conf := []* types.Conf {}
46+ cfgdata , err := os .ReadFile (configfile )
4347 if err != nil {
4448 log .Fatal ().
4549 Str ("stage" , "readconfig" ).
4650 Str ("file" , configfile ).
4751 Msgf ("Cannot open config file from %s" , types .Red (configfile ))
4852 }
4953
50- t := types.Conf {}
54+ // t := types.Conf{}
5155
52- err = yaml .Unmarshal ( cfgdata , & t )
56+ dec : = yaml .NewDecoder ( bytes . NewReader ( cfgdata ) )
5357
54- if err != nil {
55- log .Fatal ().
56- Str ("stage" , "readconfig" ).
57- Str ("file" , configfile ).
58- Msg ("Cannot map yml config file to interface, possible syntax error" )
58+ // err = yaml.Unmarshal(cfgdata, &t)
59+
60+ i := 0
61+ for {
62+ var c * types.Conf
63+ err = dec .Decode (& c )
64+ if err == io .EOF {
65+ break
66+ } else if err != nil {
67+ if len (conf ) > 0 {
68+ log .Fatal ().
69+ Str ("stage" , "readconfig" ).
70+ Str ("file" , configfile ).
71+ Msgf ("an error occured in the %d place of %s" , i , configfile )
72+ } else {
73+ log .Fatal ().
74+ Str ("stage" , "readconfig" ).
75+ Str ("file" , configfile ).
76+ Msg ("Cannot map yml config file to interface, possible syntax error" )
77+ }
78+ }
79+ conf = append (conf , c )
80+ i ++
5981 }
6082
61- return & t
83+ return conf
6284}
6385
6486func getUserHome () (string , error ) {
@@ -149,43 +171,45 @@ func backup(repos []types.Repo, conf *types.Conf) {
149171 }
150172}
151173
152- func runBackup (conf * types.Conf ) {
174+ func runBackup (conf * types.Conf , num int ) {
153175 log .Info ().Msg ("Backup run starting" )
154176
177+ numstring := strconv .Itoa (num )
178+
155179 startTime := time .Now ()
156180
157181 prometheus .JobsStarted .Inc ()
158182
159183 // Github
160184 repos := github .Get (conf )
161- prometheus .CountReposDiscovered .WithLabelValues ("github" ).Set (float64 (len (repos )))
185+ prometheus .CountReposDiscovered .WithLabelValues ("github" , numstring ).Set (float64 (len (repos )))
162186 backup (repos , conf )
163187
164188 // Gitea
165189 repos = gitea .Get (conf )
166- prometheus .CountReposDiscovered .WithLabelValues ("gitea" ).Set (float64 (len (repos )))
190+ prometheus .CountReposDiscovered .WithLabelValues ("gitea" , numstring ).Set (float64 (len (repos )))
167191 backup (repos , conf )
168192
169193 // Gogs
170194 repos = gogs .Get (conf )
171- prometheus .CountReposDiscovered .WithLabelValues ("gogs" ).Set (float64 (len (repos )))
195+ prometheus .CountReposDiscovered .WithLabelValues ("gogs" , numstring ).Set (float64 (len (repos )))
172196 backup (repos , conf )
173197
174198 // Gitlab
175199 repos = gitlab .Get (conf )
176- prometheus .CountReposDiscovered .WithLabelValues ("gitlab" ).Set (float64 (len (repos )))
200+ prometheus .CountReposDiscovered .WithLabelValues ("gitlab" , numstring ).Set (float64 (len (repos )))
177201 backup (repos , conf )
178202
179203 repos = bitbucket .Get (conf )
180- prometheus .CountReposDiscovered .WithLabelValues ("bitbucket" ).Set (float64 (len (repos )))
204+ prometheus .CountReposDiscovered .WithLabelValues ("bitbucket" , numstring ).Set (float64 (len (repos )))
181205 backup (repos , conf )
182206
183207 repos = whatever .Get (conf )
184- prometheus .CountReposDiscovered .WithLabelValues ("whatever" ).Set (float64 (len (repos )))
208+ prometheus .CountReposDiscovered .WithLabelValues ("whatever" , numstring ).Set (float64 (len (repos )))
185209 backup (repos , conf )
186210
187211 repos = onedev .Get (conf )
188- prometheus .CountReposDiscovered .WithLabelValues ("onedev" ).Set (float64 (len (repos )))
212+ prometheus .CountReposDiscovered .WithLabelValues ("onedev" , numstring ).Set (float64 (len (repos )))
189213 backup (repos , conf )
190214
191215 endTime := time .Now ()
@@ -250,51 +274,74 @@ func main() {
250274 Msgf ("this is a %s" , types .Blue ("dry run" ))
251275 }
252276
253- log .Info ().Str ("file" , cli .Configfile ).
254- Msgf ("Reading %s" , types .Green (cli .Configfile ))
277+ confs := []* types.Conf {}
278+ for _ , f := range cli .Configfiles {
279+ log .Info ().Str ("file" , f ).
280+ Msgf ("Reading %s" , types .Green (f ))
255281
256- conf := readConfigFile (cli .Configfile )
257- if conf .Log .Timeformat == "" {
258- conf .Log .Timeformat = timeformat
282+ confs = append (confs , readConfigFile (f )... )
283+ }
284+ if confs [0 ].Log .Timeformat == "" {
285+ confs [0 ].Log .Timeformat = timeformat
259286 }
260287
261- log .Logger = logger .CreateLogger (conf .Log )
288+ log .Logger = logger .CreateLogger (confs [ 0 ] .Log )
262289
263- // one pair per source-destination
264- pairs := conf .Source .Count () * conf .Destination .Count ()
265- log .Info ().
266- Int ("sources" , conf .Source .Count ()).
267- Int ("destinations" , conf .Destination .Count ()).
268- Int ("pairs" , pairs ).
269- Msg ("Configuration loaded" )
290+ validcron := confs [0 ].HasValidCronSpec ()
270291
271- if conf .HasValidCronSpec () {
272- c := cron .New ()
292+ var c * cron.Cron
273293
274- logNextRun (conf )
294+ if validcron {
295+ c = cron .New ()
296+ c .Start ()
297+ }
275298
276- _ , err := c .AddFunc (conf .Cron , func () {
277- runBackup (conf )
278- })
279- if err != nil {
280- log .Fatal ().
281- Int ("sources" , conf .Source .Count ()).
282- Int ("destinations" , conf .Destination .Count ()).
283- Int ("pairs" , pairs ).
284- Msg (err .Error ())
299+ sourcecount := 0
300+ destinationcount := 0
301+ // one pair per source-destination
302+ for num , conf := range confs {
303+ pairs := conf .Source .Count () * conf .Destination .Count ()
304+ sourcecount += conf .Source .Count ()
305+ destinationcount += conf .Destination .Count ()
306+ log .Info ().
307+ Int ("sources" , conf .Source .Count ()).
308+ Int ("destinations" , conf .Destination .Count ()).
309+ Int ("pairs" , pairs ).
310+ Msg ("Configuration loaded" )
311+
312+ if ! conf .HasValidCronSpec () {
313+ conf .Cron = confs [0 ].Cron
285314 }
286315
287- c .Start ()
316+ if conf .HasValidCronSpec () && validcron {
317+ conf := conf // https://stackoverflow.com/questions/57095167/how-do-i-create-multiple-cron-function-by-looping-through-a-list
318+ num := num
319+
320+ logNextRun (conf )
321+
322+ _ , err := c .AddFunc (conf .Cron , func () {
323+ runBackup (conf , num )
324+ })
325+ if err != nil {
326+ log .Fatal ().
327+ Int ("sources" , conf .Source .Count ()).
328+ Int ("destinations" , conf .Destination .Count ()).
329+ Int ("pairs" , pairs ).
330+ Msg (err .Error ())
331+ }
332+ } else {
333+ runBackup (conf , num )
334+ }
335+ }
288336
289- if conf .HasAllPrometheusConf () {
290- prometheus .CountSourcesConfigured .Add (float64 (conf .Source .Count ()))
291- prometheus .CountDestinationsConfigured .Add (float64 (conf .Destination .Count ()))
292- prometheus .Serve (conf .Metrics .Prometheus )
337+ if validcron {
338+ if confs [0 ].HasAllPrometheusConf () {
339+ prometheus .CountSourcesConfigured .Add (float64 (sourcecount ))
340+ prometheus .CountDestinationsConfigured .Add (float64 (destinationcount ))
341+ prometheus .Serve (confs [0 ].Metrics .Prometheus )
293342 } else {
294343 playsForever ()
295344 }
296- } else {
297- runBackup (conf )
298345 }
299346}
300347
0 commit comments