17840: Deduplicate flag-parsing code.
[arvados.git] / services / keep-web / 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         "flag"
9         "fmt"
10         "mime"
11         "os"
12
13         "git.arvados.org/arvados.git/lib/cmd"
14         "git.arvados.org/arvados.git/lib/config"
15         "git.arvados.org/arvados.git/sdk/go/arvados"
16         "github.com/coreos/go-systemd/daemon"
17         "github.com/ghodss/yaml"
18         "github.com/sirupsen/logrus"
19         log "github.com/sirupsen/logrus"
20 )
21
22 var (
23         version = "dev"
24 )
25
26 // Config specifies server configuration.
27 type Config struct {
28         Client  arvados.Client
29         Cache   cache
30         cluster *arvados.Cluster
31 }
32
33 func newConfig(logger logrus.FieldLogger, arvCfg *arvados.Config) *Config {
34         cfg := Config{}
35         var cls *arvados.Cluster
36         var err error
37         if cls, err = arvCfg.GetCluster(""); err != nil {
38                 log.Fatal(err)
39         }
40         cfg.cluster = cls
41         cfg.Cache.config = &cfg.cluster.Collections.WebDAVCache
42         cfg.Cache.cluster = cls
43         cfg.Cache.logger = logger
44         return &cfg
45 }
46
47 func init() {
48         // MakeArvadosClient returns an error if this env var isn't
49         // available as a default token (even if we explicitly set a
50         // different token before doing anything with the client). We
51         // set this dummy value during init so it doesn't clobber the
52         // one used by "run test servers".
53         if os.Getenv("ARVADOS_API_TOKEN") == "" {
54                 os.Setenv("ARVADOS_API_TOKEN", "xxx")
55         }
56
57         log.SetFormatter(&log.JSONFormatter{
58                 TimestampFormat: "2006-01-02T15:04:05.000000000Z07:00",
59         })
60 }
61
62 func configure(logger log.FieldLogger, args []string) (*Config, error) {
63         flags := flag.NewFlagSet(args[0], flag.ContinueOnError)
64
65         loader := config.NewLoader(os.Stdin, logger)
66         loader.SetupFlags(flags)
67
68         dumpConfig := flags.Bool("dump-config", false,
69                 "write current configuration to stdout and exit")
70         getVersion := flags.Bool("version", false,
71                 "print version information and exit.")
72
73         prog := args[0]
74         args = loader.MungeLegacyConfigArgs(logger, args[1:], "-legacy-keepweb-config")
75         if ok, code := cmd.ParseFlags(flags, prog, args, "", os.Stderr); !ok {
76                 os.Exit(code)
77         } else if *getVersion {
78                 fmt.Printf("%s %s\n", args[0], version)
79                 return nil, nil
80         }
81
82         arvCfg, err := loader.Load()
83         if err != nil {
84                 return nil, err
85         }
86         cfg := newConfig(logger, arvCfg)
87
88         if *dumpConfig {
89                 out, err := yaml.Marshal(cfg)
90                 if err != nil {
91                         return nil, err
92                 }
93                 _, err = os.Stdout.Write(out)
94                 return nil, err
95         }
96         return cfg, nil
97 }
98
99 func main() {
100         logger := log.New()
101
102         cfg, err := configure(logger, os.Args)
103         if err != nil {
104                 logger.Fatal(err)
105         } else if cfg == nil {
106                 return
107         }
108
109         log.Printf("keep-web %s started", version)
110
111         if ext := ".txt"; mime.TypeByExtension(ext) == "" {
112                 log.Warnf("cannot look up MIME type for %q -- this probably means /etc/mime.types is missing -- clients will see incorrect content types", ext)
113         }
114
115         os.Setenv("ARVADOS_API_HOST", cfg.cluster.Services.Controller.ExternalURL.Host)
116         srv := &server{Config: cfg}
117         if err := srv.Start(logrus.StandardLogger()); err != nil {
118                 log.Fatal(err)
119         }
120         if _, err := daemon.SdNotify(false, "READY=1"); err != nil {
121                 log.Printf("Error notifying init daemon: %v", err)
122         }
123         log.Println("Listening at", srv.Addr)
124         if err := srv.Wait(); err != nil {
125                 log.Fatal(err)
126         }
127 }