Merge branch '12260-system-health'
[arvados.git] / sdk / go / arvados / config.go
1 package arvados
2
3 import (
4         "fmt"
5         "os"
6
7         "git.curoverse.com/arvados.git/sdk/go/config"
8 )
9
10 const DefaultConfigFile = "/etc/arvados/config.yml"
11
12 type Config struct {
13         Clusters map[string]Cluster
14 }
15
16 // GetConfig returns the current system config, loading it from
17 // configFile if needed.
18 func GetConfig(configFile string) (*Config, error) {
19         var cfg Config
20         err := config.LoadFile(&cfg, configFile)
21         return &cfg, err
22 }
23
24 // GetCluster returns the cluster ID and config for the given
25 // cluster, or the default/only configured cluster if clusterID is "".
26 func (sc *Config) GetCluster(clusterID string) (*Cluster, error) {
27         if clusterID == "" {
28                 if len(sc.Clusters) == 0 {
29                         return nil, fmt.Errorf("no clusters configured")
30                 } else if len(sc.Clusters) > 1 {
31                         return nil, fmt.Errorf("multiple clusters configured, cannot choose")
32                 } else {
33                         for id, cc := range sc.Clusters {
34                                 cc.ClusterID = id
35                                 return &cc, nil
36                         }
37                 }
38         }
39         if cc, ok := sc.Clusters[clusterID]; !ok {
40                 return nil, fmt.Errorf("cluster %q is not configured", clusterID)
41         } else {
42                 cc.ClusterID = clusterID
43                 return &cc, nil
44         }
45 }
46
47 type Cluster struct {
48         ClusterID       string `json:"-"`
49         ManagementToken string
50         SystemNodes     map[string]SystemNode
51 }
52
53 // GetThisSystemNode returns a SystemNode for the node we're running
54 // on right now.
55 func (cc *Cluster) GetThisSystemNode() (*SystemNode, error) {
56         hostname, err := os.Hostname()
57         if err != nil {
58                 return nil, err
59         }
60         return cc.GetSystemNode(hostname)
61 }
62
63 // GetSystemNode returns a SystemNode for the given hostname. An error
64 // is returned if the appropriate configuration can't be determined
65 // (e.g., this does not appear to be a system node).
66 func (cc *Cluster) GetSystemNode(node string) (*SystemNode, error) {
67         if cfg, ok := cc.SystemNodes[node]; ok {
68                 return &cfg, nil
69         }
70         // If node is not listed, but "*" gives a default system node
71         // config, use the default config.
72         if cfg, ok := cc.SystemNodes["*"]; ok {
73                 return &cfg, nil
74         }
75         return nil, fmt.Errorf("config does not provision host %q as a system node", node)
76 }
77
78 type SystemNode struct {
79         Health      SystemServiceInstance `json:"arvados-health"`
80         Keepproxy   SystemServiceInstance `json:"keepproxy"`
81         Keepstore   SystemServiceInstance `json:"keepstore"`
82         Keepweb     SystemServiceInstance `json:"keep-web"`
83         Nodemanager SystemServiceInstance `json:"arvados-node-manager"`
84         RailsAPI    SystemServiceInstance `json:"arvados-api-server"`
85         Websocket   SystemServiceInstance `json:"arvados-ws"`
86         Workbench   SystemServiceInstance `json:"arvados-workbench"`
87 }
88
89 // ServicePorts returns the configured listening address (or "" if
90 // disabled) for each service on the node.
91 func (sn *SystemNode) ServicePorts() map[string]string {
92         return map[string]string{
93                 "arvados-api-server":   sn.RailsAPI.Listen,
94                 "arvados-node-manager": sn.Nodemanager.Listen,
95                 "arvados-workbench":    sn.Workbench.Listen,
96                 "arvados-ws":           sn.Websocket.Listen,
97                 "keep-web":             sn.Keepweb.Listen,
98                 "keepproxy":            sn.Keepproxy.Listen,
99                 "keepstore":            sn.Keepstore.Listen,
100         }
101 }
102
103 type SystemServiceInstance struct {
104         Listen string
105 }