Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func upCommandAction(cmd *cobra.Command, args []string) error {
DataStreamRootPath: dataStreamPath,
Variant: variantFlag,
StackVersion: stackVersion.Version(),
AgentVersion: stackVersion.Version(),
Copy link
Contributor Author

@teresaromero teresaromero Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The service cmd needs an agent version definition? or the default (same as stack) is used?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess deployers that manage their own agents could use this version, though not sure if we need a different setting for stack and agent version 🤔

In any case this is internal by now, right? No change for users.

})
if err != nil {
return fmt.Errorf("up command failed: %w", err)
Expand Down
14 changes: 14 additions & 0 deletions cmd/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ func setupStackCommand() *cobraext.Command {
return cobraext.FlagParsingError(err, cobraext.StackVersionFlagName)
}

agentVersion, err := cmd.Flags().GetString(cobraext.AgentVersionFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.AgentVersionFlagName)
}

profile, err := cobraext.GetProfileFlag(cmd)
if err != nil {
return err
Expand All @@ -130,6 +135,7 @@ func setupStackCommand() *cobraext.Command {
err = provider.BootUp(cmd.Context(), stack.Options{
DaemonMode: daemonMode,
StackVersion: stackVersion,
AgentVersion: agentVersion,
Services: services,
Profile: profile,
Printer: cmd,
Expand All @@ -146,6 +152,7 @@ func setupStackCommand() *cobraext.Command {
upCommand.Flags().StringSliceP(cobraext.StackServicesFlagName, "s", nil,
fmt.Sprintf(cobraext.StackServicesFlagDescription, strings.Join(availableServicesAsList(), ",")))
upCommand.Flags().StringP(cobraext.StackVersionFlagName, "", install.DefaultStackVersion, cobraext.StackVersionFlagDescription)
upCommand.Flags().StringP(cobraext.AgentVersionFlagName, "", install.DefaultStackVersion, cobraext.AgentVersionFlagDescription)
upCommand.Flags().String(cobraext.StackProviderFlagName, "", fmt.Sprintf(cobraext.StackProviderFlagDescription, strings.Join(stack.SupportedProviders, ", ")))
upCommand.Flags().StringSliceP(cobraext.StackUserParameterFlagName, cobraext.StackUserParameterFlagShorthand, nil, cobraext.StackUserParameterDescription)

Expand Down Expand Up @@ -201,10 +208,16 @@ func setupStackCommand() *cobraext.Command {
return cobraext.FlagParsingError(err, cobraext.StackVersionFlagName)
}

agentVersion, err := cmd.Flags().GetString(cobraext.AgentVersionFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.AgentVersionFlagName)
}

err = provider.Update(cmd.Context(), stack.Options{
StackVersion: stackVersion,
Profile: profile,
Printer: cmd,
AgentVersion: agentVersion,
})
if err != nil {
return fmt.Errorf("failed updating the stack images: %w", err)
Expand All @@ -215,6 +228,7 @@ func setupStackCommand() *cobraext.Command {
},
}
updateCommand.Flags().StringP(cobraext.StackVersionFlagName, "", install.DefaultStackVersion, cobraext.StackVersionFlagDescription)
updateCommand.Flags().StringP(cobraext.AgentVersionFlagName, "", install.DefaultStackVersion, cobraext.AgentVersionFlagDescription)

shellInitCommand := &cobra.Command{
Use: "shellinit",
Expand Down
7 changes: 7 additions & 0 deletions cmd/testrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ func getTestRunnerSystemCommand() *cobra.Command {
cmd.Flags().Bool(cobraext.SetupFlagName, false, cobraext.SetupFlagDescription)
cmd.Flags().Bool(cobraext.TearDownFlagName, false, cobraext.TearDownFlagDescription)
cmd.Flags().Bool(cobraext.NoProvisionFlagName, false, cobraext.NoProvisionFlagDescription)
cmd.Flags().StringP(cobraext.AgentVersionFlagName, "", install.DefaultStackVersion, cobraext.AgentVersionFlagDescription)

cmd.MarkFlagsMutuallyExclusive(cobraext.SetupFlagName, cobraext.TearDownFlagName, cobraext.NoProvisionFlagName)
cmd.MarkFlagsRequiredTogether(cobraext.ConfigFileFlagName, cobraext.SetupFlagName)
Expand Down Expand Up @@ -451,6 +452,11 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error {
return cobraext.FlagParsingError(err, cobraext.FailOnMissingFlagName)
}

agentVersion, err := cmd.Flags().GetString(cobraext.AgentVersionFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.AgentVersionFlagName)
}

generateTestResult, err := cmd.Flags().GetBool(cobraext.GenerateTestResultFlagName)
if err != nil {
return cobraext.FlagParsingError(err, cobraext.GenerateTestResultFlagName)
Expand Down Expand Up @@ -585,6 +591,7 @@ func testRunnerSystemCommandAction(cmd *cobra.Command, args []string) error {
WithCoverage: testCoverage,
CoverageType: testCoverageFormat,
RepositoryRoot: repositoryRoot,
AgentVersion: agentVersion,
})

logger.Debugf("Running suite...")
Expand Down
11 changes: 7 additions & 4 deletions internal/agentdeployer/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var staticSource = resource.NewSourceFS(static)
type DockerComposeAgentDeployer struct {
profile *profile.Profile
stackVersion string
agentVersion string

policyName string

Expand All @@ -61,6 +62,7 @@ type DockerComposeAgentDeployer struct {
type DockerComposeAgentDeployerOptions struct {
Profile *profile.Profile
StackVersion string
AgentVersion string
PolicyName string

PackageName string
Expand Down Expand Up @@ -88,6 +90,7 @@ func NewCustomAgentDeployer(options DockerComposeAgentDeployerOptions) (*DockerC
return &DockerComposeAgentDeployer{
profile: options.Profile,
stackVersion: options.StackVersion,
agentVersion: options.AgentVersion,
packageName: options.PackageName,
dataStream: options.DataStream,
policyName: options.PolicyName,
Expand All @@ -101,7 +104,7 @@ func (d *DockerComposeAgentDeployer) SetUp(ctx context.Context, agentInfo AgentI
logger.Debug("setting up agent using Docker Compose agent deployer")
d.agentRunID = agentInfo.Test.RunID

appConfig, err := install.Configuration(install.OptionWithStackVersion(d.stackVersion))
appConfig, err := install.Configuration(install.OptionWithStackVersion(d.stackVersion), install.OptionWithAgentVersion(d.agentVersion))
if err != nil {
return nil, fmt.Errorf("can't read application configuration: %w", err)
}
Expand Down Expand Up @@ -281,7 +284,7 @@ func (d *DockerComposeAgentDeployer) installDockerCompose(ctx context.Context, a
stackVersion = version
}

agentImage, err := selectElasticAgentImage(stackVersion, agentInfo.Agent.BaseImage)
agentImage, err := selectElasticAgentImage(d.agentVersion, agentInfo.Agent.BaseImage)
if err != nil {
return "", nil
}
Expand Down Expand Up @@ -321,8 +324,8 @@ func (d *DockerComposeAgentDeployer) installDockerCompose(ctx context.Context, a
return customAgentDir, nil
}

func selectElasticAgentImage(stackVersion, agentBaseImage string) (string, error) {
appConfig, err := install.Configuration(install.OptionWithAgentBaseImage(agentBaseImage), install.OptionWithStackVersion(stackVersion))
func selectElasticAgentImage(agentVersion, agentBaseImage string) (string, error) {
appConfig, err := install.Configuration(install.OptionWithAgentBaseImage(agentBaseImage), install.OptionWithAgentVersion(agentVersion))
if err != nil {
return "", fmt.Errorf("can't read application configuration: %w", err)
}
Expand Down
3 changes: 3 additions & 0 deletions internal/agentdeployer/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type FactoryOptions struct {
DevDeployDir string
Type string
StackVersion string
AgentVersion string
PolicyName string

DeployerName string
Expand Down Expand Up @@ -62,6 +63,7 @@ func Factory(options FactoryOptions) (AgentDeployer, error) {
DataStream: options.DataStream,
RunTearDown: options.RunTearDown,
RunTestsOnly: options.RunTestsOnly,
AgentVersion: options.AgentVersion,
}
return NewCustomAgentDeployer(opts)
case "agent":
Expand All @@ -72,6 +74,7 @@ func Factory(options FactoryOptions) (AgentDeployer, error) {
opts := KubernetesAgentDeployerOptions{
Profile: options.Profile,
StackVersion: options.StackVersion,
AgentVersion: options.AgentVersion,
PolicyName: options.PolicyName,
DataStream: options.DataStream,
RunSetup: options.RunSetup,
Expand Down
29 changes: 17 additions & 12 deletions internal/agentdeployer/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
type KubernetesAgentDeployer struct {
profile *profile.Profile
stackVersion string
agentVersion string
policyName string
dataStream string

Expand All @@ -40,6 +41,7 @@ type KubernetesAgentDeployer struct {
type KubernetesAgentDeployerOptions struct {
Profile *profile.Profile
StackVersion string
AgentVersion string
PolicyName string
DataStream string

Expand All @@ -53,11 +55,12 @@ type kubernetesDeployedAgent struct {
profile *profile.Profile
stackVersion string

agentName string
agentName string
agentVersion string
}

func (s kubernetesDeployedAgent) TearDown(ctx context.Context) error {
elasticAgentManagedYaml, err := getElasticAgentYAML(ctx, s.profile, s.agentInfo, s.stackVersion, s.agentName)
elasticAgentManagedYaml, err := getElasticAgentYAML(ctx, s.profile, s.agentInfo, s.stackVersion, s.agentName, s.agentVersion)
if err != nil {
return fmt.Errorf("can't retrieve Kubernetes file for Elastic Agent: %w", err)
}
Expand Down Expand Up @@ -92,6 +95,7 @@ func NewKubernetesAgentDeployer(opts KubernetesAgentDeployerOptions) (*Kubernete
return &KubernetesAgentDeployer{
profile: opts.Profile,
stackVersion: opts.StackVersion,
agentVersion: opts.AgentVersion,
policyName: opts.PolicyName,
dataStream: opts.DataStream,
runSetup: opts.RunSetup,
Expand Down Expand Up @@ -123,7 +127,7 @@ func (ksd *KubernetesAgentDeployer) SetUp(ctx context.Context, agentInfo AgentIn
if ksd.runTearDown || ksd.runTestsOnly {
logger.Debug("Skip install Elastic Agent in cluster")
} else {
err = installElasticAgentInCluster(ctx, ksd.profile, agentInfo, ksd.stackVersion, agentName)
err = installElasticAgentInCluster(ctx, ksd.profile, agentInfo, ksd.stackVersion, agentName, ksd.agentVersion)
if err != nil {
return nil, fmt.Errorf("can't install Elastic-Agent in the Kubernetes cluster: %w", err)
}
Expand All @@ -139,6 +143,7 @@ func (ksd *KubernetesAgentDeployer) SetUp(ctx context.Context, agentInfo AgentIn
profile: ksd.profile,
stackVersion: ksd.stackVersion,
agentName: agentName,
agentVersion: ksd.agentVersion,
}, nil
}

Expand All @@ -155,10 +160,10 @@ func (ksd *KubernetesAgentDeployer) agentName() string {

var _ AgentDeployer = new(KubernetesAgentDeployer)

func installElasticAgentInCluster(ctx context.Context, profile *profile.Profile, agentInfo AgentInfo, stackVersion, agentName string) error {
func installElasticAgentInCluster(ctx context.Context, profile *profile.Profile, agentInfo AgentInfo, stackVersion, agentName, agentVersion string) error {
logger.Debug("install Elastic Agent in the Kubernetes cluster")

elasticAgentManagedYaml, err := getElasticAgentYAML(ctx, profile, agentInfo, stackVersion, agentName)
elasticAgentManagedYaml, err := getElasticAgentYAML(ctx, profile, agentInfo, stackVersion, agentName, agentVersion)
if err != nil {
return fmt.Errorf("can't retrieve Kubernetes file for Elastic Agent: %w", err)
}
Expand All @@ -176,8 +181,8 @@ func installElasticAgentInCluster(ctx context.Context, profile *profile.Profile,
//go:embed _static/elastic-agent-managed.yaml.tmpl
var elasticAgentManagedYamlTmpl string

func getElasticAgentYAML(ctx context.Context, profile *profile.Profile, agentInfo AgentInfo, stackVersion, agentName string) ([]byte, error) {
logger.Debugf("Prepare YAML definition for Elastic Agent running in stack v%s", stackVersion)
func getElasticAgentYAML(ctx context.Context, profile *profile.Profile, agentInfo AgentInfo, stackVersion, agentName, agentVersion string) ([]byte, error) {
logger.Debugf("Prepare YAML definition for Elastic Agent (v%s) running in stack v%s", agentVersion, stackVersion)
config, err := stack.LoadConfig(profile)
if err != nil {
return nil, fmt.Errorf("failed to load config from profile: %w", err)
Expand All @@ -191,7 +196,7 @@ func getElasticAgentYAML(ctx context.Context, profile *profile.Profile, agentInf
fleetURL = url
}
if version, ok := config.Parameters[stack.ParamServerlessLocalStackVersion]; ok {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case, we get the value from the config, we need to add a new param to define agent-version at the config file, isnt it? the flag value will be overriden by the config file one

cc @mrodm @jsoriano

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the flag value will be overriden by the config file one

I think it should be the other way around, if a user is setting a flag in the command line, this value should be prioritized over the one in config files.

stackVersion = version
agentVersion = version
}

enrollmentToken := ""
Expand All @@ -207,7 +212,7 @@ func getElasticAgentYAML(ctx context.Context, profile *profile.Profile, agentInf
}
}

appConfig, err := install.Configuration(install.OptionWithStackVersion(stackVersion))
appConfig, err := install.Configuration(install.OptionWithAgentVersion(agentVersion))
if err != nil {
return nil, fmt.Errorf("can't read application configuration: %w", err)
}
Expand All @@ -228,7 +233,7 @@ func getElasticAgentYAML(ctx context.Context, profile *profile.Profile, agentInf
"enrollmentToken": enrollmentToken,
"caCertPem": caCert,
"elasticAgentImage": appConfig.StackImageRefs().ElasticAgent,
"elasticAgentTokenPolicyName": getTokenPolicyName(stackVersion, agentInfo.Policy.Name),
"elasticAgentTokenPolicyName": getTokenPolicyName(agentVersion, agentInfo.Policy.Name),
"agentName": agentName,
})
if err != nil {
Expand All @@ -255,8 +260,8 @@ func readCACertBase64(profile *profile.Profile) (string, error) {
// getTokenPolicyName function returns the policy name for the >= 8.x Elastic stacks. The agent's policy
// is predefined in the Kibana configuration file. The logic is not present in older stacks and it uses
// the default policy in Kibana (empty string).
func getTokenPolicyName(stackVersion, policyName string) string {
if strings.HasPrefix(stackVersion, "7.") {
func getTokenPolicyName(agentVersion, policyName string) string {
if strings.HasPrefix(agentVersion, "7.") {
return ""
}
return policyName
Expand Down
1 change: 1 addition & 0 deletions internal/benchrunner/runners/system/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ func (r *runner) setupService(ctx context.Context) (servicedeployer.DeployedServ
Profile: r.options.Profile,
Type: servicedeployer.TypeBench,
StackVersion: stackVersion.Version(),
AgentVersion: stackVersion.Version(),
DeployIndependentAgent: false,
}
serviceDeployer, err := servicedeployer.Factory(opts)
Expand Down
3 changes: 3 additions & 0 deletions internal/cobraext/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,7 @@ const (
ZipPackageFilePathFlagName = "zip"
ZipPackageFilePathFlagShorthand = "z"
ZipPackageFilePathFlagDescription = "path to the zip package file (*.zip)"

AgentVersionFlagName = "agent-version"
AgentVersionFlagDescription = "Elastic Agent version to be used in the stack"
)
20 changes: 15 additions & 5 deletions internal/install/application_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type ApplicationConfiguration struct {
c configFile
agentBaseImage string
stackVersion string
agentVersion string
}

type configFile struct {
Expand Down Expand Up @@ -129,7 +130,7 @@ func (ir ImageRefs) AsEnv() []string {
// StackImageRefs function selects the appropriate set of Docker image references for the given stack version.
func (ac *ApplicationConfiguration) StackImageRefs() ImageRefs {
refs := ac.c.Stack.ImageRefOverridesForVersion(ac.stackVersion)
refs.ElasticAgent = stringOrDefault(refs.ElasticAgent, fmt.Sprintf("%s:%s", selectElasticAgentImageName(ac.stackVersion, ac.agentBaseImage), ac.stackVersion))
refs.ElasticAgent = stringOrDefault(refs.ElasticAgent, fmt.Sprintf("%s:%s", selectElasticAgentImageName(ac.agentVersion, ac.agentBaseImage), ac.agentVersion))
refs.Elasticsearch = stringOrDefault(refs.Elasticsearch, fmt.Sprintf("%s:%s", elasticsearchImageName, ac.stackVersion))
refs.Kibana = stringOrDefault(refs.Kibana, fmt.Sprintf("%s:%s", kibanaImageName, ac.stackVersion))
refs.Logstash = stringOrDefault(refs.Logstash, fmt.Sprintf("%s:%s", logstashImageName, ac.stackVersion))
Expand Down Expand Up @@ -157,14 +158,14 @@ func (ac *ApplicationConfiguration) SetCurrentProfile(name string) {

// selectElasticAgentImageName function returns the appropriate image name for Elastic-Agent depending on the stack version.
// This is mandatory as "elastic-agent-complete" is available since 7.15.0-SNAPSHOT.
func selectElasticAgentImageName(version, agentBaseImage string) string {
if version == "" { // as version is optional and can be empty
func selectElasticAgentImageName(agentVersion, agentBaseImage string) string {
if agentVersion == "" { // as version is optional and can be empty
return elasticAgentWolfiImageName
}

v, err := semver.NewVersion(version)
v, err := semver.NewVersion(agentVersion)
if err != nil {
logger.Errorf("stack version not in semver format (value: %s): %v", version, err)
logger.Errorf("agent version not in semver format (value: %s): %v", agentVersion, err)
return elasticAgentWolfiImageName
}

Expand Down Expand Up @@ -217,6 +218,7 @@ func selectElasticAgentSystemDImageName(version *semver.Version) string {
type configurationOptions struct {
agentBaseImage string
stackVersion string
agentVersion string
}

type ConfigurationOption func(*configurationOptions)
Expand All @@ -235,6 +237,13 @@ func OptionWithStackVersion(stackVersion string) ConfigurationOption {
}
}

// OptionWithAgentVersion sets the Elastic Agent version to be used.
func OptionWithAgentVersion(agentVersion string) ConfigurationOption {
return func(opts *configurationOptions) {
opts.agentVersion = agentVersion
}
}

// Configuration function returns the elastic-package configuration.
func Configuration(options ...ConfigurationOption) (*ApplicationConfiguration, error) {
configPath, err := locations.NewLocationManager()
Expand Down Expand Up @@ -265,6 +274,7 @@ func Configuration(options ...ConfigurationOption) (*ApplicationConfiguration, e
c: c,
agentBaseImage: configOptions.agentBaseImage,
stackVersion: configOptions.stackVersion,
agentVersion: configOptions.agentVersion,
}

return &configuration, nil
Expand Down
2 changes: 2 additions & 0 deletions internal/service/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Options struct {
DevDeployDir string
DataStreamRootPath string
StackVersion string
AgentVersion string

Variant string
}
Expand All @@ -45,6 +46,7 @@ func BootUp(ctx context.Context, options Options) error {
Variant: options.Variant,
StackVersion: options.StackVersion,
DeployIndependentAgent: false,
AgentVersion: options.AgentVersion,
})
if errors.Is(err, os.ErrNotExist) {
fmt.Println("No service defined.")
Expand Down
Loading