Skip to content

Commit

Permalink
Fix/panic with composable renderer (elastic#823)
Browse files Browse the repository at this point in the history
* Fix a panic with wg passed to the composable object

In the code to retrieve the variables from the configuration files we
need to pass a execution callback, this callback will be called in a
goroutine. This callback can be executed multiple time until the
composable renderer is stopped. There were a problem in the code that
made the callback called multiple time and it made the waitgroup
internal counter to do to a negative values.

This commit change the behavior, it start the composable renderer give
it a callback when the callback receives the variables it will stop the
composable's Run method using the context.

This ensure that the callback will be called a single time and that the
variables are correctly retrieved.

Fixes: elastic#806
  • Loading branch information
ph authored Aug 10, 2022
1 parent 448b218 commit 56787a6
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
- Allow the / char in variable names in eql and transpiler. {issue}715[715] {pull}718[718]
- Fix data duplication for standalone agent on Kubernetes using the default manifest {issue-beats}31512[31512] {pull}742[742]
- Agent updates will clean up unneeded artifacts. {issue}693[693] {issue}694[694] {pull}752[752]
- Fix a panic caused by a race condition when installing the Elastic Agent. {issues}806[806]

==== New features

Expand Down
27 changes: 22 additions & 5 deletions internal/pkg/agent/install/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"runtime"
"strings"
"sync"
"time"

"github.com/kardianos/service"

Expand Down Expand Up @@ -233,19 +234,35 @@ func applyDynamics(ctx context.Context, log *logger.Logger, cfg *config.Config)
inputs, ok := transpiler.Lookup(ast, "inputs")
if ok {
varsArray := make([]*transpiler.Vars, 0)
var wg sync.WaitGroup
wg.Add(1)

// Give some time for the providers to replace the variables
const timeout = 15 * time.Second
var doOnce sync.Once
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()

// The composable system will continuously run, we are only interested in the first run on of the
// renderer to collect the variables we should stop the execution.
varsCallback := func(vv []*transpiler.Vars) {
varsArray = vv
wg.Done()
doOnce.Do(func() {
varsArray = vv
cancel()
})
}

ctrl, err := composable.New(log, cfg)
if err != nil {
return nil, err
}
_ = ctrl.Run(ctx, varsCallback)
wg.Wait()

// Wait for the first callback to retrieve the variables from the providers.
<-ctx.Done()

// Bail out if callback was not executed in time.
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return nil, errors.New("failed to get transpiler vars", err)
}

renderedInputs, err := transpiler.RenderInputs(inputs, varsArray)
if err != nil {
Expand Down

0 comments on commit 56787a6

Please sign in to comment.