Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ha-agent] Reset Agent State on empty RC updates #32397

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions comp/haagent/impl/haagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func (h *haAgentImpl) SetLeader(leaderAgentHostname string) {
}
}

func (h *haAgentImpl) resetAgentState() {
h.state.Store(string(haagent.Unknown))
}

// ShouldRunIntegration return true if the agent integrations should to run.
// When ha-agent is disabled, the agent behave as standalone agent (non HA) and will always run all integrations.
func (h *haAgentImpl) ShouldRunIntegration(integrationName string) bool {
Expand All @@ -78,6 +82,15 @@ func (h *haAgentImpl) ShouldRunIntegration(integrationName string) bool {
func (h *haAgentImpl) onHaAgentUpdate(updates map[string]state.RawConfig, applyStateCallback func(string, state.ApplyStatus)) {
h.log.Debugf("Updates received: count=%d", len(updates))

// New updates arrived, but if the list of updates is empty,
// it means we don't have any updates applying to this agent anymore.
// In this case, reset HA Agent setting to default states.
if len(updates) == 0 {
h.log.Warn("Empty update received. Resetting Agent State to Unknown.")
h.resetAgentState()
return
}

for configPath, rawConfig := range updates {
h.log.Debugf("Received config %s: %s", configPath, string(rawConfig.Config))
haAgentMsg := haAgentConfig{}
Expand Down
59 changes: 53 additions & 6 deletions comp/haagent/impl/haagent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/DataDog/datadog-agent/pkg/remoteconfig/state"
"github.com/DataDog/datadog-agent/pkg/util/fxutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/fx"
)

Expand Down Expand Up @@ -106,25 +107,41 @@ func Test_RCListener(t *testing.T) {
}

func Test_haAgentImpl_onHaAgentUpdate(t *testing.T) {

tests := []struct {
name string
initialState haagent.State
updates map[string]state.RawConfig
expectedApplyID string
expectedApplyStatus state.ApplyStatus
expectedAgentState haagent.State
}{
{
name: "successful update",
name: "successful update with leader matching current agent",
initialState: haagent.Unknown,
updates: map[string]state.RawConfig{
testConfigID: {Config: []byte(`{"group":"testGroup01","leader":"my-agent-hostname"}`)},
},
expectedApplyID: testConfigID,
expectedApplyStatus: state.ApplyStatus{
State: state.ApplyStateAcknowledged,
},
expectedAgentState: haagent.Active,
},
{
name: "successful update with leader NOT matching current agent",
initialState: haagent.Unknown,
updates: map[string]state.RawConfig{
testConfigID: {Config: []byte(`{"group":"testGroup01","leader":"ha-agent1"}`)},
testConfigID: {Config: []byte(`{"group":"testGroup01","leader":"another-agent-hostname"}`)},
},
expectedApplyID: testConfigID,
expectedApplyStatus: state.ApplyStatus{
State: state.ApplyStateAcknowledged,
},
expectedAgentState: haagent.Standby,
},
{
name: "invalid payload",
name: "invalid payload",
initialState: haagent.Unknown,
updates: map[string]state.RawConfig{
testConfigID: {Config: []byte(`invalid-json`)},
},
Expand All @@ -133,17 +150,28 @@ func Test_haAgentImpl_onHaAgentUpdate(t *testing.T) {
State: state.ApplyStateError,
Error: "error unmarshalling payload",
},
expectedAgentState: haagent.Unknown,
},
{
name: "invalid group",
name: "invalid group",
initialState: haagent.Unknown,
updates: map[string]state.RawConfig{
testConfigID: {Config: []byte(`{"group":"invalidGroup","leader":"ha-agent1"}`)},
testConfigID: {Config: []byte(`{"group":"invalidGroup","leader":"another-agent-hostname"}`)},
},
expectedApplyID: testConfigID,
expectedApplyStatus: state.ApplyStatus{
State: state.ApplyStateError,
Error: "group does not match",
},
expectedAgentState: haagent.Unknown,
},
{
name: "empty update",
initialState: haagent.Active,
updates: map[string]state.RawConfig{},
expectedApplyID: "",
expectedApplyStatus: state.ApplyStatus{},
expectedAgentState: haagent.Unknown,
},
}
for _, tt := range tests {
Expand All @@ -160,6 +188,10 @@ func Test_haAgentImpl_onHaAgentUpdate(t *testing.T) {

h := newHaAgentImpl(logmock.New(t), newHaAgentConfigs(agentConfigComponent))

if tt.initialState != "" {
h.state.Store(string(tt.initialState))
}

var applyID string
var applyStatus state.ApplyStatus
applyFunc := func(id string, status state.ApplyStatus) {
Expand All @@ -169,6 +201,7 @@ func Test_haAgentImpl_onHaAgentUpdate(t *testing.T) {
h.onHaAgentUpdate(tt.updates, applyFunc)
assert.Equal(t, tt.expectedApplyID, applyID)
assert.Equal(t, tt.expectedApplyStatus, applyStatus)
assert.Equal(t, tt.expectedAgentState, h.GetState())
})
}
}
Expand Down Expand Up @@ -249,3 +282,17 @@ func Test_haAgentImpl_ShouldRunIntegration(t *testing.T) {
})
}
}

func Test_haAgentImpl_resetAgentState(t *testing.T) {
// GIVEN
haAgent := newTestHaAgentComponent(t, nil)
haAgentComp := haAgent.Comp.(*haAgentImpl)
haAgentComp.state.Store(string(haagent.Active))
require.Equal(t, haagent.Active, haAgentComp.GetState())

// WHEN
haAgentComp.resetAgentState()

// THEN
assert.Equal(t, haagent.Unknown, haAgentComp.GetState())
}
Loading