blob: da77fe500be64e3b10f508967bc86366e8eeb920 [file] [log] [blame]
Serge Bazanski1f8cad72023-03-20 16:58:10 +01001package cluster
2
3import (
4 "fmt"
5 "net"
6 "os"
7 "path"
8 "sort"
9
10 "github.com/kballard/go-shellquote"
11
12 metroctl "source.monogon.dev/metropolis/cli/metroctl/core"
13 "source.monogon.dev/metropolis/cli/pkg/datafile"
14)
15
16const metroctlRunfile = "metropolis/cli/metroctl/metroctl_/metroctl"
17
18// MetroctlRunfilePath returns the absolute path to the metroctl binary available
19// if the built target depends on //metropolis/cli/metroctl. Otherwise, an error
20// is returned.
21func MetroctlRunfilePath() (string, error) {
22 path, err := datafile.ResolveRunfile(metroctlRunfile)
23 if err != nil {
24 return "", fmt.Errorf("//metropolis/cli/metroctl not found in runfiles, did you include it as a data dependency? error: %w", err)
25 }
26 return path, nil
27}
28
29// ConnectOptions returns metroctl.ConnectOptions that describe connectivity to
30// the launched cluster.
31func (c *Cluster) ConnectOptions() *metroctl.ConnectOptions {
32 // Use all metropolis nodes as endpoints. That's fine, metroctl's resolver will
33 // figure out what to actually use.
34 var endpoints []string
35 for _, n := range c.Nodes {
36 endpoints = append(endpoints, n.ManagementAddress)
37 }
38 sort.Strings(endpoints)
39 return &metroctl.ConnectOptions{
40 ConfigPath: c.metroctlDir,
41 ProxyServer: net.JoinHostPort("127.0.0.1", fmt.Sprintf("%d", c.Ports[SOCKSPort])),
42 Endpoints: endpoints,
43 }
44}
45
46// MetroctlFlags return stringified flags to pass to a metroctl binary to connect
47// to the launched cluster.
48func (c *Cluster) MetroctlFlags() string {
49 return shellquote.Join(c.ConnectOptions().ToFlags()...)
50}
51
52// MakeMetroctlWrapper builds and returns the path to a shell script which calls
53// metroctl (from //metropolis/cli/metroctl, which must be included as a data
54// dependency of the built target) with all the required flags to connect to the
55// launched cluster.
56func (c *Cluster) MakeMetroctlWrapper() (string, error) {
57 mpath, err := MetroctlRunfilePath()
58 if err != nil {
59 return "", err
60 }
61 wpath := path.Join(c.metroctlDir, "metroctl.sh")
62
63 // Don't create wrapper if it already exists.
64 if _, err := os.Stat(wpath); err == nil {
65 return wpath, nil
66 }
67
68 wrapper := fmt.Sprintf("#!/usr/bin/env bash\nexec %s %s \"$@\"", mpath, c.MetroctlFlags())
69 if err := os.WriteFile(wpath, []byte(wrapper), 0555); err != nil {
70 return "", fmt.Errorf("could not write wrapper: %w", err)
71 }
72 return wpath, nil
73}