Skip to content

Commit

Permalink
[Elastic Agent] Fix AckBatch to do nothing when no actions passed. (e…
Browse files Browse the repository at this point in the history
…lastic#25562)

* Fix AckBatch to do nothing when no actions passed.

* Add changelog.
  • Loading branch information
blakerouse authored May 5, 2021
1 parent 155e7ad commit 3ef9005
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
1 change: 1 addition & 0 deletions x-pack/elastic-agent/CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
- Don't log when upgrade capability doesn't apply {pull}25386[25386]
- Fixed issue when unversioned home is set and invoked watcher failing with ENOENT {issue}25371[25371]
- Fixed Elastic Agent: expecting Dict and received *transpiler.Key for '0' {issue}24453[24453]
- Fix AckBatch to do nothing when no actions passed {pull}25562[25562]

==== New features

Expand Down
5 changes: 5 additions & 0 deletions x-pack/elastic-agent/pkg/fleetapi/acker/fleet/fleet_acker.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func (f *Acker) AckBatch(ctx context.Context, actions []fleetapi.Action) error {
ids = append(ids, action.ID())
}

if len(events) == 0 {
// no events to send (nothing to do)
return nil
}

cmd := fleetapi.NewAckCmd(f.agentInfo, f.client)
req := &fleetapi.AckRequest{
Events: events,
Expand Down
103 changes: 102 additions & 1 deletion x-pack/elastic-agent/pkg/fleetapi/acker/fleet/fleet_acker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/fleetapi"
)

func TestAcker(t *testing.T) {
func TestAcker_AckCommit(t *testing.T) {
type ackRequest struct {
Events []fleetapi.AckEvent `json:"events"`
}
Expand Down Expand Up @@ -69,6 +69,80 @@ func TestAcker(t *testing.T) {
}
}

func TestAcker_AckBatch(t *testing.T) {
type ackRequest struct {
Events []fleetapi.AckEvent `json:"events"`
}

log, _ := logger.New("fleet_acker", false)
client := newTestingClient()
agentInfo := &testAgentInfo{}
acker, err := NewAcker(log, agentInfo, client)
if err != nil {
t.Fatal(err)
}

if acker == nil {
t.Fatal("acker not initialized")
}

testID1 := "ack-test-action-id-1"
testAction1 := &fleetapi.ActionUnknown{ActionID: testID1}
testID2 := "ack-test-action-id-2"
testAction2 := &fleetapi.ActionUnknown{ActionID: testID2}

ch := client.Answer(func(headers http.Header, body io.Reader) (*http.Response, error) {
content, err := ioutil.ReadAll(body)
assert.NoError(t, err)
cr := &ackRequest{}
err = json.Unmarshal(content, &cr)
assert.NoError(t, err)

assert.EqualValues(t, 2, len(cr.Events))
assert.EqualValues(t, testID1, cr.Events[0].ActionID)
assert.EqualValues(t, testID2, cr.Events[1].ActionID)

resp := wrapStrToResp(http.StatusOK, `{ "actions": [] }`)
return resp, nil
})

go func() {
for range ch {
}
}()

if err := acker.AckBatch(context.Background(), []fleetapi.Action{testAction1, testAction2}); err != nil {
t.Fatal(err)
}
if err := acker.Commit(context.Background()); err != nil {
t.Fatal(err)
}
}

func TestAcker_AckBatch_Empty(t *testing.T) {
log, _ := logger.New("fleet_acker", false)
client := newNotCalledClient()
agentInfo := &testAgentInfo{}
acker, err := NewAcker(log, agentInfo, client)
if err != nil {
t.Fatal(err)
}

if acker == nil {
t.Fatal("acker not initialized")
}

if err := acker.AckBatch(context.Background(), []fleetapi.Action{}); err != nil {
t.Fatal(err)
}
if err := acker.Commit(context.Background()); err != nil {
t.Fatal(err)
}
if client.called {
t.Fatal("client should not have been used")
}
}

type clientCallbackFunc func(headers http.Header, body io.Reader) (*http.Response, error)

type testingClient struct {
Expand Down Expand Up @@ -122,3 +196,30 @@ func wrapStrToResp(code int, body string) *http.Response {
Header: make(http.Header),
}
}

type notCalledClient struct {
sync.Mutex
called bool
}

func (t *notCalledClient) Send(
_ context.Context,
method string,
path string,
params url.Values,
headers http.Header,
body io.Reader,
) (*http.Response, error) {
t.Lock()
defer t.Unlock()
t.called = true
return nil, fmt.Errorf("should not have been called")
}

func (t *notCalledClient) URI() string {
return "http://localhost"
}

func newNotCalledClient() *notCalledClient {
return &notCalledClient{}
}

0 comments on commit 3ef9005

Please sign in to comment.