Skip to content

Commit f9a44b8

Browse files
authored
kms: extend the Client.Restart API to support cluster-wide restarts (#40)
This commit changes the behavior of `Client.Restart` such that it uses the cluster-wide restart mechanism to restart all nodes within a cluster. The adv. of the new cluster-wide restart is that a client doesn't have to know all cluster nodes to restart all nodes within a cluster. Instead, it can delegate this task to one of the cluster nodes. However, a client can still restart all cluster nodes itself by providing a list of hosts. Signed-off-by: Andreas Auernhammer <github@aead.dev>
1 parent 876634e commit f9a44b8

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

kms/client.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,12 @@ func (c *Client) Ready(ctx context.Context, req *ReadinessRequest) error {
423423
}
424424

425425
// Restart restarts one or multiple KMS servers. If req.Hosts is empty,
426-
// all known servers are restarted.
426+
// all servers that are part of the same cluster are restarted.
427+
//
428+
// There are two ways to restart all nodes within a cluster. When req.Hosts
429+
// is empty, one node restarts all its peers before restarting itself.
430+
// When req.Hosts is a list of all server nodes then each node is restarted
431+
// by the client.
427432
//
428433
// Depending on the OS, a KMS server may not support restarting itself.
429434
//
@@ -435,15 +440,44 @@ func (c *Client) Ready(ctx context.Context, req *ReadinessRequest) error {
435440
// the "Unwrap() []error" interface. Each of these errors are of type HostError.
436441
func (c *Client) Restart(ctx context.Context, req *RestartRequest) error {
437442
const (
438-
Method = http.MethodPost
439-
Path = api.PathRestart
440-
StatusOK = http.StatusOK
443+
Method = http.MethodPost
444+
Path = api.PathRestart
445+
QuerySelf = api.QueryRestartSelf // Used to restart only a single node
446+
StatusOK = http.StatusOK
441447
)
448+
449+
// If no hosts are specified, we call the restart API on an arbitrary
450+
// host and let it restart all its peers. Otherwise, we restart each
451+
// host on its own without doing a cluster-wide restart.
452+
if len(req.Hosts) == 0 {
453+
url, host, err := c.lb.URL(Path)
454+
if err != nil {
455+
return hostError(host, err)
456+
}
457+
req, err := http.NewRequestWithContext(ctx, Method, url, nil)
458+
if err != nil {
459+
return hostError(host, err)
460+
}
461+
req.Header.Set(headers.Accept, headers.ContentTypeAppAny)
462+
463+
resp, err := c.client.Do(req)
464+
if err != nil {
465+
return hostError(host, err)
466+
}
467+
defer resp.Body.Close()
468+
469+
if resp.StatusCode != StatusOK {
470+
return hostError(host, readError(resp))
471+
}
472+
return nil
473+
}
474+
442475
restart := func(ctx context.Context, endpoint string) error {
443476
url, err := url.JoinPath(httpsURL(endpoint), Path)
444477
if err != nil {
445478
return hostError(endpoint, err)
446479
}
480+
url += "?" + QuerySelf // Only restart this particular node
447481

448482
r, err := http.NewRequestWithContext(ctx, Method, url, nil)
449483
if err != nil {
@@ -463,22 +497,18 @@ func (c *Client) Restart(ctx context.Context, req *RestartRequest) error {
463497
return nil
464498
}
465499

466-
endpoints := req.Hosts
467-
if len(endpoints) == 0 {
468-
endpoints = c.lb.Hosts
469-
}
470-
if len(endpoints) == 1 {
471-
return restart(ctx, endpoints[0])
500+
if len(req.Hosts) == 1 {
501+
return restart(ctx, req.Hosts[0])
472502
}
473503

474-
errs := make([]error, len(endpoints))
504+
errs := make([]error, len(req.Hosts))
475505
var wg sync.WaitGroup
476-
for i := range endpoints {
506+
for i, host := range req.Hosts {
477507
wg.Add(1)
478508

479509
go func(i int) {
480510
defer wg.Done()
481-
errs[i] = restart(ctx, endpoints[i])
511+
errs[i] = restart(ctx, host)
482512
}(i)
483513
}
484514
wg.Wait()

kms/internal/api/api.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ const (
2929

3030
// API query parameters supported by KMS servers.
3131
const (
32-
QueryReadyWrite = "write"
32+
QueryReadyWrite = "write"
33+
QueryRestartSelf = "self"
3334
)

0 commit comments

Comments
 (0)