-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathhostsysteminfo.go
More file actions
175 lines (151 loc) · 5.71 KB
/
hostsysteminfo.go
File metadata and controls
175 lines (151 loc) · 5.71 KB
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
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
// Package hostsysteminfoimpl implements a component to generate the 'host_system_info' metadata payload for inventory.
package hostsysteminfoimpl
import (
"context"
"encoding/json"
"net/http"
"runtime"
"time"
api "github.com/DataDog/datadog-agent/comp/api/api/def"
"github.com/DataDog/datadog-agent/comp/core/config"
flaretypes "github.com/DataDog/datadog-agent/comp/core/flare/types"
"github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface"
ipc "github.com/DataDog/datadog-agent/comp/core/ipc/def"
log "github.com/DataDog/datadog-agent/comp/core/log/def"
hostsysteminfo "github.com/DataDog/datadog-agent/comp/metadata/hostsysteminfo/def"
"github.com/DataDog/datadog-agent/comp/metadata/internal/util"
"github.com/DataDog/datadog-agent/comp/metadata/runner/runnerimpl"
"github.com/DataDog/datadog-agent/pkg/inventory/systeminfo"
"github.com/DataDog/datadog-agent/pkg/serializer"
"github.com/DataDog/datadog-agent/pkg/serializer/marshaler"
httputils "github.com/DataDog/datadog-agent/pkg/util/http"
"github.com/DataDog/datadog-agent/pkg/util/uuid"
)
const flareFileName = "hostsysteminfo.json"
type hostSystemInfoMetadata struct {
Manufacturer string `json:"manufacturer"`
ModelNumber string `json:"model_number"`
SerialNumber string `json:"serial_number"`
ModelName string `json:"model_name"`
ChassisType string `json:"chassis_type"`
Identifier string `json:"identifier"`
}
type hostSystemInfo struct {
util.InventoryPayload
log log.Component
conf config.Component
hostname string
data *hostSystemInfoMetadata
}
type Payload struct {
Hostname string `json:"hostname"`
Timestamp int64 `json:"timestamp"`
Metadata *hostSystemInfoMetadata `json:"host_system_info_metadata"`
UUID string `json:"uuid"`
}
func (p *Payload) MarshalJSON() ([]byte, error) {
type PayloadAlias Payload
return json.Marshal((*PayloadAlias)(p))
}
type Requires struct {
Log log.Component
Config config.Component
Serializer serializer.MetricSerializer
Hostname hostnameinterface.Component
IPCClient ipc.HTTPClient
}
type Provides struct {
Comp hostsysteminfo.Component
Provider runnerimpl.Provider
FlareProvider flaretypes.Provider
Endpoint api.AgentEndpointProvider
}
func NewSystemInfoProvider(deps Requires) Provides {
hname, _ := deps.Hostname.Get(context.Background())
hh := &hostSystemInfo{
log: deps.Log,
conf: deps.Config,
hostname: hname,
data: &hostSystemInfoMetadata{},
}
hh.InventoryPayload = util.CreateInventoryPayload(deps.Config, deps.Log, deps.Serializer, hh.getPayload, flareFileName)
// Override default intervals for system info metadata
// System info changes infrequently, so check less often
hh.InventoryPayload.MinInterval = 1 * time.Hour
hh.InventoryPayload.MaxInterval = 1 * time.Hour
// Only enable system info metadata collection for end user device infrastructure mode on Windows and Darwin
infraMode := deps.Config.GetString("infrastructure_mode")
isEndUserDevice := infraMode == "end_user_device"
isSupportedOS := runtime.GOOS == "windows" || runtime.GOOS == "darwin"
hh.InventoryPayload.Enabled = hh.InventoryPayload.Enabled && isEndUserDevice && isSupportedOS
var provider runnerimpl.Provider
if hh.InventoryPayload.Enabled {
provider = hh.MetadataProvider()
deps.Log.Info("System info metadata collection enabled for end user device mode")
} else {
if !isSupportedOS {
deps.Log.Debugf("System info metadata collection disabled: only supported on Windows and macOS (current OS: %s)", runtime.GOOS)
} else {
deps.Log.Debugf("System info metadata collection disabled: infrastructure_mode is '%s' (requires 'end_user_device')", infraMode)
}
}
return Provides{
Comp: hh,
Provider: provider,
FlareProvider: hh.FlareProvider(),
Endpoint: api.NewAgentEndpointProvider(hh.writePayloadAsJSON, "/metadata/host-system-info", "GET"),
}
}
func (hh *hostSystemInfo) fillData() error {
// System info collection is only supported on Windows and Darwin
if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
hh.log.Debugf("System information collection not supported on %s", runtime.GOOS)
hh.data = &hostSystemInfoMetadata{}
return nil
}
sysInfo, err := systeminfo.Collect()
if err != nil {
hh.log.Errorf("Failed to collect system information: %v", err)
hh.data = &hostSystemInfoMetadata{}
return err
}
// Handle case where collection returns nil data
if sysInfo == nil {
hh.log.Debug("System information collection returned no data")
hh.data = &hostSystemInfoMetadata{}
return nil
}
hh.data.Manufacturer = sysInfo.Manufacturer
hh.data.ModelNumber = sysInfo.ModelNumber
hh.data.SerialNumber = sysInfo.SerialNumber
hh.data.ModelName = sysInfo.ModelName
hh.data.ChassisType = sysInfo.ChassisType
hh.data.Identifier = sysInfo.Identifier
return nil
}
func (hh *hostSystemInfo) writePayloadAsJSON(w http.ResponseWriter, _ *http.Request) {
// GetAsJSON calls getPayload which already scrub the data
scrubbed, err := hh.GetAsJSON()
if err != nil {
httputils.SetJSONError(w, err, 500)
return
}
w.Write(scrubbed)
}
func (hh *hostSystemInfo) getPayload() marshaler.JSONMarshaler {
// Try to collect system info data
if err := hh.fillData(); err != nil {
hh.log.Debugf("Skipping system info metadata payload due to collection failure: %v", err)
return nil
}
return &Payload{
Hostname: hh.hostname,
Timestamp: time.Now().UnixNano(),
Metadata: hh.data,
UUID: uuid.GetUUID(),
}
}