Skip to content

Commit

Permalink
[haagent] Add haagent component
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreYang committed Nov 18, 2024
1 parent 947fdd4 commit af96a94
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@
/comp/rdnsquerier @DataDog/ndm-integrations
/comp/serializer/compression @DataDog/agent-metrics-logs
/comp/snmpscan @DataDog/ndm-core
/comp/haagent @DataDog/network-device-monitoring @DataDog/remote-config @DataDog/fleet
# END COMPONENTS

# Additional notification to @iglendd about Agent Telemetry changes for optional approval and governance acknowledgement
Expand Down
2 changes: 2 additions & 0 deletions cmd/agent/subcommands/run/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
internalsettings "github.com/DataDog/datadog-agent/cmd/agent/subcommands/run/internal/settings"
agenttelemetry "github.com/DataDog/datadog-agent/comp/core/agenttelemetry/def"
agenttelemetryfx "github.com/DataDog/datadog-agent/comp/core/agenttelemetry/fx"
haagentfx "github.com/DataDog/datadog-agent/comp/haagent/fx"

// checks implemented as components

Expand Down Expand Up @@ -472,6 +473,7 @@ func getSharedFxOption() fx.Option {
agenttelemetryfx.Module(),
networkpath.Bundle(),
remoteagentregistryfx.Module(),
haagentfx.Module(),
)
}

Expand Down
25 changes: 25 additions & 0 deletions comp/haagent/def/component.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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 2024-present Datadog, Inc.

// Package haagent handles states for HA Agent feature.
package haagent

// team: network-device-monitoring

// Component is the component type.
type Component interface {
// Enabled returns true if ha_agent.enabled is set to true
Enabled() bool

// GetGroup returns the value of ha_agent.group
GetGroup() string

// IsLeader returns true if the current Agent is leader
IsLeader() bool

// SetLeader takes the leader agent hostname as input, if it matches the current agent hostname,
// the isLeader state is set to true, otherwise false.
SetLeader(leaderAgentHostname string)
}
23 changes: 23 additions & 0 deletions comp/haagent/fx/fx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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 2024-present Datadog, Inc.

// Package fx provides the fx module for the haagent component
package fx

import (
haagent "github.com/DataDog/datadog-agent/comp/haagent/def"
haagentimpl "github.com/DataDog/datadog-agent/comp/haagent/impl"
"github.com/DataDog/datadog-agent/pkg/util/fxutil"
)

// Module defines the fx options for this component
func Module() fxutil.Module {
return fxutil.Component(
fxutil.ProvideComponentConstructor(
haagentimpl.NewComponent,
),
fxutil.ProvideOptional[haagent.Component](),
)
}
22 changes: 22 additions & 0 deletions comp/haagent/impl/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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 2024-present Datadog, Inc.

package haagentimpl

import (
"github.com/DataDog/datadog-agent/comp/core/config"
)

type haAgentConfigs struct {
enabled bool
group string
}

func newHaAgentConfigs(agentConfig config.Component) *haAgentConfigs {
return &haAgentConfigs{
enabled: agentConfig.GetBool("ha_agent.enabled"),
group: agentConfig.GetString("ha_agent.group"),
}
}
44 changes: 44 additions & 0 deletions comp/haagent/impl/haagent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package haagentimpl

import (
"context"

log "github.com/DataDog/datadog-agent/comp/core/log/def"
"github.com/DataDog/datadog-agent/pkg/util/hostname"
"go.uber.org/atomic"
)

type haAgentImpl struct {
log log.Component
haAgentConfigs *haAgentConfigs
isLeader *atomic.Bool
}

func newHaAgentImpl(log log.Component, haAgentConfigs *haAgentConfigs) *haAgentImpl {
return &haAgentImpl{
log: log,
haAgentConfigs: haAgentConfigs,
isLeader: atomic.NewBool(false),
}
}

func (h *haAgentImpl) Enabled() bool {
return h.haAgentConfigs.enabled
}

func (h *haAgentImpl) GetGroup() string {
return h.haAgentConfigs.group
}

func (h *haAgentImpl) IsLeader() bool {
return h.isLeader.Load()
}

func (h *haAgentImpl) SetLeader(leaderAgentHostname string) {
agentHostname, err := hostname.Get(context.TODO())
if err != nil {
h.log.Warnf("Error getting the hostname: %v", err)
return
}
h.isLeader.Store(agentHostname == leaderAgentHostname)
}
33 changes: 33 additions & 0 deletions comp/haagent/impl/haagent_comp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 2024-present Datadog, Inc.

// Package haagentimpl implements the haagent component interface
package haagentimpl

