-
-
Notifications
You must be signed in to change notification settings - Fork 32
/
daemon.go
102 lines (85 loc) · 2.54 KB
/
daemon.go
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
// Copyright (c) Liam Stanley <[email protected]>. All rights reserved. Use of
// this source code is governed by the MIT license that can be found in
// the LICENSE file.
package main
import (
"context"
"fmt"
"net"
"sync"
"time"
"github.com/apex/log"
"github.com/hashicorp/vault/api"
)
func worker(ctx context.Context, wg *sync.WaitGroup, addr string) {
defer wg.Done()
client := newVault(addr)
var errCount int
var errDelay time.Duration
for {
errDelay = (30 * time.Second) * time.Duration(errCount)
if errDelay > conf.MaxCheckInterval {
errDelay = conf.MaxCheckInterval
}
if errCount > 0 {
logger.WithFields(log.Fields{
"delay": errDelay,
"addr": addr,
}).Info("delaying checks due to errors")
}
select {
case <-ctx.Done():
logger.WithField("addr", addr).Info("closing worker")
return
case <-time.After(conf.CheckInterval + errDelay):
logger.WithField("addr", addr).Info("running checks")
status, err := client.Sys().SealStatus()
if err != nil {
errCount++
nerr := fmt.Errorf("checking seal status: %w", err)
if err, ok := err.(net.Error); ok && err.Timeout() { //nolint:errorlint
// It's a network timeout. If it's the first network timeout,
// don't notify, just try again. This should help with network
// blips.
if errCount == 1 {
logger.WithField("addr", addr).WithError(err).Error("checking seal status")
continue
}
}
notify(nerr)
continue
}
logger.WithFields(log.Fields{"addr": addr, "status": status}).Info("seal status")
if !status.Sealed {
// Not sealed, don't do anything.
errCount = 0
continue
}
// Attempt to loop through the tokens and send the unseal request.
// Each vault-unseal service should have 2 keys. The API allows
// unsealing from multiple locations, so as long as two nodes are
// online, the unseal can occur using two keys from one instance, and
// one key from another.
for i, token := range conf.Tokens {
logger.WithFields(log.Fields{
"addr": addr,
"token": i + 1,
"progress": status.Progress,
"total": status.T,
}).Info("using unseal token")
var resp *api.SealStatusResponse
resp, err = client.Sys().Unseal(token)
if err != nil {
notify(fmt.Errorf("using unseal key %d on %v: %w", i+1, addr, err))
errCount++
continue
}
logger.WithField("addr", addr).Info("token successfully sent")
if !resp.Sealed {
notify(fmt.Errorf("(was sealed) %v now unsealed with tokens", addr))
continue
}
}
}
}
}