Skip to content

Commit

Permalink
Agent: Allow custom response properties in the action response (elast…
Browse files Browse the repository at this point in the history
…ic#28575)

* Allow custom response properties in the action response

* ActionApp.Response is optional
  • Loading branch information
aleksmaus authored and wiwen committed Nov 1, 2021
1 parent 125c423 commit 0e2f6ec
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,50 @@ func (h *AppAction) Handle(ctx context.Context, a fleetapi.Action, acker store.F
action.StartedAt = readMapString(res, "started_at", startFormatted)
action.CompletedAt = readMapString(res, "completed_at", endFormatted)
action.Error = readMapString(res, "error", "")
appendActionResponse(action, action.InputType, res)
}

return acker.Ack(ctx, action)
}

var (
none = struct{}{}

// The set of action response fields are not included in the action_response property, because there are already set to top level fields
excludeActionResponseFields = map[string]struct{}{
"started_at": none,
"completed_at": none,
"error": none,
}
)

// appendActionResponse appends the action response property with all the action response values excluding the ones specified in excludeActionResponseFields
// "action_response": {
// "endpoint": {
// "acked": true
// }
// }
func appendActionResponse(action *fleetapi.ActionApp, inputType string, res map[string]interface{}) {
if len(res) == 0 {
return
}

m := make(map[string]interface{}, len(res))

for k, v := range res {
if _, ok := excludeActionResponseFields[k]; !ok {
m[k] = v
}
}

if len(m) > 0 {
mt := make(map[string]interface{}, 1)
mt[inputType] = m

action.Response = mt
}
}

func readMapString(m map[string]interface{}, key string, def string) string {
if m == nil {
return def
Expand Down
9 changes: 5 additions & 4 deletions x-pack/elastic-agent/pkg/fleetapi/ack_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ type AckEvent struct {
Message string `json:"message,omitempty"` // : 'hello2',
Payload string `json:"payload,omitempty"` // : 'payload2',

ActionData json.RawMessage `json:"action_data,omitempty"` // copy of original action data
StartedAt string `json:"started_at,omitempty"` // time action started
CompletedAt string `json:"completed_at,omitempty"` // time action completed
Error string `json:"error,omitempty"` // optional action error
ActionData json.RawMessage `json:"action_data,omitempty"` // copy of original action data
ActionResponse map[string]interface{} `json:"action_response,omitempty"` // custom (per beat) response payload
StartedAt string `json:"started_at,omitempty"` // time action started
CompletedAt string `json:"completed_at,omitempty"` // time action completed
Error string `json:"error,omitempty"` // optional action error
}

// AckRequest consists of multiple actions acked to fleet ui.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func constructEvent(action fleetapi.Action, agentID string) fleetapi.AckEvent {

if a, ok := action.(*fleetapi.ActionApp); ok {
ackev.ActionData = a.Data
ackev.ActionResponse = a.Response
ackev.StartedAt = a.StartedAt
ackev.CompletedAt = a.CompletedAt
ackev.Error = a.Error
Expand Down
18 changes: 10 additions & 8 deletions x-pack/elastic-agent/pkg/fleetapi/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,15 @@ func (a *ActionSettings) String() string {

// ActionApp is the application action request.
type ActionApp struct {
ActionID string `json:"id" mapstructure:"id"`
ActionType string `json:"type" mapstructure:"type"`
InputType string `json:"input_type" mapstructure:"input_type"`
Timeout int64 `json:"timeout,omitempty" mapstructure:"timeout,omitempty"`
Data json.RawMessage `json:"data" mapstructure:"data"`
StartedAt string `json:"started_at,omitempty" mapstructure:"started_at,omitempty"`
CompletedAt string `json:"completed_at,omitempty" mapstructure:"completed_at,omitempty"`
Error string `json:"error,omitempty" mapstructure:"error,omitempty"`
ActionID string `json:"id" mapstructure:"id"`
ActionType string `json:"type" mapstructure:"type"`
InputType string `json:"input_type" mapstructure:"input_type"`
Timeout int64 `json:"timeout,omitempty" mapstructure:"timeout,omitempty"`
Data json.RawMessage `json:"data" mapstructure:"data"`
Response map[string]interface{} `json:"response,omitempty" mapstructure:"response,omitempty"`
StartedAt string `json:"started_at,omitempty" mapstructure:"started_at,omitempty"`
CompletedAt string `json:"completed_at,omitempty" mapstructure:"completed_at,omitempty"`
Error string `json:"error,omitempty" mapstructure:"error,omitempty"`
}

func (a *ActionApp) String() string {
Expand Down Expand Up @@ -287,6 +288,7 @@ func (a *Actions) UnmarshalJSON(data []byte) error {
InputType: response.InputType,
Timeout: response.Timeout,
Data: response.Data,
Response: response.Response,
}
case ActionTypeUnenroll:
action = &ActionUnenroll{
Expand Down

0 comments on commit 0e2f6ec

Please sign in to comment.