blob: 9903b04b0ff445408abfa7df264a26bbbccfd9df [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
2// SPDX-License-Identifier: Apache-2.0
3
Serge Bazanskicaa12082023-02-16 14:54:04 +01004package main
5
6import (
7 "context"
Tim Windelschmidtd5f851b2024-04-23 14:59:37 +02008 "errors"
Serge Bazanskicaa12082023-02-16 14:54:04 +01009 "flag"
10 "fmt"
11 "os"
Tim Windelschmidtb765f242024-05-08 01:40:02 +020012 "os/signal"
Serge Bazanskicaa12082023-02-16 14:54:04 +010013
Jan Schär0175d7a2025-03-26 12:57:23 +000014 "golang.org/x/crypto/ssh"
Tim Windelschmidt44cacd62023-06-12 23:54:45 +020015 "k8s.io/klog/v2"
Serge Bazanskicaa12082023-02-16 14:54:04 +010016
17 "source.monogon.dev/cloud/bmaas/bmdb"
Serge Bazanski77628312023-02-15 23:33:22 +010018 "source.monogon.dev/cloud/bmaas/bmdb/webug"
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020019 "source.monogon.dev/cloud/equinix/wrapngo"
Serge Bazanskicaa12082023-02-16 14:54:04 +010020 "source.monogon.dev/cloud/lib/component"
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020021 "source.monogon.dev/cloud/shepherd/manager"
Serge Bazanskicaa12082023-02-16 14:54:04 +010022)
23
24type Config struct {
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020025 Component component.ComponentConfig
26 BMDB bmdb.BMDB
27 WebugConfig webug.Config
Serge Bazanskicaa12082023-02-16 14:54:04 +010028
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020029 SSHKey manager.SSHKey
Serge Bazanskicaa12082023-02-16 14:54:04 +010030 InitializerConfig manager.InitializerConfig
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020031 ProvisionerConfig manager.ProvisionerConfig
Serge Bazanskiae004682023-04-18 13:28:48 +020032 RecovererConfig manager.RecovererConfig
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020033
34 API wrapngo.Opts
35 Provider providerConfig
36 UpdaterConfig UpdaterConfig
Serge Bazanskicaa12082023-02-16 14:54:04 +010037}
38
39// TODO(q3k): factor this out to BMDB library?
40func runtimeInfo() string {
41 hostname, _ := os.Hostname()
42 if hostname == "" {
43 hostname = "UNKNOWN"
44 }
45 return fmt.Sprintf("host %s", hostname)
46}
47
48func (c *Config) RegisterFlags() {
49 c.Component.RegisterFlags("shepherd")
50 c.BMDB.ComponentName = "shepherd-equinix"
51 c.BMDB.RuntimeInfo = runtimeInfo()
52 c.BMDB.Database.RegisterFlags("bmdb")
Serge Bazanski77628312023-02-15 23:33:22 +010053 c.WebugConfig.RegisterFlags()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020054
55 c.SSHKey.RegisterFlags()
56 c.InitializerConfig.RegisterFlags()
57 c.ProvisionerConfig.RegisterFlags()
58 c.RecovererConfig.RegisterFlags()
59
Serge Bazanskicaa12082023-02-16 14:54:04 +010060 c.API.RegisterFlags()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020061 c.Provider.RegisterFlags()
62 c.UpdaterConfig.RegisterFlags()
Serge Bazanskicaa12082023-02-16 14:54:04 +010063}
64
65func main() {
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020066 var c Config
Serge Bazanskicaa12082023-02-16 14:54:04 +010067 c.RegisterFlags()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020068
Serge Bazanskicaa12082023-02-16 14:54:04 +010069 flag.Parse()
Tim Windelschmidt44cacd62023-06-12 23:54:45 +020070 if flag.NArg() > 0 {
71 klog.Exitf("unexpected positional arguments: %v", flag.Args())
72 }
Serge Bazanskicaa12082023-02-16 14:54:04 +010073
Serge Bazanskic50f6942023-04-24 18:27:22 +020074 registry := c.Component.PrometheusRegistry()
75 c.BMDB.EnableMetrics(registry)
76
Tim Windelschmidtb765f242024-05-08 01:40:02 +020077 ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
Serge Bazanskifbda89e2023-04-24 17:43:58 +020078 c.Component.StartPrometheus(ctx)
Serge Bazanskicaa12082023-02-16 14:54:04 +010079
80 if c.API.APIKey == "" || c.API.User == "" {
81 klog.Exitf("-equinix_api_username and -equinix_api_key must be set")
82 }
Serge Bazanskidea7cd02023-04-26 13:58:17 +020083 c.API.MetricsRegistry = registry
Serge Bazanskicaa12082023-02-16 14:54:04 +010084 api := wrapngo.New(&c.API)
85
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020086 provider, err := c.Provider.New(&c.SSHKey, api)
Serge Bazanskicaa12082023-02-16 14:54:04 +010087 if err != nil {
88 klog.Exitf("%v", err)
89 }
90
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020091 sshSigner, err := c.SSHKey.Signer()
Serge Bazanskicaa12082023-02-16 14:54:04 +010092 if err != nil {
93 klog.Exitf("%v", err)
94 }
95
Jan Schär0175d7a2025-03-26 12:57:23 +000096 c.InitializerConfig.SSHConfig.Auth = []ssh.AuthMethod{ssh.PublicKeys(sshSigner)}
97 // Equinix OS installations always use root.
98 c.InitializerConfig.SSHConfig.User = "root"
99 // Ignore the host key, since it's likely the first time anything logs into
100 // this device, and also because there's no way of knowing its fingerprint.
101 c.InitializerConfig.SSHConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200102
103 provisioner, err := manager.NewProvisioner(provider, c.ProvisionerConfig)
104 if err != nil {
105 klog.Exitf("%v", err)
106 }
107
Jan Schär0175d7a2025-03-26 12:57:23 +0000108 initializer, err := manager.NewInitializer(provider, c.InitializerConfig)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200109 if err != nil {
110 klog.Exitf("%v", err)
111 }
112
113 recoverer, err := manager.NewRecoverer(provider, c.RecovererConfig)
Serge Bazanskiae004682023-04-18 13:28:48 +0200114 if err != nil {
115 klog.Exitf("%v", err)
116 }
117
Serge Bazanskiafd3cf82023-04-19 17:43:46 +0200118 updater, err := c.UpdaterConfig.New(api)
119 if err != nil {
120 klog.Exitf("%v", err)
121 }
122
Serge Bazanskicaa12082023-02-16 14:54:04 +0100123 conn, err := c.BMDB.Open(true)
124 if err != nil {
125 klog.Exitf("Failed to open BMDB connection: %v", err)
126 }
Serge Bazanski77628312023-02-15 23:33:22 +0100127
Serge Bazanskicaa12082023-02-16 14:54:04 +0100128 go func() {
129 err = provisioner.Run(ctx, conn)
130 if err != nil {
131 klog.Exit(err)
132 }
133 }()
134 go func() {
Serge Bazanski86a714d2023-04-17 15:54:21 +0200135 err = manager.RunControlLoop(ctx, conn, initializer)
Serge Bazanskicaa12082023-02-16 14:54:04 +0100136 if err != nil {
137 klog.Exit(err)
138 }
139 }()
Serge Bazanski77628312023-02-15 23:33:22 +0100140 go func() {
Serge Bazanskiae004682023-04-18 13:28:48 +0200141 err = manager.RunControlLoop(ctx, conn, recoverer)
142 if err != nil {
143 klog.Exit(err)
144 }
145 }()
146 go func() {
Serge Bazanskiafd3cf82023-04-19 17:43:46 +0200147 err = updater.Run(ctx, conn)
148 if err != nil {
149 klog.Exit(err)
150 }
151 }()
152 go func() {
Tim Windelschmidtd5f851b2024-04-23 14:59:37 +0200153 if err := c.WebugConfig.Start(ctx, conn); err != nil && !errors.Is(err, ctx.Err()) {
Serge Bazanski77628312023-02-15 23:33:22 +0100154 klog.Exitf("Failed to start webug: %v", err)
155 }
156 }()
Serge Bazanskicaa12082023-02-16 14:54:04 +0100157
158 <-ctx.Done()
159}