diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 2361baf73f5..9f35f0dffcd 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -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 diff --git a/internal/pkg/agent/install/uninstall.go b/internal/pkg/agent/install/uninstall.go index 87ff47ae169..598ddaeea8c 100644 --- a/internal/pkg/agent/install/uninstall.go +++ b/internal/pkg/agent/install/uninstall.go @@ -13,6 +13,7 @@ import ( "runtime" "strings" "sync" + "time" "github.com/kardianos/service" @@ -233,11 +234,20 @@ 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) @@ -245,7 +255,14 @@ func applyDynamics(ctx context.Context, log *logger.Logger, cfg *config.Config) 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 {