Skip to content

Commit 4fa6bb6

Browse files
authored
send package.version to components (#4024)
The agent now includes AgentInfo alongside the connection information during component startup. It also stores the BuildHash sent by the components as part of the ComponentVersionInfo during check-in. To facilitate testing, an info.Agent interface has been created to abstract the implementation of info.AgentInfo. This abstraction allows for the creation of mocks, enabling testing scenarios where using `info.NewAgentInfo` is impractical. This is because `info.NewAgentInfo` relies on the agent vault, which, on Mac systems, is the system's keychain. Accessing the keychain requires root permissions, which are not available during testing.
1 parent 8dcab21 commit 4fa6bb6

29 files changed

+418
-97
lines changed

internal/pkg/agent/application/actions/handlers/handler_action_policy_change.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const (
3737
// PolicyChangeHandler is a handler for POLICY_CHANGE action.
3838
type PolicyChangeHandler struct {
3939
log *logger.Logger
40-
agentInfo *info.AgentInfo
40+
agentInfo info.Agent
4141
config *configuration.Configuration
4242
store storage.Store
4343
ch chan coordinator.ConfigChange
@@ -52,7 +52,7 @@ type PolicyChangeHandler struct {
5252
// NewPolicyChangeHandler creates a new PolicyChange handler.
5353
func NewPolicyChangeHandler(
5454
log *logger.Logger,
55-
agentInfo *info.AgentInfo,
55+
agentInfo info.Agent,
5656
config *configuration.Configuration,
5757
store storage.Store,
5858
ch chan coordinator.ConfigChange,
@@ -264,7 +264,7 @@ func clientEqual(k1 remote.Config, k2 remote.Config) bool {
264264
return true
265265
}
266266

267-
func fleetToReader(agentInfo *info.AgentInfo, cfg *configuration.Configuration) (io.Reader, error) {
267+
func fleetToReader(agentInfo info.Agent, cfg *configuration.Configuration) (io.Reader, error) {
268268
configToStore := map[string]interface{}{
269269
"fleet": cfg.Fleet,
270270
"agent": map[string]interface{}{

internal/pkg/agent/application/actions/handlers/handler_action_policy_change_test.go

+2-7
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ func TestPolicyChange(t *testing.T) {
3434
log, _ := logger.New("", false)
3535
ack := noopacker.New()
3636

37-
ctx, cancel := context.WithCancel(context.Background())
38-
defer cancel()
39-
40-
agentInfo, _ := info.NewAgentInfo(ctx, true)
37+
agentInfo := &info.AgentInfo{}
4138
nullStore := &storage.NullStore{}
4239

4340
t.Run("Receive a config change and successfully emits a raw configuration", func(t *testing.T) {
@@ -63,10 +60,8 @@ func TestPolicyChange(t *testing.T) {
6360

6461
func TestPolicyAcked(t *testing.T) {
6562
log, _ := logger.New("", false)
66-
ctx, cancel := context.WithCancel(context.Background())
67-
defer cancel()
6863

69-
agentInfo, _ := info.NewAgentInfo(ctx, true)
64+
agentInfo := &info.AgentInfo{}
7065
nullStore := &storage.NullStore{}
7166

7267
t.Run("Config change should ACK", func(t *testing.T) {

internal/pkg/agent/application/actions/handlers/handler_action_settings.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ import (
2020
// Settings handles settings change coming from fleet and updates log level.
2121
type Settings struct {
2222
log *logger.Logger
23-
agentInfo *info.AgentInfo
23+
agentInfo info.Agent
2424
coord *coordinator.Coordinator
2525
}
2626

2727
// NewSettings creates a new Settings handler.
2828
func NewSettings(
2929
log *logger.Logger,
30-
agentInfo *info.AgentInfo,
30+
agentInfo info.Agent,
3131
coord *coordinator.Coordinator,
3232
) *Settings {
3333
return &Settings{

internal/pkg/agent/application/actions/handlers/handler_action_upgrade_test.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ func TestUpgradeHandler(t *testing.T) {
6363
defer cancel()
6464

6565
log, _ := logger.New("", false)
66-
agentInfo, _ := info.NewAgentInfo(ctx, true)
66+
67+
agentInfo := &info.AgentInfo{}
6768
msgChan := make(chan string)
6869

6970
// Create and start the coordinator
@@ -95,7 +96,8 @@ func TestUpgradeHandlerSameVersion(t *testing.T) {
9596
defer cancel()
9697

9798
log, _ := logger.New("", false)
98-
agentInfo, _ := info.NewAgentInfo(ctx, true)
99+
100+
agentInfo := &info.AgentInfo{}
99101
msgChan := make(chan string)
100102

101103
// Create and start the Coordinator
@@ -129,7 +131,8 @@ func TestUpgradeHandlerNewVersion(t *testing.T) {
129131
defer cancel()
130132

131133
log, _ := logger.New("", false)
132-
agentInfo, _ := info.NewAgentInfo(ctx, true)
134+
135+
agentInfo := &info.AgentInfo{}
133136
msgChan := make(chan string)
134137

135138
// Create and start the Coordinator

internal/pkg/agent/application/application.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func New(
4141
log *logger.Logger,
4242
baseLogger *logger.Logger,
4343
logLevel logp.Level,
44-
agentInfo *info.AgentInfo,
44+
agentInfo info.Agent,
4545
reexec coordinator.ReExecManager,
4646
tracer *apm.Tracer,
4747
testingMode bool,

internal/pkg/agent/application/coordinator/coordinator.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ type configReloader interface {
173173
// All configuration changes, update variables, and upgrade actions are managed and controlled by the coordinator.
174174
type Coordinator struct {
175175
logger *logger.Logger
176-
agentInfo *info.AgentInfo
176+
agentInfo info.Agent
177177
isManaged bool
178178

179179
cfg *configuration.Configuration
@@ -322,7 +322,7 @@ type UpdateComponentChange struct {
322322
}
323323

324324
// New creates a new coordinator.
325-
func New(logger *logger.Logger, cfg *configuration.Configuration, logLevel logp.Level, agentInfo *info.AgentInfo, specs component.RuntimeSpecs, reexecMgr ReExecManager, upgradeMgr UpgradeManager, runtimeMgr RuntimeManager, configMgr ConfigManager, varsMgr VarsManager, caps capabilities.Capabilities, monitorMgr MonitorManager, isManaged bool, modifiers ...ComponentsModifier) *Coordinator {
325+
func New(logger *logger.Logger, cfg *configuration.Configuration, logLevel logp.Level, agentInfo info.Agent, specs component.RuntimeSpecs, reexecMgr ReExecManager, upgradeMgr UpgradeManager, runtimeMgr RuntimeManager, configMgr ConfigManager, varsMgr VarsManager, caps capabilities.Capabilities, monitorMgr MonitorManager, isManaged bool, modifiers ...ComponentsModifier) *Coordinator {
326326
var fleetState cproto.State
327327
var fleetMessage string
328328
if !isManaged {

internal/pkg/agent/application/coordinator/diagnostics_test.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,9 @@ components:
409409
assert.YAMLEq(t, expected, string(result), "components-actual diagnostic returned unexpected value")
410410
}
411411

412+
// TestDiagnosticState creates a coordinator with a test state and verify that
413+
// the state diagnostic reports it.
412414
func TestDiagnosticState(t *testing.T) {
413-
// Create a coordinator with a test state and verify that the state
414-
// diagnostic reports it
415-
416415
now := time.Now().UTC()
417416
state := State{
418417
State: agentclient.Starting,
@@ -427,7 +426,8 @@ func TestDiagnosticState(t *testing.T) {
427426
State: client.UnitStateDegraded,
428427
Message: "degraded message",
429428
VersionInfo: runtime.ComponentVersionInfo{
430-
Name: "version name",
429+
Name: "version name",
430+
BuildHash: "a-build-hash",
431431
},
432432
},
433433
},
@@ -461,6 +461,7 @@ components:
461461
units: {}
462462
version_info:
463463
name: "version name"
464+
build_hash: "a-build-hash"
464465
upgrade_details:
465466
target_version: 8.12.0
466467
state: UPG_DOWNLOADING
@@ -503,7 +504,8 @@ func TestDiagnosticStateForAPM(t *testing.T) {
503504
State: client.UnitStateDegraded,
504505
Message: "degraded message",
505506
VersionInfo: runtime.ComponentVersionInfo{
506-
Name: "version name",
507+
Name: "version name",
508+
BuildHash: "a-build-hash",
507509
},
508510
Component: &proto.Component{
509511
ApmConfig: &proto.APMConfig{
@@ -540,6 +542,7 @@ components:
540542
units: {}
541543
version_info:
542544
name: "version name"
545+
build_hash: "a-build-hash"
543546
component:
544547
apmconfig:
545548
elastic:

internal/pkg/agent/application/fleet_server_bootstrap.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func FleetServerComponentModifier(serverCfg *configuration.FleetServerConfig) co
102102

103103
// InjectFleetConfigComponentModifier The modifier that injects the fleet configuration for the components
104104
// that need to be able to connect to fleet server.
105-
func InjectFleetConfigComponentModifier(fleetCfg *configuration.FleetAgentConfig, agentInfo *info.AgentInfo) coordinator.ComponentsModifier {
105+
func InjectFleetConfigComponentModifier(fleetCfg *configuration.FleetAgentConfig, agentInfo info.Agent) coordinator.ComponentsModifier {
106106
return func(comps []component.Component, cfg map[string]interface{}) ([]component.Component, error) {
107107
hostsStr := fleetCfg.Client.GetHosts()
108108
fleetHosts := make([]interface{}, 0, len(hostsStr))

internal/pkg/agent/application/info/agent_info.go

+23
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,29 @@ import (
1111
"github.com/elastic/elastic-agent/pkg/core/logger"
1212
)
1313

14+
type Agent interface {
15+
// AgentID returns an agent identifier.
16+
AgentID() string
17+
18+
// Headers returns custom headers used to communicate with elasticsearch.
19+
Headers() map[string]string
20+
21+
// LogLevel retrieves a log level.
22+
LogLevel() string
23+
24+
// ReloadID reloads agent info ID from configuration file.
25+
ReloadID(ctx context.Context) error
26+
27+
// SetLogLevel updates log level of agent.
28+
SetLogLevel(ctx context.Context, level string) error
29+
30+
// Snapshot returns if this version is a snapshot.
31+
Snapshot() bool
32+
33+
// Version returns the version for this Agent.
34+
Version() string
35+
}
36+
1437
// AgentInfo is a collection of information about agent.
1538
type AgentInfo struct {
1639
agentID string

internal/pkg/agent/application/managed_mode.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const dispatchFlushInterval = time.Minute * 5
4141

4242
type managedConfigManager struct {
4343
log *logger.Logger
44-
agentInfo *info.AgentInfo
44+
agentInfo info.Agent
4545
cfg *configuration.Configuration
4646
client *remote.Client
4747
store storage.Store
@@ -60,7 +60,7 @@ type managedConfigManager struct {
6060
func newManagedConfigManager(
6161
ctx context.Context,
6262
log *logger.Logger,
63-
agentInfo *info.AgentInfo,
63+
agentInfo info.Agent,
6464
cfg *configuration.Configuration,
6565
storeSaver storage.Store,
6666
runtime *runtime.Manager,

internal/pkg/agent/application/monitoring/v1_monitor.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ type BeatsMonitor struct {
6969
enabled bool // feature flag disabling whole v1 monitoring story
7070
config *monitoringConfig
7171
operatingSystem string
72-
agentInfo *info.AgentInfo
72+
agentInfo info.Agent
7373
}
7474

7575
type monitoringConfig struct {
7676
C *monitoringCfg.MonitoringConfig `config:"agent.monitoring"`
7777
}
7878

7979
// New creates a new BeatsMonitor instance.
80-
func New(enabled bool, operatingSystem string, cfg *monitoringCfg.MonitoringConfig, agentInfo *info.AgentInfo) *BeatsMonitor {
80+
func New(enabled bool, operatingSystem string, cfg *monitoringCfg.MonitoringConfig, agentInfo info.Agent) *BeatsMonitor {
8181
return &BeatsMonitor{
8282
enabled: enabled,
8383
config: &monitoringConfig{
@@ -914,7 +914,7 @@ func (b *BeatsMonitor) injectMetricsInput(cfg map[string]interface{}, componentI
914914
return nil
915915
}
916916

917-
func createProcessorsForJSONInput(name string, compID, monitoringNamespace string, agentInfo *info.AgentInfo) []interface{} {
917+
func createProcessorsForJSONInput(name string, compID, monitoringNamespace string, agentInfo info.Agent) []interface{} {
918918
return []interface{}{
919919
map[string]interface{}{
920920
"add_fields": map[string]interface{}{

internal/pkg/agent/application/upgrade/upgrade.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var ErrSameVersion = errors.New("upgrade did not occur because its the same vers
5353
type Upgrader struct {
5454
log *logger.Logger
5555
settings *artifact.Config
56-
agentInfo *info.AgentInfo
56+
agentInfo info.Agent
5757
upgradeable bool
5858
fleetServerURI string
5959
markerWatcher MarkerWatcher
@@ -67,7 +67,7 @@ func IsUpgradeable() bool {
6767
}
6868

6969
// NewUpgrader creates an upgrader which is capable of performing upgrade operation
70-
func NewUpgrader(log *logger.Logger, settings *artifact.Config, agentInfo *info.AgentInfo) (*Upgrader, error) {
70+
func NewUpgrader(log *logger.Logger, settings *artifact.Config, agentInfo info.Agent) (*Upgrader, error) {
7171
return &Upgrader{
7272
log: log,
7373
settings: settings,

internal/pkg/agent/storage/encrypted_disk_store.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func (d *EncryptedDiskStore) Load() (rc io.ReadCloser, err error) {
164164
fd, err := os.OpenFile(d.target, os.O_RDONLY, perms)
165165
if err != nil {
166166
if errors.Is(err, os.ErrNotExist) {
167-
// If file doesn't exists, return empty reader closer
167+
// If file doesn't exist, return empty reader closer
168168
return io.NopCloser(bytes.NewReader([]byte{})), nil
169169
}
170170
return nil, errors.New(err,

internal/pkg/agent/vault/vault_notdarwin.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,25 @@ func New(ctx context.Context, path string, opts ...OptionFunc) (v *Vault, err er
9696
func (v *Vault) Set(ctx context.Context, key string, data []byte) (err error) {
9797
enc, err := v.encrypt(data)
9898
if err != nil {
99-
return err
99+
return fmt.Errorf("vault Set: could not encrypt key: %w", err)
100100
}
101101

102102
err = v.tryLock(ctx)
103103
if err != nil {
104-
return err
104+
return fmt.Errorf("vault Set: could acquire lock: %w", err)
105105
}
106106
defer func() {
107107
err = v.unlockAndJoinErrors(err)
108+
if err != nil {
109+
err = fmt.Errorf("vault Set: unlockAndJoinErrors failed: %w", err)
110+
}
108111
}()
109112

110-
return writeFile(v.filepathFromKey(key), enc)
113+
err = writeFile(v.filepathFromKey(key), enc)
114+
if err != nil {
115+
return fmt.Errorf("vaukt: could not write key to file: %w", err)
116+
}
117+
return nil
111118
}
112119

113120
// Get retrieves the key from the vault store

pkg/component/runtime/command.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ func (c *commandRuntime) stop(ctx context.Context) error {
420420

421421
func (c *commandRuntime) startWatcher(info *process.Info, comm Communicator) {
422422
go func() {
423-
err := comm.WriteConnInfo(info.Stdin)
423+
err := comm.WriteStartUpInfo(info.Stdin)
424424
if err != nil {
425425
_, _ = c.logErr.Write([]byte(fmt.Sprintf("Failed: failed to provide connection information to spawned pid '%d': %s", info.PID, err)))
426426
// kill instantly

pkg/component/runtime/conn_info_server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func newConnInfoServer(log *logger.Logger, comm Communicator, port int) (*connIn
4646
break
4747
}
4848
log.Debugf("client connected, sending connection info")
49-
err = comm.WriteConnInfo(conn)
49+
err = comm.WriteStartUpInfo(conn)
5050
if err != nil {
5151
if !errors.Is(err, io.EOF) {
5252
log.Errorf("failed write conn info: %v", err)

pkg/component/runtime/conn_info_server_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func newMockCommunicator() *mockCommunicator {
4444
}
4545
}
4646

47-
func (c *mockCommunicator) WriteConnInfo(w io.Writer, services ...client.Service) error {
47+
func (c *mockCommunicator) WriteStartUpInfo(w io.Writer, services ...client.Service) error {
4848
infoBytes, err := protobuf.Marshal(c.startupInfo)
4949
if err != nil {
5050
return fmt.Errorf("failed to marshal connection information: %w", err)

pkg/component/runtime/manager.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ type Manager struct {
9797
ca *authority.CertificateAuthority
9898
listenAddr string
9999
listenPort int
100-
agentInfo *info.AgentInfo
100+
agentInfo info.Agent
101101
tracer *apm.Tracer
102102
monitor MonitoringManager
103103
grpcConfig *configuration.GRPCConfig
@@ -150,7 +150,7 @@ func NewManager(
150150
logger,
151151
baseLogger *logger.Logger,
152152
listenAddr string,
153-
agentInfo *info.AgentInfo,
153+
agentInfo info.Agent,
154154
tracer *apm.Tracer,
155155
monitor MonitoringManager,
156156
grpcConfig *configuration.GRPCConfig,
@@ -159,6 +159,10 @@ func NewManager(
159159
if err != nil {
160160
return nil, err
161161
}
162+
163+
if agentInfo == nil {
164+
return nil, errors.New("agentInfo cannot be nil")
165+
}
162166
m := &Manager{
163167
logger: logger,
164168
baseLogger: baseLogger,

0 commit comments

Comments
 (0)