-
Notifications
You must be signed in to change notification settings - Fork 3
/
facts.go
186 lines (160 loc) · 4.41 KB
/
facts.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright (c) R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0
package machineroom
import (
"context"
"encoding/hex"
"os"
"time"
"github.com/choria-io/go-choria/choria"
"github.com/choria-io/tokens"
"github.com/nats-io/nkeys"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/net"
"github.com/sirupsen/logrus"
)
func generateFacts(ctx context.Context, opts Options, log *logrus.Entry) (any, error) {
data := map[string]map[string]any{
"machine_room": {},
"host": {},
"mem": {},
"swap": {},
"cpu": {},
"disk": {},
"net": {},
}
machineRoomFacts(opts, data, log)
additionalFacts(ctx, opts, data, log)
standardFacts(ctx, opts, data, log)
return data, nil
}
func additionalFacts(ctx context.Context, opts Options, data map[string]map[string]any, log *logrus.Entry) {
if opts.AdditionalFacts == nil {
return
}
extra, err := opts.AdditionalFacts(ctx, opts.roCopy(), log)
if err != nil {
log.Errorf("Could not gather additional facts: %v", err)
} else {
data["machine_room"]["additional_facts"] = extra
}
}
func machineRoomFacts(opts Options, data map[string]map[string]any, log *logrus.Entry) {
var err error
ext := tokens.MapClaims{}
var provToken []byte
if choria.FileExist(opts.ProvisioningJWTFile) {
provToken, err = os.ReadFile(opts.ProvisioningJWTFile)
if err == nil {
t, err := tokens.ParseProvisionTokenUnverified(string(provToken))
if err == nil {
ext = t.Extensions
}
}
}
token := []byte{}
pubKey := []byte{}
pubNKey := ""
if choria.FileExist(opts.ServerJWTFile) {
token, err = os.ReadFile(opts.ServerJWTFile)
if err != nil {
log.Warnf("Could not read server token: %v", err)
}
}
if choria.FileExist(opts.ServerSeedFile) {
pubKey, _, err = choria.Ed25519KeyPairFromSeedFile(opts.ServerSeedFile)
if err != nil {
log.Warnf("Could not read server public key: %v", err)
}
}
if choria.FileExist(opts.NatsNeySeedFile) {
pubNKey, err = loadNkeyPublic(opts)
if err != nil {
log.Warnf("Could not read nkey: %v", err)
}
}
data["machine_room"] = map[string]any{
"timestamp": time.Now(),
"timestamp_seconds": time.Now().Unix(),
"server": map[string]any{
"token": string(token),
"public_key": hex.EncodeToString(pubKey),
"public_nkey": pubNKey,
},
"options": opts,
"provisioning": map[string]any{
"extended_claims": ext,
"token": string(provToken),
},
}
}
func loadNkeyPublic(opts Options) (string, error) {
seed, err := os.ReadFile(opts.NatsNeySeedFile)
if err != nil {
return "", err
}
kp, err := nkeys.FromSeed(seed)
if err != nil {
return "", err
}
return kp.PublicKey()
}
func standardFacts(ctx context.Context, opts Options, data map[string]map[string]any, log *logrus.Entry) {
if opts.NoStandardFacts {
return
}
var err error
if !opts.NoMemoryFacts {
data["mem"]["virtual"], err = mem.VirtualMemoryWithContext(ctx)
if err != nil {
log.Warnf("Could not gather virtual memory information: %v", err)
}
data["swap"]["memory"], err = mem.SwapMemoryWithContext(ctx)
if err != nil {
log.Warnf("Could not gather swap information: %v", err)
}
}
if !opts.NoCPUFacts {
data["cpu"]["info"], err = cpu.InfoWithContext(ctx)
if err != nil {
log.Warnf("Could not gather CPU information: %v", err)
}
}
if !opts.NoDiskFacts {
parts, err := disk.PartitionsWithContext(ctx, false)
if err != nil {
log.Warnf("Could not gather Disk partitions: %v", err)
}
if len(parts) > 0 {
matchedParts := []disk.PartitionStat{}
usages := []*disk.UsageStat{}
for _, part := range parts {
matchedParts = append(matchedParts, part)
u, err := disk.UsageWithContext(ctx, part.Mountpoint)
if err != nil {
log.Warnf("Could not get usage for partition %s: %v", part.Mountpoint, err)
continue
}
usages = append(usages, u)
}
data["disk"]["partitions"] = matchedParts
data["disk"]["usage"] = usages
}
}
if !opts.NoHostFacts {
data["host"]["info"], err = host.InfoWithContext(ctx)
if err != nil {
log.Warnf("Could not gather host information: %v", err)
}
}
if !opts.NoNetworkFacts {
data["net"]["interfaces"], err = net.InterfacesWithContext(ctx)
if err != nil {
log.Warnf("Could not gather network interfaces: %v", err)
}
}
}