Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions x-pack/agent/pkg/agent/application/agent_id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package application

import (
"fmt"

"github.com/gofrs/uuid"
)

func generateAgentID() (string, error) {
id, err := uuid.NewV4()
if err != nil {
return "", fmt.Errorf("error while generating UUID for agent: %v", err)
}

return id.String(), nil
}
27 changes: 27 additions & 0 deletions x-pack/agent/pkg/agent/application/agent_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package application

type AgentInfo struct {
Comment thread
michalpristas marked this conversation as resolved.
Comment thread
michalpristas marked this conversation as resolved.
agentID string
}

// NewAgentInfo creates a new agent information.
// Generates new unique identifier for agent.
func NewAgentInfo() (*AgentInfo, error) {
agentID, err := generateAgentID()
if err != nil {
return nil, err
}

return &AgentInfo{
agentID: agentID,
}, nil
}

// AgentID returns an agent identifier.
func (i *AgentInfo) AgentID() string {
return i.agentID
}
6 changes: 1 addition & 5 deletions x-pack/agent/pkg/agent/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type Application interface {
Start() error
Stop() error
AgentInfo() *AgentInfo
}

// New creates a new Agent and bootstrap the required subsystem.
Expand Down Expand Up @@ -60,8 +61,3 @@ func createApplication(
return nil, ErrInvalidMgmtMode
}
}

func getAgentID() string {
// TODO: implement correct way of acquiring agent ID
return "default"
}
29 changes: 21 additions & 8 deletions x-pack/agent/pkg/agent/application/local_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ var ErrNoConfiguration = errors.New("no configuration found")
// Local represents a standalone agents, that will read his configuration directly from disk.
// Some part of the configuration can be reloaded.
type Local struct {
log *logger.Logger
source source
log *logger.Logger
source source
agentInfo *AgentInfo
}

type source interface {
Expand All @@ -53,7 +54,10 @@ func newLocal(
}
}

agentID := getAgentID()
agentInfo, err := NewAgentInfo()
if err != nil {
return nil, err
}

