blob: 13220399091f9914e1790455466159c78765b71c [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
Tim Windelschmidtd0e39cb2024-09-16 16:14:00 +020014 xssh "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"
Tim Windelschmidtd0e39cb2024-09-16 16:14:00 +020022 "source.monogon.dev/go/net/ssh"
Serge Bazanskicaa12082023-02-16 14:54:04 +010023)
24
25type Config struct {
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020026 Component component.ComponentConfig
27 BMDB bmdb.BMDB
28 WebugConfig webug.Config
Serge Bazanskicaa12082023-02-16 14:54:04 +010029
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020030 SSHKey manager.SSHKey
Serge Bazanskicaa12082023-02-16 14:54:04 +010031 InitializerConfig manager.InitializerConfig
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020032 ProvisionerConfig manager.ProvisionerConfig
Serge Bazanskiae004682023-04-18 13:28:48 +020033 RecovererConfig manager.RecovererConfig
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020034
35 API wrapngo.Opts
36 Provider providerConfig
37 UpdaterConfig UpdaterConfig
Serge Bazanskicaa12082023-02-16 14:54:04 +010038}
39
40// TODO(q3k): factor this out to BMDB library?
41func runtimeInfo() string {
42 hostname, _ := os.Hostname()
43 if hostname == "" {
44 hostname = "UNKNOWN"
45 }
46 return fmt.Sprintf("host %s", hostname)
47}
48
49func (c *Config) RegisterFlags() {
50 c.Component.RegisterFlags("shepherd")
51 c.BMDB.ComponentName = "shepherd-equinix"
52 c.BMDB.RuntimeInfo = runtimeInfo()
53 c.BMDB.Database.RegisterFlags("bmdb")
Serge Bazanski77628312023-02-15 23:33:22 +010054 c.WebugConfig.RegisterFlags()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020055
56 c.SSHKey.RegisterFlags()
57 c.InitializerConfig.RegisterFlags()
58 c.ProvisionerConfig.RegisterFlags()
59 c.RecovererConfig.RegisterFlags()
60
Serge Bazanskicaa12082023-02-16 14:54:04 +010061 c.API.RegisterFlags()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020062 c.Provider.RegisterFlags()
63 c.UpdaterConfig.RegisterFlags()
Serge Bazanskicaa12082023-02-16 14:54:04 +010064}
65
66func main() {
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020067 var c Config
Serge Bazanskicaa12082023-02-16 14:54:04 +010068 c.RegisterFlags()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020069
Serge Bazanskicaa12082023-02-16 14:54:04 +010070 flag.Parse()
Tim Windelschmidt44cacd62023-06-12 23:54:45 +020071 if flag.NArg() > 0 {
72 klog.Exitf("unexpected positional arguments: %v", flag.Args())
73 }
Serge Bazanskicaa12082023-02-16 14:54:04 +010074
Serge Bazanskic50f6942023-04-24 18:27:22 +020075 registry := c.Component.PrometheusRegistry()
76 c.BMDB.EnableMetrics(registry)
77
Tim Windelschmidtb765f242024-05-08 01:40:02 +020078 ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
Serge Bazanskifbda89e2023-04-24 17:43:58 +020079 c.Component.StartPrometheus(ctx)
Serge Bazanskicaa12082023-02-16 14:54:04 +010080
81 if c.API.APIKey == "" || c.API.User == "" {
82 klog.Exitf("-equinix_api_username and -equinix_api_key must be set")
83 }
Serge Bazanskidea7cd02023-04-26 13:58:17 +020084 c.API.MetricsRegistry = registry
Serge Bazanskicaa12082023-02-16 14:54:04 +010085 api := wrapngo.New(&c.API)
86
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020087 provider, err := c.Provider.New(&c.SSHKey, api)
Serge Bazanskicaa12082023-02-16 14:54:04 +010088 if err != nil {
89 klog.Exitf("%v", err)
90 }
91
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020092 sshSigner, err := c.SSHKey.Signer()
Serge Bazanskicaa12082023-02-16 14:54:04 +010093 if err != nil {
94 klog.Exitf("%v", err)
95 }
96
Tim Windelschmidtd0e39cb2024-09-16 16:14:00 +020097 sshClient := &ssh.DirectClient{
98 AuthMethods: []xssh.AuthMethod{xssh.PublicKeys(sshSigner)},
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020099 // Equinix OS installations always use root.
100 Username: "root",
101 }
102
103 provisioner, err := manager.NewProvisioner(provider, c.ProvisionerConfig)
104 if err != nil {
105 klog.Exitf("%v", err)
106 }
107
108 initializer, err := manager.NewInitializer(provider, sshClient, c.InitializerConfig)
109 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}