File: server.go

package info (click to toggle)
hcloud-cli 1.39.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,628 kB
  • sloc: sh: 36; makefile: 7
file content (125 lines) | stat: -rw-r--r-- 2,984 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package hcapi2

import (
	"context"
	"strconv"
	"sync"

	"github.com/hetznercloud/hcloud-go/v2/hcloud"
)

type ServerClient interface {
	ServerClientBase
	ServerName(id int64) string
	Names() []string
	LabelKeys(idOrName string) []string
}

func NewServerClient(client *hcloud.ServerClient) ServerClient {
	return &serverClient{
		ServerClientBase: client,
	}
}

// ServerClient embeds the Hetzner Cloud Server client and provides some
// additional helper functions.
type serverClient struct {
	ServerClientBase

	ServerTypes *hcloud.ServerTypeClient

	srvByID   map[int64]*hcloud.Server
	srvByName map[string]*hcloud.Server

	once sync.Once
	err  error
}

// ServerName obtains the name of the server with id. If the name could not
// be fetched it returns the value id converted to a string.
func (c *serverClient) ServerName(id int64) string {
	if err := c.init(); err != nil {
		return strconv.FormatInt(id, 10)
	}

	srv, ok := c.srvByID[id]
	if !ok || srv.Name == "" {
		return strconv.FormatInt(id, 10)
	}
	return srv.Name
}

// Names obtains a list of available servers. It returns nil if the
// server names could not be fetched or if there are no servers.
func (c *serverClient) Names() []string {
	if err := c.init(); err != nil || len(c.srvByID) == 0 {
		return nil
	}
	names := make([]string, len(c.srvByID))
	i := 0
	for _, srv := range c.srvByID {
		name := srv.Name
		if name == "" {
			name = strconv.FormatInt(srv.ID, 10)
		}
		names[i] = name
		i++
	}
	return names
}

// LabelKeys returns a slice containing the keys of all labels assigned
// to the Server with the passed idOrName.
func (c *serverClient) LabelKeys(idOrName string) []string {
	var srv *hcloud.Server

	if err := c.init(); err != nil || len(c.srvByID) == 0 {
		return nil
	}
	// Try to get server by ID.
	if id, err := strconv.ParseInt(idOrName, 10, 64); err != nil {
		srv = c.srvByID[id]
	}
	// If the above failed idOrName might contain a server name. If srv is not
	// nil at this point and we found something in the map, someone gave their
	// server a name containing the ID of another server.
	if v, ok := c.srvByName[idOrName]; ok && srv == nil {
		srv = v
	}
	if srv == nil || len(srv.Labels) == 0 {
		return nil
	}
	return labelKeys(srv.Labels)
}

// ServerTypeNames returns a slice of all available server types.
func (c *serverClient) ServerTypeNames() []string {
	sts, err := c.ServerTypes.All(context.Background())
	if err != nil || len(sts) == 0 {
		return nil
	}
	names := make([]string, len(sts))
	for i, st := range sts {
		names[i] = st.Name
	}
	return names
}

func (c *serverClient) init() error {
	c.once.Do(func() {
		srvs, err := c.All(context.Background())
		if err != nil {
			c.err = err
		}
		if c.err != nil || len(srvs) == 0 {
			return
		}
		c.srvByID = make(map[int64]*hcloud.Server, len(srvs))
		c.srvByName = make(map[string]*hcloud.Server, len(srvs))
		for _, srv := range srvs {
			c.srvByID[srv.ID] = srv
			c.srvByName[srv.Name] = srv
		}
	})
	return c.err
}