c := localConfigDefault()
if err := config.Unpack(c); err != nil {
Expand All @@ -62,7 +66,12 @@ func newLocal(

logR := logreporter.NewReporter(log, c.Reporting)

reporter := reporting.NewReporter(log, agentID, logR)
localApplication := &Local{
log: log,
agentInfo: agentInfo,
}

reporter := reporting.NewReporter(log, localApplication.agentInfo, logR)

router, err := newRouter(log, streamFactory(config, nil, reporter))
if err != nil {
Expand All @@ -81,10 +90,9 @@ func newLocal(
cfgSource = newPeriodic(log, c.Reload.Period, discover, emit)
}

return &Local{
log: log,
source: cfgSource,
}, nil
localApplication.source = cfgSource

return localApplication, nil
}

// Start starts a local agent.
Expand All @@ -104,6 +112,11 @@ func (l *Local) Stop() error {
return l.source.Stop()
}

// AgentInfo retrieves agent information.
func (l *Local) AgentInfo() *AgentInfo {
return l.agentInfo
}

func discoverer(patterns ...string) discoverFunc {
var p []string
for _, newP := range patterns {
Expand Down
41 changes: 29 additions & 12 deletions x-pack/agent/pkg/agent/application/managed_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"net/http"
"net/url"
"sync"

"github.com/pkg/errors"

Expand All @@ -34,17 +35,22 @@ type apiClient interface {
// Managed application, when the application is run in managed mode, most of the configuration are
// coming from the Fleet App.
type Managed struct {
log *logger.Logger
Config FleetAgentConfig
api apiClient
log *logger.Logger
Config FleetAgentConfig
api apiClient
agentInfo *AgentInfo
infoLock sync.Mutex
}

func newManaged(
log *logger.Logger,
rawConfig *config.Config,
) (*Managed, error) {

agentID := getAgentID()
agentInfo, err := NewAgentInfo()
if agentInfo != nil {
return nil, err
}

path := fleetAgentConfigPath()

Expand All @@ -70,7 +76,13 @@ func newManaged(
return nil, errors.Wrap(err, "fail to create API client")
}

reporter, err := createFleetReporters(log, cfg, agentID, client)
managedApplication := &Managed{
log: log,
api: client,
agentInfo: agentInfo,
}

reporter, err := createFleetReporters(log, cfg, managedApplication.agentInfo, client)
if err != nil {
return nil, errors.Wrap(err, "fail to create reporters")
}
Expand All @@ -81,10 +93,7 @@ func newManaged(
return nil, errors.Wrap(err, "fail to initialize pipeline router")
}

return &Managed{
log: log,
api: client,
}, nil
return managedApplication, nil
}

// Start starts a managed agent.
Expand All @@ -99,19 +108,27 @@ func (m *Managed) Stop() error {
return nil
}

// AgentInfo retrieves agent information.
func (m *Managed) AgentInfo() *AgentInfo {
m.infoLock.Lock()
defer m.infoLock.Unlock()

return m.agentInfo
}

func createFleetReporters(
log *logger.Logger,
cfg *FleetAgentConfig,
agentID string,
agentInfo *AgentInfo,
client apiClient,
) (reporter, error) {

logR := logreporter.NewReporter(log, cfg.Reporting.Log)

fleetR, err := fleetreporter.NewReporter(agentID, log, cfg.Reporting.Fleet, client)
fleetR, err := fleetreporter.NewReporter(agentInfo, log, cfg.Reporting.Fleet, client)
if err != nil {
return nil, err
}

return reporting.NewReporter(log, agentID, logR, fleetR), nil
return reporting.NewReporter(log, agentInfo, logR, fleetR), nil
}
20 changes: 13 additions & 7 deletions x-pack/agent/pkg/fleetapi/checkin_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/pkg/errors"
)

const checkingPath = "/api/fleet/agents/%s/checkin"

// CheckinRequest consists of multiple events reported to fleet ui.
type CheckinRequest struct {
Events []SerializableEvent `json:"events"`
Expand Down Expand Up @@ -53,17 +55,20 @@ func (e *CheckinResponse) Validate() error {

// CheckinCmd is a fleet API command.
type CheckinCmd struct {
client clienter
checkinPath string
client clienter
info agentInfo
}

type agentInfo interface {
AgentID() string
}

// NewCheckinCmd creates a new api command.
func NewCheckinCmd(agentID string, client clienter) *CheckinCmd {
const p = "/api/fleet/agents/%s/checkin"
func NewCheckinCmd(info agentInfo, client clienter) *CheckinCmd {

return &CheckinCmd{
client: client,
checkinPath: fmt.Sprintf(p, agentID),
client: client,
info: info,
}
}

Expand All @@ -78,7 +83,8 @@ func (e *CheckinCmd) Execute(r *CheckinRequest) (*CheckinResponse, error) {
return nil, errors.Wrap(err, "fail to encode the checkin request")
}

resp, err := e.client.Send("POST", e.checkinPath, nil, nil, bytes.NewBuffer(b))
cp := fmt.Sprintf(checkingPath, e.info.AgentID())
resp, err := e.client.Send("POST", cp, nil, nil, bytes.NewBuffer(b))
if err != nil {
return nil, errors.Wrap(err, "fail to checkin to fleet")
}
Expand Down
26 changes: 15 additions & 11 deletions x-pack/agent/pkg/fleetapi/checkin_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ import (
"github.com/stretchr/testify/require"
)

type info struct{}

func (*info) AgentID() string { return "id" }

func TestCheckin(t *testing.T) {
const agentID = "bob"
const withAPIKey = "secret"
agentInfo := &info{}

t.Run("Send back status of actions", withServerWithAuthClient(
func(t *testing.T) *http.ServeMux {
Expand All @@ -27,7 +31,7 @@ func TestCheckin(t *testing.T) {
}
`
mux := http.NewServeMux()
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentID)
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentInfo.AgentID())
mux.HandleFunc(path, authHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)

Expand Down Expand Up @@ -72,7 +76,7 @@ func TestCheckin(t *testing.T) {
},
}

cmd := NewCheckinCmd(agentID, client)
cmd := NewCheckinCmd(&info{}, client)

request := CheckinRequest{
Events: []SerializableEvent{
Expand All @@ -95,15 +99,15 @@ Something went wrong
}
`
mux := http.NewServeMux()
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentID)
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentInfo.AgentID())
mux.HandleFunc(path, authHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, raw)
}, withAPIKey))
return mux
}, withAPIKey,
func(t *testing.T, client clienter) {
cmd := NewCheckinCmd(agentID, client)
cmd := NewCheckinCmd(agentInfo, client)

request := CheckinRequest{}

Expand Down Expand Up @@ -146,15 +150,15 @@ Something went wrong
}
`
mux := http.NewServeMux()
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentID)
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentInfo.AgentID())
mux.HandleFunc(path, authHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, raw)
}, withAPIKey))
return mux
}, withAPIKey,
func(t *testing.T, client clienter) {
cmd := NewCheckinCmd(agentID, client)
cmd := NewCheckinCmd(agentInfo, client)

request := CheckinRequest{}

Expand Down Expand Up @@ -208,15 +212,15 @@ Something went wrong
}
`
mux := http.NewServeMux()
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentID)
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentInfo.AgentID())
mux.HandleFunc(path, authHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, raw)
}, withAPIKey))
return mux
}, withAPIKey,
func(t *testing.T, client clienter) {
cmd := NewCheckinCmd(agentID, client)
cmd := NewCheckinCmd(agentInfo, client)

request := CheckinRequest{}

Expand Down Expand Up @@ -246,15 +250,15 @@ Something went wrong
}
`
mux := http.NewServeMux()
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentID)
path := fmt.Sprintf("/api/fleet/agents/%s/checkin", agentInfo.AgentID())
mux.HandleFunc(path, authHandler(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, raw)
}, withAPIKey))
return mux
}, withAPIKey,
func(t *testing.T, client clienter) {
cmd := NewCheckinCmd(agentID, client)
cmd := NewCheckinCmd(agentInfo, client)

request := CheckinRequest{}

Expand Down
8 changes: 6 additions & 2 deletions x-pack/agent/pkg/reporter/fleet/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ type Reporter struct {
closeOnce sync.Once
}

type agentInfo interface {
AgentID() string
}

// NewReporter creates a new fleet reporter.
func NewReporter(agentID string, l *logger.Logger, c *ManagementConfig, client remoteClient) (*Reporter, error) {
checkinClient := fleetapi.NewCheckinCmd(agentID, client)
func NewReporter(agentInfo agentInfo, l *logger.Logger, c *ManagementConfig, client remoteClient) (*Reporter, error) {
checkinClient := fleetapi.NewCheckinCmd(agentInfo, client)

frequency := time.Duration(c.ReportingCheckFrequency) * time.Second
r := &Reporter{
Expand Down
Loading