1package hcapi
2
3import (
4	"context"
5	"strconv"
6	"sync"
7
8	"github.com/hetznercloud/hcloud-go/hcloud"
9)
10
11// ServerClient embeds the Hetzner Cloud Server client and provides some
12// additional helper functions.
13type ServerClient struct {
14	*hcloud.ServerClient
15
16	ServerTypes *hcloud.ServerTypeClient
17
18	srvByID   map[int]*hcloud.Server
19	srvByName map[string]*hcloud.Server
20
21	once sync.Once
22	err  error
23}
24
25// ServerName obtains the name of the server with id. If the name could not
26// be fetched it returns the value id converted to a string.
27func (c *ServerClient) ServerName(id int) string {
28	if err := c.init(); err != nil {
29		return strconv.Itoa(id)
30	}
31
32	srv, ok := c.srvByID[id]
33	if !ok || srv.Name == "" {
34		return strconv.Itoa(id)
35	}
36	return srv.Name
37}
38
39// ServerNames obtains a list of available servers. It returns nil if the
40// server names could not be fetched or if there are no servers.
41func (c *ServerClient) ServerNames() []string {
42	if err := c.init(); err != nil || len(c.srvByID) == 0 {
43		return nil
44	}
45	names := make([]string, len(c.srvByID))
46	i := 0
47	for _, srv := range c.srvByID {
48		name := srv.Name
49		if name == "" {
50			name = strconv.Itoa(srv.ID)
51		}
52		names[i] = name
53		i++
54	}
55	return names
56}
57
58// ServerLabelKeys returns a slice containing the keys of all labels assigned
59// to the Server with the passed idOrName.
60func (c *ServerClient) ServerLabelKeys(idOrName string) []string {
61	var srv *hcloud.Server
62
63	if err := c.init(); err != nil || len(c.srvByID) == 0 {
64		return nil
65	}
66	// Try to get server by ID.
67	if id, err := strconv.Atoi(idOrName); err != nil {
68		srv = c.srvByID[id]
69	}
70	// If the above failed idOrName might contain a server name. If srv is not
71	// nil at this point and we found something in the map, someone gave their
72	// server a name containing the ID of another server.
73	if v, ok := c.srvByName[idOrName]; ok && srv == nil {
74		srv = v
75	}
76	if srv == nil || len(srv.Labels) == 0 {
77		return nil
78	}
79	return lkeys(srv.Labels)
80}
81
82// ServerTypeNames returns a slice of all available server types.
83func (c *ServerClient) ServerTypeNames() []string {
84	sts, err := c.ServerTypes.All(context.Background())
85	if err != nil || len(sts) == 0 {
86		return nil
87	}
88	names := make([]string, len(sts))
89	for i, st := range sts {
90		names[i] = st.Name
91	}
92	return names
93}
94
95func (c *ServerClient) init() error {
96	c.once.Do(func() {
97		srvs, err := c.All(context.Background())
98		if err != nil {
99			c.err = err
100		}
101		if c.err != nil || len(srvs) == 0 {
102			return
103		}
104		c.srvByID = make(map[int]*hcloud.Server, len(srvs))
105		c.srvByName = make(map[string]*hcloud.Server, len(srvs))
106		for _, srv := range srvs {
107			c.srvByID[srv.ID] = srv
108			c.srvByName[srv.Name] = srv
109		}
110	})
111	return c.err
112}
113