15112: Use FieldLogger interface so tests can use ctxlog.TestLogger.
[arvados.git] / services / keep-balance / main.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package main
6
7 import (
8         "encoding/json"
9         "flag"
10         "fmt"
11         "log"
12         "net/http"
13         "os"
14         "time"
15
16         "git.curoverse.com/arvados.git/sdk/go/arvados"
17         "git.curoverse.com/arvados.git/sdk/go/config"
18         "github.com/sirupsen/logrus"
19 )
20
21 var debugf = func(string, ...interface{}) {}
22
23 func main() {
24         var cfg Config
25         var runOptions RunOptions
26
27         configPath := flag.String("config", defaultConfigPath,
28                 "`path` of JSON or YAML configuration file")
29         serviceListPath := flag.String("config.KeepServiceList", "",
30                 "`path` of JSON or YAML file with list of keep services to balance, as given by \"arv keep_service list\" "+
31                         "(default: config[\"KeepServiceList\"], or if none given, get all available services and filter by config[\"KeepServiceTypes\"])")
32         flag.BoolVar(&runOptions.Once, "once", false,
33                 "balance once and then exit")
34         flag.BoolVar(&runOptions.CommitPulls, "commit-pulls", false,
35                 "send pull requests (make more replicas of blocks that are underreplicated or are not in optimal rendezvous probe order)")
36         flag.BoolVar(&runOptions.CommitTrash, "commit-trash", false,
37                 "send trash requests (delete unreferenced old blocks, and excess replicas of overreplicated blocks)")
38         dumpConfig := flag.Bool("dump-config", false, "write current configuration to stdout and exit")
39         dumpFlag := flag.Bool("dump", false, "dump details for each block to stdout")
40         debugFlag := flag.Bool("debug", false, "enable debug messages")
41         getVersion := flag.Bool("version", false, "Print version information and exit.")
42         flag.Usage = usage
43         flag.Parse()
44
45         // Print version information if requested
46         if *getVersion {
47                 fmt.Printf("keep-balance %s\n", version)
48                 return
49         }
50
51         mustReadConfig(&cfg, *configPath)
52         if *serviceListPath != "" {
53                 mustReadConfig(&cfg.KeepServiceList, *serviceListPath)
54         }
55
56         if *dumpConfig {
57                 log.Fatal(config.DumpAndExit(cfg))
58         }
59
60         to := time.Duration(cfg.RequestTimeout)
61         if to == 0 {
62                 to = 30 * time.Minute
63         }
64         arvados.DefaultSecureClient.Timeout = to
65         arvados.InsecureHTTPClient.Timeout = to
66         http.DefaultClient.Timeout = to
67
68         log.Printf("keep-balance %s started", version)
69
70         if *debugFlag {
71                 debugf = log.Printf
72                 if j, err := json.Marshal(cfg); err != nil {
73                         log.Fatal(err)
74                 } else {
75                         log.Printf("config is %s", j)
76                 }
77         }
78         if *dumpFlag {
79                 dumper := logrus.New()
80                 dumper.Out = os.Stdout
81                 dumper.Formatter = &logrus.TextFormatter{}
82                 runOptions.Dumper = dumper
83         }
84         srv, err := NewServer(cfg, runOptions)
85         if err != nil {
86                 // (don't run)
87         } else if runOptions.Once {
88                 _, err = srv.Run()
89         } else {
90                 err = srv.RunForever(nil)
91         }
92         if err != nil {
93                 log.Fatal(err)
94         }
95 }
96
97 func mustReadConfig(dst interface{}, path string) {
98         if err := config.LoadFile(dst, path); err != nil {
99                 log.Fatal(err)
100         }
101 }