Skip to content

Commit 9261e9f

Browse files
authored
Add --agent-version flag for flexible Elastic Agent version configuration (#3054)
Added --agent-version flag to stack up, stack update, and test system commands The flag defaults to the stack version if not specified, maintaining backward compatibility Environment variables (ELASTIC_AGENT_IMAGE_REF_OVERRIDE) and configuration file settings (stack.image_ref_overrides.elastic-agent) still take precedence over the flag System tests now support running with different agent versions, making it easier to test compatibility with older agent versions
1 parent 34463f9 commit 9261e9f

28 files changed

+374
-221
lines changed

.buildkite/pipeline.trigger.integration.tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ STACK_COMMAND_TESTS=(
2424
test-stack-command-with-apm-server
2525
test-stack-command-with-basic-subscription
2626
test-stack-command-with-self-monitor
27+
test-stack-command-agent-version-flag
2728
)
2829

2930
for test in "${STACK_COMMAND_TESTS[@]}"; do

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ test-go-ci: $(CODE_COVERAGE_REPORT_FOLDER)
6161
test-stack-command-default:
6262
./scripts/test-stack-command.sh
6363

64+
test-stack-command-agent-version-flag:
65+
AGENT_VERSION_FLAG=9.1.0 ./scripts/test-stack-command.sh
66+
6467
# Oldest minor where fleet is GA.
6568
test-stack-command-oldest:
6669
./scripts/test-stack-command.sh 7.14.2
@@ -87,7 +90,7 @@ test-stack-command-with-self-monitor:
8790
test-stack-command-with-basic-subscription:
8891
ELASTIC_SUBSCRIPTION=basic ./scripts/test-stack-command.sh
8992

90-
test-stack-command: test-stack-command-default test-stack-command-7x test-stack-command-800 test-stack-command-8x test-stack-command-9x test-stack-command-with-apm-server
93+
test-stack-command: test-stack-command-default test-stack-command-agent-version-flag test-stack-command-7x test-stack-command-800 test-stack-command-8x test-stack-command-9x test-stack-command-with-apm-server
9194

9295
test-check-packages: test-check-packages-with-kind test-check-packages-other test-check-packages-parallel test-check-packages-with-custom-agent test-check-packages-benchmarks test-check-packages-false-positives test-check-packages-with-logstash
9396

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ _Context: global_
488488

489489
Use this command to spin up a Docker-based Elastic Stack consisting of Elasticsearch, Kibana, and the Package Registry. By default the latest released version of the stack is spun up but it is possible to specify a different version, including SNAPSHOT versions by appending --version <version>.
490490

491+
Use --agent-version to specify a different version for the Elastic Agent from the stack.
492+
491493
You can run your own custom images for Elasticsearch, Kibana or Elastic Agent, see [this document](./docs/howto/custom_images.md).
492494

493495
Be aware that a common issue while trying to boot up the stack is that your Docker environments settings are too low in terms of memory threshold.
@@ -542,6 +544,8 @@ Use this command to boot up the stack locally.
542544

543545
By default the latest released version of the stack is spun up but it is possible to specify a different version, including SNAPSHOT versions by appending --version <version>.
544546

547+
Use --agent-version to specify a different version for the Elastic Agent from the stack.
548+
545549
You can run your own custom images for Elasticsearch, Kibana or Elastic Agent, see [this document](./docs/howto/custom_images.md).
546550

547551
Be aware that a common issue while trying to boot up the stack is that your Docker environments settings are too low in terms of memory threshold.

cmd/stack.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ var availableServices = map[string]struct{}{
3131

3232
const stackLongDescription = `Use this command to spin up a Docker-based Elastic Stack consisting of Elasticsearch, Kibana, and the Package Registry. By default the latest released version of the stack is spun up but it is possible to specify a different version, including SNAPSHOT versions by appending --version <version>.
3333
34+
Use --agent-version to specify a different version for the Elastic Agent from the stack.
35+
3436
You can run your own custom images for Elasticsearch, Kibana or Elastic Agent, see [this document](./docs/howto/custom_images.md).
3537
3638
Be aware that a common issue while trying to boot up the stack is that your Docker environments settings are too low in terms of memory threshold.
@@ -43,6 +45,8 @@ const stackUpLongDescription = `Use this command to boot up the stack locally.
4345
4446
By default the latest released version of the stack is spun up but it is possible to specify a different version, including SNAPSHOT versions by appending --version <version>.
4547
48+
Use --agent-version to specify a different version for the Elastic Agent from the stack.
49+
4650
You can run your own custom images for Elasticsearch, Kibana or Elastic Agent, see [this document](./docs/howto/custom_images.md).
4751
4852
Be aware that a common issue while trying to boot up the stack is that your Docker environments settings are too low in terms of memory threshold.
@@ -107,6 +111,11 @@ func setupStackCommand() *cobraext.Command {
107111
return cobraext.FlagParsingError(err, cobraext.StackVersionFlagName)
108112
}
109113

114+
agentVersion, err := cmd.Flags().GetString(cobraext.AgentVersionFlagName)
115+
if err != nil {
116+
return cobraext.FlagParsingError(err, cobraext.AgentVersionFlagName)
117+
}
118+
110119
profile, err := cobraext.GetProfileFlag(cmd)
111120
if err != nil {
112121
return err
@@ -128,11 +137,12 @@ func setupStackCommand() *cobraext.Command {
128137

129138
cmd.Printf("Using profile %s.\n", profile.ProfilePath)
130139
err = provider.BootUp(cmd.Context(), stack.Options{
131-
DaemonMode: daemonMode,
132-
StackVersion: stackVersion,
133-
Services: services,
134-
Profile: profile,
135-
Printer: cmd,
140+
DaemonMode: daemonMode,
141+
StackVersion: stackVersion,
142+
OverrideAgentVersion: agentVersion,
143+
Services: services,
144+
Profile: profile,
145+
Printer: cmd,
136146
})
137147
if err != nil {
138148
return fmt.Errorf("booting up the stack failed: %w", err)
@@ -146,6 +156,7 @@ func setupStackCommand() *cobraext.Command {
146156
upCommand.Flags().StringSliceP(cobraext.StackServicesFlagName, "s", nil,
147157
fmt.Sprintf(cobraext.StackServicesFlagDescription, strings.Join(availableServicesAsList(), ",")))
148158
upCommand.Flags().StringP(cobraext.StackVersionFlagName, "", install.DefaultStackVersion, cobraext.StackVersionFlagDescription)
159+
upCommand.Flags().String(cobraext.AgentVersionFlagName, "", cobraext.AgentVersionFlagDescription)
149160
upCommand.Flags().String(cobraext.StackProviderFlagName, "", fmt.Sprintf(cobraext.StackProviderFlagDescription, strings.Join(stack.SupportedProviders, ", ")))
150161
upCommand.Flags().StringSliceP(cobraext.StackUserParameterFlagName, cobraext.StackUserParameterFlagShorthand, nil, cobraext.StackUserParameterDescription)
151162

@@ -201,10 +212,16 @@ func setupStackCommand() *cobraext.Command {
201212
return cobraext.FlagParsingError(err, cobraext.StackVersionFlagName)
202213
}
203214

215+
agentVersion, err := cmd.Flags().GetString(cobraext.AgentVersionFlagName)
216+
if err != nil {
217+
return cobraext.FlagParsingError(err, cobraext.AgentVersionFlagName)
218+
}
219+
204220
err = provider.Update(cmd.Context(), stack.Options{
205-
StackVersion: stackVersion,
206-
Profile: profile,
207-
Printer: cmd,
221+
StackVersion: stackVersion,
222+
Profile: profile,
223+
Printer: cmd,
224+
OverrideAgentVersion: agentVersion,
208225
})
209226
if err != nil {
210227
return fmt.Errorf("failed updating the stack images: %w", err)
@@ -215,6 +232,7 @@ func setupStackCommand() *cobraext.Command {
215232
},
216233
}
217234
updateCommand.Flags().StringP(cobraext.StackVersionFlagName, "", install.DefaultStackVersion, cobraext.StackVersionFlagDescription)
235+
updateCommand.Flags().String(cobraext.AgentVersionFlagName, "", cobraext.AgentVersionFlagDescription)
218236

219237
shellInitCommand := &cobra.Command{
220238
Use: "shellinit",

cmd/testrunner.go

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ func getTestRunnerSystemCommand() *cobra.Command {
420420
cmd.Flags().Bool(cobraext.SetupFlagName, false, cobraext.SetupFlagDescription)
421421
cmd.Flags().Bool(cobraext.TearDownFlagName, false, cobraext.TearDownFlagDescription)
422422
cmd.Flags().Bool(cobraext.NoProvisionFlagName, false, cobraext.NoProvisionFlagDescription)
423+
cmd.Flags().String(cobraext.AgentVersionFlagName, "", cobraext.AgentVersionFlagDescription)
423424

424425
cmd.MarkFlagsMutuallyExclusive(cobraext.SetupFlagName, cobraext.TearDownFlagName, cobraext.NoProvisionFlagName)
425426
cmd.MarkFlagsRequiredTogether(cobraext.ConfigFileFlagName, cobraext.SetupFlagName)
@@ -541,6 +542,11 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error {
541542
return fmt.Errorf("can't create Kibana client: %w", err)
542543
}
543544

545+
agentVersion, err := cmd.Flags().GetString(cobraext.AgentVersionFlagName)
546+
if err != nil {
547+
return cobraext.FlagParsingError(err, cobraext.AgentVersionFlagName)
548+
}
549+
544550
esClient, err := stack.NewElasticsearchClientFromProfile(profile)
545551
if err != nil {
546552
return fmt.Errorf("can't create Elasticsearch client: %w", err)
@@ -567,24 +573,25 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error {
567573
}
568574

569575
runner := system.NewSystemTestRunner(system.SystemTestRunnerOptions{
570-
Profile: profile,
571-
PackageRootPath: packageRootPath,
572-
KibanaClient: kibanaClient,
573-
API: esClient.API,
574-
ESClient: esClient,
575-
ConfigFilePath: configFileFlag,
576-
RunSetup: runSetup,
577-
RunTearDown: runTearDown,
578-
RunTestsOnly: runTestsOnly,
579-
DataStreams: dataStreams,
580-
ServiceVariant: variantFlag,
581-
FailOnMissingTests: failOnMissing,
582-
GenerateTestResult: generateTestResult,
583-
DeferCleanup: deferCleanup,
584-
GlobalTestConfig: globalTestConfig.System,
585-
WithCoverage: testCoverage,
586-
CoverageType: testCoverageFormat,
587-
RepositoryRoot: repositoryRoot,
576+
Profile: profile,
577+
PackageRootPath: packageRootPath,
578+
KibanaClient: kibanaClient,
579+
API: esClient.API,
580+
ESClient: esClient,
581+
ConfigFilePath: configFileFlag,
582+
RunSetup: runSetup,
583+
RunTearDown: runTearDown,
584+
RunTestsOnly: runTestsOnly,
585+
DataStreams: dataStreams,
586+
ServiceVariant: variantFlag,
587+
FailOnMissingTests: failOnMissing,
588+
GenerateTestResult: generateTestResult,
589+
DeferCleanup: deferCleanup,
590+
GlobalTestConfig: globalTestConfig.System,
591+
WithCoverage: testCoverage,
592+
CoverageType: testCoverageFormat,
593+
RepositoryRoot: repositoryRoot,
594+
OverrideAgentVersion: agentVersion,
588595
})
589596

590597
logger.Debugf("Running suite...")

internal/agentdeployer/_static/docker-agent-base.yml.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
{{- $pid_mode := fact "pid_mode" -}}
44
{{- $ports := fact "ports" -}}
55
{{- $dockerfile_hash := fact "dockerfile_hash" -}}
6-
{{- $stack_version := fact "stack_version" }}
6+
{{- $agent_version := fact "agent_version" }}
77
{{- $agent_image := fact "agent_image" }}
88
{{- $enrollment_token := fact "enrollment_token" }}
99
services:
1010
elastic-agent:
1111
hostname: ${AGENT_HOSTNAME}
1212
{{ if ne $dockerfile_hash "" }}
13-
image: "elastic-package-test-elastic-agent:{{ $stack_version }}-{{ $dockerfile_hash }}"
13+
image: "elastic-package-test-elastic-agent:{{ $agent_version }}-{{ $dockerfile_hash }}"
1414
build:
1515
context: .
1616
args:

internal/agentdeployer/agent.go

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ var staticSource = resource.NewSourceFS(static)
4444
// CustomAgentDeployer knows how to deploy a custom elastic-agent defined via
4545
// a Docker Compose file.
4646
type DockerComposeAgentDeployer struct {
47-
profile *profile.Profile
48-
stackVersion string
47+
profile *profile.Profile
48+
stackVersion string
49+
overrideAgentVersion string
4950

5051
policyName string
5152

@@ -59,9 +60,10 @@ type DockerComposeAgentDeployer struct {
5960
}
6061

6162
type DockerComposeAgentDeployerOptions struct {
62-
Profile *profile.Profile
63-
StackVersion string
64-
PolicyName string
63+
Profile *profile.Profile
64+
StackVersion string
65+
OverrideAgentVersion string
66+
PolicyName string
6567

6668
PackageName string
6769
DataStream string
@@ -86,13 +88,14 @@ var _ DeployedAgent = new(dockerComposeDeployedAgent)
8688
// NewCustomAgentDeployer returns a new instance of a deployedCustomAgent.
8789
func NewCustomAgentDeployer(options DockerComposeAgentDeployerOptions) (*DockerComposeAgentDeployer, error) {
8890
return &DockerComposeAgentDeployer{
89-
profile: options.Profile,
90-
stackVersion: options.StackVersion,
91-
packageName: options.PackageName,
92-
dataStream: options.DataStream,
93-
policyName: options.PolicyName,
94-
runTearDown: options.RunTearDown,
95-
runTestsOnly: options.RunTestsOnly,
91+
profile: options.Profile,
92+
stackVersion: options.StackVersion,
93+
overrideAgentVersion: options.OverrideAgentVersion,
94+
packageName: options.PackageName,
95+
dataStream: options.DataStream,
96+
policyName: options.PolicyName,
97+
runTearDown: options.RunTearDown,
98+
runTestsOnly: options.RunTestsOnly,
9699
}, nil
97100
}
98101

@@ -101,7 +104,13 @@ func (d *DockerComposeAgentDeployer) SetUp(ctx context.Context, agentInfo AgentI
101104
logger.Debug("setting up agent using Docker Compose agent deployer")
102105
d.agentRunID = agentInfo.Test.RunID
103106

104-
appConfig, err := install.Configuration(install.OptionWithStackVersion(d.stackVersion))
107+
// default agent version to stack version
108+
agentVersion := d.stackVersion
109+
if d.overrideAgentVersion != "" {
110+
agentVersion = d.overrideAgentVersion
111+
}
112+
113+
appConfig, err := install.Configuration(install.OptionWithStackVersion(d.stackVersion), install.OptionWithAgentVersion(agentVersion))
105114
if err != nil {
106115
return nil, fmt.Errorf("can't read application configuration: %w", err)
107116
}
@@ -281,7 +290,13 @@ func (d *DockerComposeAgentDeployer) installDockerCompose(ctx context.Context, a
281290
stackVersion = version
282291
}
283292

284-
agentImage, err := selectElasticAgentImage(stackVersion, agentInfo.Agent.BaseImage)
293+
agentVersion := stackVersion
294+
// Allow overriding the agent version if specified by the flag
295+
if d.overrideAgentVersion != "" {
296+
agentVersion = d.overrideAgentVersion
297+
}
298+
299+
agentImage, err := selectElasticAgentImage(agentVersion, agentInfo.Agent.BaseImage)
285300
if err != nil {
286301
return "", nil
287302
}
@@ -295,7 +310,7 @@ func (d *DockerComposeAgentDeployer) installDockerCompose(ctx context.Context, a
295310
"pid_mode": agentInfo.Agent.PidMode,
296311
"ports": strings.Join(agentInfo.Agent.Ports, ","),
297312
"dockerfile_hash": hex.EncodeToString(hashDockerfile),
298-
"stack_version": stackVersion,
313+
"agent_version": agentVersion,
299314
"fleet_url": fleetURL,
300315
"kibana_host": stack.DockerInternalHost(kibanaHost),
301316
"elasticsearch_username": config.ElasticsearchUsername,
@@ -321,8 +336,8 @@ func (d *DockerComposeAgentDeployer) installDockerCompose(ctx context.Context, a
321336
return customAgentDir, nil
322337
}
323338

324-
func selectElasticAgentImage(stackVersion, agentBaseImage string) (string, error) {
325-
appConfig, err := install.Configuration(install.OptionWithAgentBaseImage(agentBaseImage), install.OptionWithStackVersion(stackVersion))
339+
func selectElasticAgentImage(agentVersion, agentBaseImage string) (string, error) {
340+
appConfig, err := install.Configuration(install.OptionWithAgentBaseImage(agentBaseImage), install.OptionWithAgentVersion(agentVersion))
326341
if err != nil {
327342
return "", fmt.Errorf("can't read application configuration: %w", err)
328343
}

internal/agentdeployer/factory.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ const (
2424
type FactoryOptions struct {
2525
Profile *profile.Profile
2626

27-
PackageRootPath string
28-
DataStreamRootPath string
29-
DevDeployDir string
30-
Type string
31-
StackVersion string
32-
PolicyName string
27+
PackageRootPath string
28+
DataStreamRootPath string
29+
DevDeployDir string
30+
Type string
31+
StackVersion string
32+
OverrideAgentVersion string
33+
PolicyName string
3334

3435
DeployerName string
3536

@@ -55,13 +56,14 @@ func Factory(options FactoryOptions) (AgentDeployer, error) {
5556
return nil, fmt.Errorf("agent deployer is not supported for type %s", options.Type)
5657
}
5758
opts := DockerComposeAgentDeployerOptions{
58-
Profile: options.Profile,
59-
StackVersion: options.StackVersion,
60-
PackageName: options.PackageName,
61-
PolicyName: options.PolicyName,
62-
DataStream: options.DataStream,
63-
RunTearDown: options.RunTearDown,
64-
RunTestsOnly: options.RunTestsOnly,
59+
Profile: options.Profile,
60+
StackVersion: options.StackVersion,
61+
PackageName: options.PackageName,
62+
PolicyName: options.PolicyName,
63+
DataStream: options.DataStream,
64+
RunTearDown: options.RunTearDown,
65+
RunTestsOnly: options.RunTestsOnly,
66+
OverrideAgentVersion: options.OverrideAgentVersion,
6567
}
6668
return NewCustomAgentDeployer(opts)
6769
case "agent":
@@ -70,13 +72,14 @@ func Factory(options FactoryOptions) (AgentDeployer, error) {
7072
return nil, nil
7173
case "k8s":
7274
opts := KubernetesAgentDeployerOptions{
73-
Profile: options.Profile,
74-
StackVersion: options.StackVersion,
75-
PolicyName: options.PolicyName,
76-
DataStream: options.DataStream,
77-
RunSetup: options.RunSetup,
78-
RunTestsOnly: options.RunTestsOnly,
79-
RunTearDown: options.RunTearDown,
75+
Profile: options.Profile,
76+
StackVersion: options.StackVersion,
77+
OverrideAgentVersion: options.OverrideAgentVersion,
78+
PolicyName: options.PolicyName,
79+
DataStream: options.DataStream,
80+
RunSetup: options.RunSetup,
81+
RunTestsOnly: options.RunTestsOnly,
82+
RunTearDown: options.RunTearDown,
8083
}
8184
return NewKubernetesAgentDeployer(opts)
8285
}

0 commit comments

Comments
 (0)