import (
"github.com/DataDog/datadog-agent/comp/core/config"
log "github.com/DataDog/datadog-agent/comp/core/log/def"
haagent "github.com/DataDog/datadog-agent/comp/haagent/def"
)

// Requires defines the dependencies for the haagent component
type Requires struct {
Logger log.Component
AgentConfig config.Component
}

// Provides defines the output of the haagent component
type Provides struct {
Comp haagent.Component
}

// NewComponent creates a new haagent component
func NewComponent(reqs Requires) (Provides, error) {
haAgentConfigs := newHaAgentConfigs(reqs.AgentConfig)
provides := Provides{
Comp: newHaAgentImpl(reqs.Logger, haAgentConfigs),
}
return provides, nil
}
57 changes: 57 additions & 0 deletions comp/haagent/impl/haagent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package haagentimpl

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_Enabled(t *testing.T) {
tests := []struct {
name string
configs map[string]interface{}
expectedEnabled bool
}{
{
name: "enabled",
configs: map[string]interface{}{
"ha_agent.enabled": true,
},
expectedEnabled: true,
},
{
name: "disabled",
configs: map[string]interface{}{
"ha_agent.enabled": false,
},
expectedEnabled: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
haAgent := newTestHaAgentComponent(t, tt.configs)
assert.Equal(t, tt.expectedEnabled, haAgent.Enabled())
})
}
}

func Test_GetGroup(t *testing.T) {
agentConfigs := map[string]interface{}{
"ha_agent.group": "my-group-01",
}
haAgent := newTestHaAgentComponent(t, agentConfigs)
assert.Equal(t, "my-group-01", haAgent.GetGroup())
}

func Test_IsLeader_SetLeader(t *testing.T) {
agentConfigs := map[string]interface{}{
"hostname": "my-agent-hostname",
}
haAgent := newTestHaAgentComponent(t, agentConfigs)

haAgent.SetLeader("another-agent")
assert.False(t, haAgent.IsLeader())

haAgent.SetLeader("my-agent-hostname")
assert.True(t, haAgent.IsLeader())
}
32 changes: 32 additions & 0 deletions comp/haagent/impl/haagent_testutils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package haagentimpl

import (
"testing"

"github.com/DataDog/datadog-agent/comp/core/config"
logmock "github.com/DataDog/datadog-agent/comp/core/log/mock"
haagent "github.com/DataDog/datadog-agent/comp/haagent/def"
"github.com/DataDog/datadog-agent/pkg/util/fxutil"
"github.com/stretchr/testify/require"
"go.uber.org/fx"
)

func newTestHaAgentComponent(t *testing.T, agentConfigs map[string]interface{}) haagent.Component {
logComponent := logmock.New(t)
agentConfigComponent := fxutil.Test[config.Component](t, fx.Options(
config.MockModule(),
fx.Replace(config.MockParams{Overrides: agentConfigs}),
))

requires := Requires{
Logger: logComponent,
AgentConfig: agentConfigComponent,
}

provides, err := NewComponent(requires)
require.NoError(t, err)

comp := provides.Comp
require.NotNil(t, comp)
return comp
}
45 changes: 45 additions & 0 deletions comp/haagent/mock/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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 2024-present Datadog, Inc.

//go:build test

// Package mock provides a mock for the haagent component
package mock

import (
"testing"

log "github.com/DataDog/datadog-agent/comp/core/log/def"
haagent "github.com/DataDog/datadog-agent/comp/haagent/def"
)

type mock struct {
Logger log.Component
}

func (m *mock) GetGroup() string {
return "mockGroup01"
}

func (m *mock) Enabled() bool {
return true
}

func (m *mock) SetLeader(_ string) {
}

func (m *mock) IsLeader() bool { return false }

// Provides that defines the output of mocked snmpscan component
type Provides struct {
comp haagent.Component
}

// Mock returns a mock for haagent component.
func Mock(_ *testing.T) Provides {
return Provides{
comp: &mock{},
}
}
4 changes: 4 additions & 0 deletions pkg/config/setup/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,10 @@ func InitConfig(config pkgconfigmodel.Setup) {
config.BindEnvAndSetDefault("network_path.collector.reverse_dns_enrichment.timeout", 5000)
bindEnvAndSetLogsConfigKeys(config, "network_path.forwarder.")

// HA Agent
config.BindEnvAndSetDefault("ha_agent.enabled", false)
config.BindEnv("ha_agent.group")

// Kube ApiServer
config.BindEnvAndSetDefault("kubernetes_kubeconfig_path", "")
config.BindEnvAndSetDefault("kubernetes_apiserver_ca_path", "")
Expand Down

0 comments on commit af96a94

Please sign in to comment.