6c22cd587d
* command/agent/host: collect host data, multi platform * nomad/structs/structs: new HostDataRequest/Response * client/agent_endpoint: add RPC endpoint * command/agent/agent_endpoint: add Host * api/agent: add the Host endpoint * nomad/client_agent_endpoint: add Agent Host with forwarding * nomad/client_agent_endpoint: use findClientConn This changes forwardMonitorClient and forwardProfileClient to use findClientConn, which was cribbed from the common parts of those funcs. * command/debug: call agent hosts * command/agent/host: eliminate calling external programs
124 lines
2.3 KiB
Go
124 lines
2.3 KiB
Go
package host
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type HostData struct {
|
|
OS string
|
|
Network []map[string]string
|
|
ResolvConf string
|
|
Hosts string
|
|
Environment map[string]string
|
|
Disk map[string]DiskUsage
|
|
}
|
|
|
|
type DiskUsage struct {
|
|
DiskMB int64
|
|
UsedMB int64
|
|
}
|
|
|
|
func MakeHostData() (*HostData, error) {
|
|
du := make(map[string]DiskUsage)
|
|
for _, path := range mountedPaths() {
|
|
u, err := diskUsage(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
du[path] = u
|
|
}
|
|
|
|
return &HostData{
|
|
OS: uname(),
|
|
Network: network(),
|
|
ResolvConf: resolvConf(),
|
|
Hosts: etcHosts(),
|
|
Environment: environment(),
|
|
Disk: du,
|
|
}, nil
|
|
}
|
|
|
|
// diskUsage calculates the DiskUsage
|
|
func diskUsage(path string) (du DiskUsage, err error) {
|
|
s, err := makeDf(path)
|
|
if err != nil {
|
|
return du, err
|
|
}
|
|
|
|
disk := float64(s.total())
|
|
// Bavail is blocks available to unprivileged users, Bfree includes reserved blocks
|
|
free := float64(s.available())
|
|
used := disk - free
|
|
mb := float64(1048576)
|
|
|
|
disk = disk / mb
|
|
used = used / mb
|
|
|
|
du.DiskMB = int64(disk)
|
|
du.UsedMB = int64(used)
|
|
return du, nil
|
|
}
|
|
|
|
var (
|
|
envRedactSet = makeEnvRedactSet()
|
|
)
|
|
|
|
// environment returns the process environment in a map
|
|
func environment() map[string]string {
|
|
env := make(map[string]string)
|
|
|
|
for _, e := range os.Environ() {
|
|
s := strings.SplitN(e, "=", 2)
|
|
k := s[0]
|
|
up := strings.ToUpper(k)
|
|
v := s[1]
|
|
|
|
_, redact := envRedactSet[k]
|
|
if redact ||
|
|
strings.Contains(up, "TOKEN") ||
|
|
strings.Contains(up, "SECRET") {
|
|
v = "<redacted>"
|
|
}
|
|
|
|
env[k] = v
|
|
}
|
|
return env
|
|
}
|
|
|
|
// makeEnvRedactSet creates a set of well known environment variables that should be
|
|
// redacted in the output
|
|
func makeEnvRedactSet() map[string]struct{} {
|
|
// Duplicated from config.DefaultEnvBlacklist in order to avoid an import cycle
|
|
configDefault := []string{
|
|
"CONSUL_TOKEN",
|
|
"CONSUL_HTTP_TOKEN",
|
|
"VAULT_TOKEN",
|
|
"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN",
|
|
"GOOGLE_APPLICATION_CREDENTIALS",
|
|
}
|
|
|
|
set := make(map[string]struct{})
|
|
for _, e := range configDefault {
|
|
set[e] = struct{}{}
|
|
}
|
|
|
|
return set
|
|
}
|
|
|
|
// slurp returns the file contents as a string, returning an error string
|
|
func slurp(path string) string {
|
|
fh, err := os.Open(path)
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
|
|
bs, err := ioutil.ReadAll(fh)
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
|
|
return string(bs)
|
|
}
|