Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove created agents in service deployer #1771

Merged
merged 7 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all 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 internal/servicedeployer/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func Factory(options FactoryOptions) (ServiceDeployer, error) {
Profile: options.Profile,
DefinitionsDir: serviceDeployerPath,
StackVersion: options.StackVersion,
PolicyName: options.PolicyName,
RunSetup: options.RunSetup,
RunTestsOnly: options.RunTestsOnly,
RunTearDown: options.RunTearDown,
Expand Down
42 changes: 33 additions & 9 deletions internal/servicedeployer/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type KubernetesServiceDeployer struct {
profile *profile.Profile
definitionsDir string
stackVersion string
policyName string

deployIndependentAgent bool

Expand All @@ -40,6 +41,7 @@ type KubernetesServiceDeployerOptions struct {
Profile *profile.Profile
DefinitionsDir string
StackVersion string
PolicyName string

DeployIndependentAgent bool

Expand All @@ -49,14 +51,30 @@ type KubernetesServiceDeployerOptions struct {
}

type kubernetesDeployedService struct {
svcInfo ServiceInfo
svcInfo ServiceInfo
stackVersion string
profile *profile.Profile
policyName string

deployIndependentAgent bool

definitionsDir string
}

func (s kubernetesDeployedService) TearDown(ctx context.Context) error {
logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsDir)
if !s.deployIndependentAgent {
logger.Debug("Uninstall Elastic Agent Kubernetes")
elasticAgentManagedYaml, err := getElasticAgentYAML(s.profile, s.stackVersion, s.policyName)
if err != nil {
return fmt.Errorf("can't retrieve Kubernetes file for Elastic Agent: %w", err)
}
err = kubectl.DeleteStdin(ctx, elasticAgentManagedYaml)
if err != nil {
return fmt.Errorf("can't uninstall Elastic Agent Kubernetes resources (path: %s): %w", s.definitionsDir, err)
}
}

logger.Debugf("Uninstall custom Kubernetes definitions (directory: %s)", s.definitionsDir)
definitionPaths, err := findKubernetesDefinitions(s.definitionsDir)
if err != nil {
return fmt.Errorf("can't find Kubernetes definitions in given directory (path: %s): %w", s.definitionsDir, err)
Expand All @@ -71,6 +89,7 @@ func (s kubernetesDeployedService) TearDown(ctx context.Context) error {
if err != nil {
return fmt.Errorf("can't uninstall Kubernetes resources (path: %s): %w", s.definitionsDir, err)
}

return nil
}

Expand Down Expand Up @@ -99,6 +118,7 @@ func NewKubernetesServiceDeployer(opts KubernetesServiceDeployerOptions) (*Kuber
profile: opts.Profile,
definitionsDir: opts.DefinitionsDir,
stackVersion: opts.StackVersion,
policyName: opts.PolicyName,
runSetup: opts.RunSetup,
runTestsOnly: opts.RunTestsOnly,
runTearDown: opts.RunTearDown,
Expand Down Expand Up @@ -126,7 +146,7 @@ func (ksd KubernetesServiceDeployer) SetUp(ctx context.Context, svcInfo ServiceI
if ksd.runTearDown || ksd.runTestsOnly || ksd.deployIndependentAgent {
logger.Debug("Skip install Elastic Agent in cluster")
} else {
err = installElasticAgentInCluster(ctx, ksd.profile, ksd.stackVersion)
err = installElasticAgentInCluster(ctx, ksd.profile, ksd.stackVersion, ksd.policyName)
if err != nil {
return nil, fmt.Errorf("can't install Elastic-Agent in the Kubernetes cluster: %w", err)
}
Expand All @@ -145,8 +165,12 @@ func (ksd KubernetesServiceDeployer) SetUp(ctx context.Context, svcInfo ServiceI
// to deploy Agent Pod. Because of this, hostname inside pod will be equal to the name of the k8s host.
svcInfo.Agent.Host.NamePrefix = "kind-control-plane"
return &kubernetesDeployedService{
svcInfo: svcInfo,
definitionsDir: ksd.definitionsDir,
svcInfo: svcInfo,
definitionsDir: ksd.definitionsDir,
stackVersion: ksd.stackVersion,
profile: ksd.profile,
deployIndependentAgent: ksd.deployIndependentAgent,
policyName: ksd.policyName,
}, nil
}

Expand Down Expand Up @@ -183,10 +207,10 @@ func findKubernetesDefinitions(definitionsDir string) ([]string, error) {
return definitionPaths, nil
}

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

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

func getElasticAgentYAML(profile *profile.Profile, stackVersion string) ([]byte, error) {
func getElasticAgentYAML(profile *profile.Profile, stackVersion, policyName string) ([]byte, error) {
logger.Debugf("Prepare YAML definition for Elastic Agent running in stack v%s", stackVersion)

appConfig, err := install.Configuration()
Expand All @@ -222,7 +246,7 @@ func getElasticAgentYAML(profile *profile.Profile, stackVersion string) ([]byte,
"kibanaURL": "https://kibana:5601",
"caCertPem": caCert,
"elasticAgentImage": appConfig.StackImageRefs(stackVersion).ElasticAgent,
"elasticAgentTokenPolicyName": getTokenPolicyName(stackVersion, defaulFleetTokenPolicyName),
"elasticAgentTokenPolicyName": getTokenPolicyName(stackVersion, policyName),
})
if err != nil {
return nil, fmt.Errorf("can't generate elastic agent manifest: %w", err)
Expand Down
29 changes: 15 additions & 14 deletions internal/testrunner/runners/system/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ type runner struct {
serviceStateFilePath string

// Execution order of following handlers is defined in runner.TearDown() method.
unenrollAgentHandler func(context.Context) error
removeAgentHandler func(context.Context) error
deleteTestPolicyHandler func(context.Context) error
deletePackageHandler func(context.Context) error
resetAgentPolicyHandler func(context.Context) error
Expand Down Expand Up @@ -374,11 +374,11 @@ func (r *runner) tearDownTest(ctx context.Context) error {
r.resetAgentLogLevelHandler = nil
}

if r.unenrollAgentHandler != nil {
if err := r.unenrollAgentHandler(cleanupCtx); err != nil {
if r.removeAgentHandler != nil {
if err := r.removeAgentHandler(cleanupCtx); err != nil {
return err
}
r.unenrollAgentHandler = nil
r.removeAgentHandler = nil
}

if r.deleteTestPolicyHandler != nil {
Expand Down Expand Up @@ -805,7 +805,7 @@ func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInf
scenario.enrollingTime = enrollingTime
scenario.agent = agentDeployed

service, svcInfo, err := r.setupService(ctx, config, serviceOptions, svcInfo, agentInfo, agentDeployed, serviceStateData)
service, svcInfo, err := r.setupService(ctx, config, serviceOptions, svcInfo, agentInfo, agentDeployed, policy, serviceStateData)
if errors.Is(err, os.ErrNotExist) {
logger.Debugf("No service deployer defined for this test")
} else if err != nil {
Expand Down Expand Up @@ -933,14 +933,16 @@ func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInf
agent := agents[0]
logger.Debugf("Selected enrolled agent %q", agent.ID)

r.unenrollAgentHandler = func(ctx context.Context) error {
if !r.options.RunIndependentElasticAgent {
r.removeAgentHandler = func(ctx context.Context) error {
// When not using independent agents, service deployers like kubernetes or custom agents create new Elastic Agent
createdNewAgent := svcInfo.Agent.Host.NamePrefix == "docker-custom-agent" || svcInfo.Agent.Host.NamePrefix == "kind-control-plane"
Copy link
Member

Choose a reason for hiding this comment

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

Nit. Depending on the name of the agent may be fragile, we may forget to modify this if the set of names change.

Copy link
Contributor Author

@mrodm mrodm Apr 16, 2024

Choose a reason for hiding this comment

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

I could add a new field into svcInfo to set whether or not this service requires a new Agent (different from the stack).

Maybe something like this (adding Stack field) ?

	// Agent related properties.
	Agent struct {
		// Host describes the machine which is running the agent.
		Host struct {
			// Name prefix for the host's name
			NamePrefix string
		}
		// Stack indicates whether or not this Agent is the one running/set in "elastic-package stack up"
		Stack bool
	}

WDYT @jsoriano ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or maybe change it to be Independent

svcInfo.Agent.Independent (true or false)

Copy link
Member

Choose a reason for hiding this comment

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

Both options SGTM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perfect, I'll merge this PR as it is then, and I'll create a follow-up PR to remove those agent names with one of these options and run the tests with integrations again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created PR #1776

if !r.options.RunIndependentElasticAgent && !createdNewAgent {
return nil
}
logger.Debug("unenrolling agent...")
logger.Debug("removing agent...")
err := r.options.KibanaClient.RemoveAgent(ctx, agent)
if err != nil {
return fmt.Errorf("failed to unenroll agent %q: %w", agent.ID, err)
return fmt.Errorf("failed to remove agent %q: %w", agent.ID, err)
}
return nil
}
Expand Down Expand Up @@ -1094,7 +1096,7 @@ func (r *runner) prepareScenario(ctx context.Context, config *testConfig, svcInf
return &scenario, nil
}

func (r *runner) setupService(ctx context.Context, config *testConfig, serviceOptions servicedeployer.FactoryOptions, svcInfo servicedeployer.ServiceInfo, agentInfo agentdeployer.AgentInfo, agentDeployed agentdeployer.DeployedAgent, state ServiceState) (servicedeployer.DeployedService, servicedeployer.ServiceInfo, error) {
func (r *runner) setupService(ctx context.Context, config *testConfig, serviceOptions servicedeployer.FactoryOptions, svcInfo servicedeployer.ServiceInfo, agentInfo agentdeployer.AgentInfo, agentDeployed agentdeployer.DeployedAgent, policy *kibana.Policy, state ServiceState) (servicedeployer.DeployedService, servicedeployer.ServiceInfo, error) {
logger.Debug("setting up service...")
if r.options.RunTearDown || r.options.RunTestsOnly {
svcInfo.Test.RunID = state.ServiceRunID
Expand All @@ -1112,10 +1114,9 @@ func (r *runner) setupService(ctx context.Context, config *testConfig, serviceOp
svcInfo.Logs.Folder.Local = agentInfo.Logs.Folder.Local
}

// In case of custom agent (servicedeployer) enabling independent agents, update serviceOptions to include test policy too
if r.options.RunIndependentElasticAgent {
serviceOptions.PolicyName = agentInfo.Policy.Name
}
// In case of custom or kubernetes agents (servicedeployer) it is needed also the Agent Policy created
// for each test execution
serviceOptions.PolicyName = policy.Name

if config.Service != "" {
svcInfo.Name = config.Service
Expand Down