From 2b85191686182a4d549ff11878b49e9351c398c6 Mon Sep 17 00:00:00 2001 From: Anderson Queiroz Date: Fri, 1 Sep 2023 14:08:37 +0200 Subject: [PATCH] wip --- .../artifact/download/http/downloader.go | 22 +- internal/pkg/agent/cmd/enroll_cmd.go | 4 +- internal/pkg/agent/cmd/logs_test.go | 30 +- pkg/testing/fixture_install.go | 16 +- pkg/testing/multipass/provisioner.go | 5 +- pkg/testing/tools/agents.go | 134 +-------- pkg/testing/tools/check/check.go | 26 +- pkg/testing/tools/cmd.go | 25 -- pkg/testing/tools/fleet/fleet.go | 128 +++++++++ pkg/testing/tools/tools.go | 50 ++-- testing/integration/diagnostics_test.go | 4 +- testing/integration/endpoint_security_test.go | 268 +++++++++--------- testing/integration/fqdn_test.go | 5 +- testing/integration/monitoring_logs_test.go | 5 +- testing/integration/proxy_url_test.go | 12 +- testing/integration/upgrade_test.go | 114 ++++---- 16 files changed, 449 insertions(+), 399 deletions(-) delete mode 100644 pkg/testing/tools/cmd.go create mode 100644 pkg/testing/tools/fleet/fleet.go diff --git a/internal/pkg/agent/application/upgrade/artifact/download/http/downloader.go b/internal/pkg/agent/application/upgrade/artifact/download/http/downloader.go index 4336c4153d8..b6a6dc2a346 100644 --- a/internal/pkg/agent/application/upgrade/artifact/download/http/downloader.go +++ b/internal/pkg/agent/application/upgrade/artifact/download/http/downloader.go @@ -168,7 +168,7 @@ func (e *Downloader) downloadFile(ctx context.Context, artifactName, filename, f return "", err } - req, err := http.NewRequest("GET", sourceURI, nil) + req, err := http.NewRequest(http.MethodGet, sourceURI, nil) if err != nil { return "", errors.New(err, "fetching package failed", errors.TypeNetwork, errors.M(errors.MetaKeyURI, sourceURI)) } @@ -232,7 +232,11 @@ type downloadProgressReporter struct { started time.Time } -func newDownloadProgressReporter(log progressLogger, sourceURI string, timeout time.Duration, length int) *downloadProgressReporter { +func newDownloadProgressReporter( + log progressLogger, + sourceURI string, + timeout time.Duration, + length int) *downloadProgressReporter { return &downloadProgressReporter{ log: log, sourceURI: sourceURI, @@ -328,7 +332,12 @@ func (dp *downloadProgressReporter) ReportFailed(err error) { percentComplete := downloaded / dp.length * 100.0 msg = "download from %s failed at %s/%s (%.2f%% complete) @ %sps: %s" args = []interface{}{ - dp.sourceURI, units.HumanSize(downloaded), units.HumanSize(dp.length), percentComplete, units.HumanSize(bytesPerSecond), err, + dp.sourceURI, + units.HumanSize(downloaded), + units.HumanSize(dp.length), + percentComplete, + units.HumanSize(bytesPerSecond), + err, } } else { // length unknown so provide the amount downloaded and the speed @@ -337,16 +346,17 @@ func (dp *downloadProgressReporter) ReportFailed(err error) { dp.sourceURI, units.HumanSize(downloaded), units.HumanSize(bytesPerSecond), err, } } - dp.log.Infof(msg, args...) + dp.log.Errorf(msg, args...) if timePast >= dp.warnTimeout { // see reason in `Report` dp.log.Warnf(msg, args...) } } -// progressLogger is a logger that only needs to implement Infof and Warnf, as those are the only functions -// that the downloadProgressReporter uses. +// progressLogger is a logger that only needs to implement Infof and Warnf and +// Errorf as those are the only functions that the downloadProgressReporter uses. type progressLogger interface { Infof(format string, args ...interface{}) Warnf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) } diff --git a/internal/pkg/agent/cmd/enroll_cmd.go b/internal/pkg/agent/cmd/enroll_cmd.go index 30d9a43621a..ed8f073752b 100644 --- a/internal/pkg/agent/cmd/enroll_cmd.go +++ b/internal/pkg/agent/cmd/enroll_cmd.go @@ -269,9 +269,9 @@ func (c *enrollCmd) Execute(ctx context.Context, streams *cli.IOStreams) error { defer func() { if err != nil { - fmt.Fprintln(streams.Out, "Successfully enrolled the Elastic Agent.") - } else { fmt.Fprintf(streams.Out, "Something went wrong while enrolling the Elastic Agent: %v\n", err) + } else { + fmt.Fprintln(streams.Out, "Successfully enrolled the Elastic Agent.") } }() diff --git a/internal/pkg/agent/cmd/logs_test.go b/internal/pkg/agent/cmd/logs_test.go index 620ed100b4c..c02e58b8ae4 100644 --- a/internal/pkg/agent/cmd/logs_test.go +++ b/internal/pkg/agent/cmd/logs_test.go @@ -38,10 +38,10 @@ func TestGetLogFilenames(t *testing.T) { t.Run("returns the correct sorted filelist", func(t *testing.T) { dir := t.TempDir() - createFileEmpty(t, dir, file2) - createFileEmpty(t, dir, file) - createFileEmpty(t, dir, file1) - createFileEmpty(t, dir, file3) + createFileForTest(t, dir, file2) + createFileForTest(t, dir, file) + createFileForTest(t, dir, file1) + createFileForTest(t, dir, file3) names, err := getLogFilenames(dir) require.NoError(t, err) @@ -62,14 +62,14 @@ func TestGetLogFilenames(t *testing.T) { prevDayFile2 := "elastic-agent-20230529-2.ndjson" prevDayFile3 := "elastic-agent-20230529-3.ndjson" - createFileEmpty(t, dir, file2) - createFileEmpty(t, dir, file) - createFileEmpty(t, dir, prevDayFile1) - createFileEmpty(t, dir, file1) - createFileEmpty(t, dir, prevDayFile) - createFileEmpty(t, dir, prevDayFile2) - createFileEmpty(t, dir, file3) - createFileEmpty(t, dir, prevDayFile3) + createFileForTest(t, dir, file2) + createFileForTest(t, dir, file) + createFileForTest(t, dir, prevDayFile1) + createFileForTest(t, dir, file1) + createFileForTest(t, dir, prevDayFile) + createFileForTest(t, dir, prevDayFile2) + createFileForTest(t, dir, file3) + createFileForTest(t, dir, prevDayFile3) names, err := getLogFilenames(dir) require.NoError(t, err) @@ -99,7 +99,7 @@ func TestGetLogFilenames(t *testing.T) { t.Run("does not return non-log entries", func(t *testing.T) { dir := t.TempDir() - createFileEmpty(t, dir, "excluded") + createFileForTest(t, dir, "excluded") names, err := getLogFilenames(dir) require.NoError(t, err) @@ -109,7 +109,7 @@ func TestGetLogFilenames(t *testing.T) { t.Run("returns a list of one", func(t *testing.T) { dir := t.TempDir() - createFileEmpty(t, dir, file1) + createFileForTest(t, dir, file1) names, err := getLogFilenames(dir) require.NoError(t, err) @@ -539,7 +539,7 @@ func generateLines(prefix string, start, end int) string { return b.String() } -func createFileEmpty(t *testing.T, dir, name string) { +func createFileForTest(t *testing.T, dir, name string) { createFileContent(t, dir, name, nil) } diff --git a/pkg/testing/fixture_install.go b/pkg/testing/fixture_install.go index 14a4e265288..4f5d602a925 100644 --- a/pkg/testing/fixture_install.go +++ b/pkg/testing/fixture_install.go @@ -81,8 +81,12 @@ func (i InstallOpts) toCmdArgs() []string { return args } -// Install installs the prepared Elastic Agent binary and returns: -// - the combined output of stdout and stderr +// Install installs the prepared Elastic Agent binary and registers a t.Cleanup +// function to uninstall the agent if it hasn't been uninstalled. It also takes +// cate of collecting a diagnostics when AGENT_COLLECT_DIAG=true or the test +// has failed. +// It returns: +// - the combined output of Install command stdout and stderr // - an error if any. func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ...process.CmdOption) ([]byte, error) { installArgs := []string{"install"} @@ -114,7 +118,7 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts .. } // diagnostics is collected when either the environment variable - // AGENT_KEEP_INSTALLED=true or the test is marked failed + // AGENT_COLLECT_DIAG=true or the test is marked failed collect := collectDiag() failed := f.t.Failed() if collect || failed { @@ -221,11 +225,13 @@ func (f *Fixture) collectDiagnostics() { f.t.Logf("failed to collect diagnostics; failed to create %s: %s", diagPath, err) return } - outputPath := filepath.Join(diagPath, fmt.Sprintf("%s-diagnostics-%s.zip", f.t.Name(), time.Now().Format(time.RFC3339))) + outputPath := filepath.Join(diagPath, + fmt.Sprintf("%s-diagnostics-%s.zip", f.t.Name(), time.Now().Format(time.RFC3339))) output, err := f.Exec(ctx, []string{"diagnostics", "-f", outputPath}) if err != nil { - f.t.Logf("failed to collect diagnostics to %s (%s): %s", outputPath, err, output) + f.t.Logf("failed to collect diagnostics to %s. err: %v: output: %q", + outputPath, err, output) } } diff --git a/pkg/testing/multipass/provisioner.go b/pkg/testing/multipass/provisioner.go index 2be04b806fc..58392d4a75b 100644 --- a/pkg/testing/multipass/provisioner.go +++ b/pkg/testing/multipass/provisioner.go @@ -147,7 +147,10 @@ func (p *provisioner) launch(ctx context.Context, cfg runner.Config, batch runne var output bytes.Buffer p.logger.Logf("Launching multipass image %s", batch.ID) - proc, err := process.Start("multipass", process.WithContext(ctx), process.WithArgs(args), process.WithCmdOptions(runner.AttachOut(&output), runner.AttachErr(&output))) + proc, err := process.Start("multipass", + process.WithContext(ctx), + process.WithArgs(args), + process.WithCmdOptions(runner.AttachOut(&output), runner.AttachErr(&output))) if err != nil { return fmt.Errorf("failed to run multipass launch: %w", err) } diff --git a/pkg/testing/tools/agents.go b/pkg/testing/tools/agents.go index 1bb6eda9cd4..c6fc92d070d 100644 --- a/pkg/testing/tools/agents.go +++ b/pkg/testing/tools/agents.go @@ -6,137 +6,27 @@ package tools import ( "context" - "errors" - "fmt" - "os" "testing" "time" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" - "github.com/elastic/elastic-agent-libs/kibana" "github.com/elastic/elastic-agent/pkg/control/v2/client" "github.com/elastic/elastic-agent/pkg/control/v2/cproto" ) -// GetAgentByHostnameFromList get an agent by the local_metadata.host.name property, reading from the agents list -func GetAgentByHostnameFromList(client *kibana.Client, hostname string) (*kibana.AgentExisting, error) { - listAgentsResp, err := client.ListAgents(context.Background(), kibana.ListAgentsRequest{}) - if err != nil { - return nil, err +// WaitForLocalAgentHealthy will keep checking the agent state until it becomes healthy +// ot the timeout is exceeded. If the agent becomes health, it returns true, if +// not the test is marked as failed and false is returned. +// The timeout is the context deadline, if defined, or set to 2 minutes. +func WaitForLocalAgentHealthy(ctx context.Context, t *testing.T, c client.Client) bool { + // https://github.com/elastic/elastic-agent/pull/3265 + timeout := 2 * time.Minute + if deadline, ok := ctx.Deadline(); ok { + timeout = time.Until(deadline) } - for _, item := range listAgentsResp.Items { - agentHostname := item.LocalMetadata.Host.Hostname - if agentHostname == hostname { - return &item, nil - } - } - - return nil, fmt.Errorf("unable to find agent with hostname [%s]", hostname) -} - -func GetAgentStatus(client *kibana.Client) (string, error) { - hostname, err := os.Hostname() - if err != nil { - return "", err - } - - agent, err := GetAgentByHostnameFromList(client, hostname) - if err != nil { - return "", err - } - - return agent.Status, nil -} - -func GetAgentVersion(client *kibana.Client) (string, error) { - hostname, err := os.Hostname() - if err != nil { - return "", err - } - - agent, err := GetAgentByHostnameFromList(client, hostname) - if err != nil { - return "", err - } - - return agent.Agent.Version, err -} - -func UnEnrollAgent(client *kibana.Client) error { - hostname, err := os.Hostname() - if err != nil { - return err - } - agentID, err := GetAgentIDByHostname(client, hostname) - if err != nil { - return err - } - - unEnrollAgentReq := kibana.UnEnrollAgentRequest{ - ID: agentID, - Revoke: true, - } - _, err = client.UnEnrollAgent(context.Background(), unEnrollAgentReq) - if err != nil { - return fmt.Errorf("unable to unenroll agent with ID [%s]: %w", agentID, err) - } - - return nil -} - -func GetAgentIDByHostname(client *kibana.Client, hostname string) (string, error) { - agent, err := GetAgentByHostnameFromList(client, hostname) - if err != nil { - return "", err - } - return agent.Agent.ID, nil -} - -func UpgradeAgent(client *kibana.Client, version string) error { - hostname, err := os.Hostname() - if err != nil { - return err - } - agentID, err := GetAgentIDByHostname(client, hostname) - if err != nil { - return err - } - - upgradeAgentReq := kibana.UpgradeAgentRequest{ - ID: agentID, - Version: version, - } - _, err = client.UpgradeAgent(context.Background(), upgradeAgentReq) - if err != nil { - return fmt.Errorf("unable to upgrade agent with ID [%s]: %w", agentID, err) - } - - return nil -} - -func GetDefaultFleetServerURL(client *kibana.Client) (string, error) { - req := kibana.ListFleetServerHostsRequest{} - resp, err := client.ListFleetServerHosts(context.Background(), req) - if err != nil { - return "", fmt.Errorf("unable to list fleet server hosts: %w", err) - } - - for _, item := range resp.Items { - if item.IsDefault { - hostURLs := item.HostURLs - if len(hostURLs) > 0 { - return hostURLs[0], nil - } - } - } - - return "", errors.New("unable to determine default fleet server host") -} - -func WaitForAgent(ctx context.Context, t *testing.T, c client.Client) { - require.Eventually(t, func() bool { + return assert.Eventually(t, func() bool { err := c.Connect(ctx) if err != nil { t.Logf("connecting client to agent: %v", err) @@ -150,5 +40,5 @@ func WaitForAgent(ctx context.Context, t *testing.T, c client.Client) { } t.Logf("agent state: %+v", state) return state.State == cproto.State_HEALTHY - }, 2*time.Minute, 10*time.Second, "Agent never became healthy") + }, timeout, 10*time.Second, "Agent never became healthy") } diff --git a/pkg/testing/tools/check/check.go b/pkg/testing/tools/check/check.go index b5815fce255..0c56589a384 100644 --- a/pkg/testing/tools/check/check.go +++ b/pkg/testing/tools/check/check.go @@ -11,14 +11,16 @@ import ( "github.com/stretchr/testify/assert" + "github.com/elastic/elastic-agent-libs/kibana" "github.com/elastic/elastic-agent/pkg/control/v2/cproto" integrationtest "github.com/elastic/elastic-agent/pkg/testing" + "github.com/elastic/elastic-agent/pkg/testing/tools/fleet" ) // ConnectedToFleet checks if the agent defined in the fixture is connected to // Fleet Server. It uses assert.Eventually and if it fails the last error will // be printed. It returns if the agent is connected to Fleet Server or not. -func ConnectedToFleet(t *testing.T, fixture *integrationtest.Fixture) bool { +func ConnectedToFleet(t *testing.T, fixture *integrationtest.Fixture, timeout time.Duration) bool { t.Helper() var err error @@ -28,7 +30,7 @@ func ConnectedToFleet(t *testing.T, fixture *integrationtest.Fixture) bool { return agentStatus.FleetState == int(cproto.State_HEALTHY) } - connected := assert.Eventually(t, assertFn, 5*time.Minute, 5*time.Second, + connected := assert.Eventually(t, assertFn, timeout, 5*time.Second, "want fleet state %s, got %s. agent status: %v", cproto.State_HEALTHY, cproto.State(agentStatus.FleetState), agentStatus) @@ -39,3 +41,23 @@ func ConnectedToFleet(t *testing.T, fixture *integrationtest.Fixture) bool { return connected } + +// FleetAgentStatus returns a niladic function that returns true if the agent +// has reached expectedStatus; false otherwise. The returned function is intended +// for use with assert.Eventually or require.Eventually. +func FleetAgentStatus(t *testing.T, client *kibana.Client, expectedStatus string) func() bool { + return func() bool { + currentStatus, err := fleet.AgentStatus(client) + if err != nil { + t.Errorf("unable to determine agent status: %s", err.Error()) + return false + } + + if currentStatus == expectedStatus { + return true + } + + t.Logf("Agent fleet status: %s", currentStatus) + return false + } +} diff --git a/pkg/testing/tools/cmd.go b/pkg/testing/tools/cmd.go deleted file mode 100644 index 4330b1504d1..00000000000 --- a/pkg/testing/tools/cmd.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package tools - -import ( - "context" - - atesting "github.com/elastic/elastic-agent/pkg/testing" -) - -// InstallAgent force install the Elastic Agent through agentFixture. -func InstallAgent(installOpts atesting.InstallOpts, agentFixture *atesting.Fixture) ([]byte, error) { - return agentFixture.Install(context.Background(), &installOpts) -} - -// InstallStandaloneAgent force install the Elastic Agent through agentFixture. -func InstallStandaloneAgent(agentFixture *atesting.Fixture) ([]byte, error) { - installOpts := atesting.InstallOpts{ - NonInteractive: true, - Force: true, - } - return agentFixture.Install(context.Background(), &installOpts) -} diff --git a/pkg/testing/tools/fleet/fleet.go b/pkg/testing/tools/fleet/fleet.go new file mode 100644 index 00000000000..f92b3bff5b8 --- /dev/null +++ b/pkg/testing/tools/fleet/fleet.go @@ -0,0 +1,128 @@ +package fleet + +import ( + "context" + "errors" + "fmt" + "os" + + "github.com/elastic/elastic-agent-libs/kibana" +) + +// AgentByHostnameFromList get an agent by the local_metadata.host.name property, reading from the agents list +func AgentByHostnameFromList(client *kibana.Client, hostname string) (*kibana.AgentExisting, error) { + listAgentsResp, err := client.ListAgents(context.Background(), kibana.ListAgentsRequest{}) + if err != nil { + return nil, err + } + + for _, item := range listAgentsResp.Items { + agentHostname := item.LocalMetadata.Host.Hostname + if agentHostname == hostname { + return &item, nil + } + } + + return nil, fmt.Errorf("unable to find agent with hostname [%s]", hostname) +} + +func AgentStatus(client *kibana.Client) (string, error) { + // TODO: fix me: this does not work if FQDN is enabled + hostname, err := os.Hostname() + if err != nil { + return "", err + } + + agent, err := AgentByHostnameFromList(client, hostname) + if err != nil { + return "", err + } + + return agent.Status, nil +} + +func AgentVersion(client *kibana.Client) (string, error) { + hostname, err := os.Hostname() + if err != nil { + return "", err + } + + agent, err := AgentByHostnameFromList(client, hostname) + if err != nil { + return "", err + } + + return agent.Agent.Version, err +} + +func UnenrollAgent(client *kibana.Client) error { + hostname, err := os.Hostname() + if err != nil { + return err + } + agentID, err := AgentIDByHostname(client, hostname) + if err != nil { + return err + } + + unEnrollAgentReq := kibana.UnEnrollAgentRequest{ + ID: agentID, + Revoke: true, + } + _, err = client.UnEnrollAgent(context.Background(), unEnrollAgentReq) + if err != nil { + return fmt.Errorf("unable to unenroll agent with ID [%s]: %w", agentID, err) + } + + return nil +} + +func AgentIDByHostname(client *kibana.Client, hostname string) (string, error) { + agent, err := AgentByHostnameFromList(client, hostname) + if err != nil { + return "", err + } + return agent.Agent.ID, nil +} + +func UpgradeAgent(client *kibana.Client, version string) error { + // TODO: fix me: this does not work if FQDN is enabled + hostname, err := os.Hostname() + if err != nil { + return err + } + agentID, err := AgentIDByHostname(client, hostname) + if err != nil { + return err + } + + upgradeAgentReq := kibana.UpgradeAgentRequest{ + ID: agentID, + Version: version, + } + _, err = client.UpgradeAgent(context.Background(), upgradeAgentReq) + if err != nil { + return fmt.Errorf("unable to upgrade agent with ID [%s]: %w", agentID, err) + } + + return nil +} + +func DefaultURL(client *kibana.Client) (string, error) { + req := kibana.ListFleetServerHostsRequest{} + resp, err := client.ListFleetServerHosts(context.Background(), req) + if err != nil { + return "", fmt.Errorf("unable to list fleet server hosts: %w", err) + } + + for _, item := range resp.Items { + if item.IsDefault { + hostURLs := item.HostURLs + if len(hostURLs) > 0 { + return hostURLs[0], nil + } + } + } + + return "", errors.New("unable to determine default fleet server URL") +} diff --git a/pkg/testing/tools/tools.go b/pkg/testing/tools/tools.go index 7b125293eb6..3fe61a02e4c 100644 --- a/pkg/testing/tools/tools.go +++ b/pkg/testing/tools/tools.go @@ -10,32 +10,15 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/elastic/elastic-agent-libs/kibana" atesting "github.com/elastic/elastic-agent/pkg/testing" - - "github.com/stretchr/testify/require" + "github.com/elastic/elastic-agent/pkg/testing/tools/check" + "github.com/elastic/elastic-agent/pkg/testing/tools/fleet" ) -// WaitForAgentStatus returns a niladic function that returns true if the agent -// has reached expectedStatus; false otherwise. The returned function is intended -// for use with assert.Eventually or require.Eventually. -func WaitForAgentStatus(t *testing.T, client *kibana.Client, expectedStatus string) func() bool { - return func() bool { - currentStatus, err := GetAgentStatus(client) - if err != nil { - t.Errorf("unable to determine agent status: %s", err.Error()) - return false - } - - if currentStatus == expectedStatus { - return true - } - - t.Logf("Agent status: %s", currentStatus) - return false - } -} - // WaitForPolicyRevision returns a niladic function that returns true if the // given agent's policy revision has reached the given policy revision; false // otherwise. The returned function is intended @@ -53,7 +36,11 @@ func WaitForPolicyRevision(t *testing.T, client *kibana.Client, agentID string, // InstallAgentWithPolicy creates the given policy, enrolls the given agent // fixture in Fleet using the default Fleet Server, waits for the agent to be // online, and returns the created policy. -func InstallAgentWithPolicy(t *testing.T, ctx context.Context, installOpts atesting.InstallOpts, agentFixture *atesting.Fixture, kibClient *kibana.Client, createPolicyReq kibana.AgentPolicy) (kibana.PolicyResponse, error) { +func InstallAgentWithPolicy(t *testing.T, ctx context.Context, + installOpts atesting.InstallOpts, + agentFixture *atesting.Fixture, + kibClient *kibana.Client, + createPolicyReq kibana.AgentPolicy) (kibana.PolicyResponse, error) { t.Helper() // Create policy @@ -110,7 +97,7 @@ func InstallAgentForPolicy(t *testing.T, ctx context.Context, } // Get default Fleet Server URL - fleetServerURL, err := GetDefaultFleetServerURL(kibClient) + fleetServerURL, err := fleet.DefaultURL(kibClient) if err != nil { return fmt.Errorf("unable to get default Fleet Server URL: %w", err) } @@ -121,7 +108,8 @@ func InstallAgentForPolicy(t *testing.T, ctx context.Context, URL: fleetServerURL, EnrollmentToken: enrollmentToken.APIKey, } - output, err := InstallAgent(installOpts, agentFixture) + + output, err := agentFixture.Install(ctx, &installOpts) if err != nil { t.Log(string(output)) return fmt.Errorf("unable to enroll Elastic Agent: %w", err) @@ -132,10 +120,18 @@ func InstallAgentForPolicy(t *testing.T, ctx context.Context, if deadline, ok := ctx.Deadline(); ok { timeout = time.Until(deadline) } + + assert.Eventually( + t, + check.FleetAgentStatus(t, kibClient, "online"), + timeout, + 10*time.Second, + "Elastic Agent status is not online", + ) // Wait for Agent to be healthy - require.Eventually( + assert.Eventually( t, - WaitForAgentStatus(t, kibClient, "online"), + check.FleetAgentStatus(t, kibClient, "online"), timeout, 10*time.Second, "Elastic Agent status is not online", diff --git a/testing/integration/diagnostics_test.go b/testing/integration/diagnostics_test.go index 9b181c0075d..00d8d97aed0 100644 --- a/testing/integration/diagnostics_test.go +++ b/testing/integration/diagnostics_test.go @@ -88,7 +88,7 @@ type componentAndUnitNames struct { func TestDiagnosticsOptionalValues(t *testing.T) { define.Require(t, define.Requirements{ - Local: true, + Local: false, }) fixture, err := define.NewFixture(t, define.Version()) @@ -113,7 +113,7 @@ func TestDiagnosticsOptionalValues(t *testing.T) { func TestDiagnosticsCommand(t *testing.T) { define.Require(t, define.Requirements{ - Local: true, + Local: false, }) f, err := define.NewFixture(t, define.Version()) diff --git a/testing/integration/endpoint_security_test.go b/testing/integration/endpoint_security_test.go index bb77f724e52..666f4c994de 100644 --- a/testing/integration/endpoint_security_test.go +++ b/testing/integration/endpoint_security_test.go @@ -19,9 +19,8 @@ import ( "text/template" "time" - "github.com/stretchr/testify/require" - "github.com/google/uuid" + "github.com/stretchr/testify/require" "github.com/elastic/elastic-agent-libs/kibana" "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths" @@ -30,6 +29,7 @@ import ( atesting "github.com/elastic/elastic-agent/pkg/testing" "github.com/elastic/elastic-agent/pkg/testing/define" "github.com/elastic/elastic-agent/pkg/testing/tools" + "github.com/elastic/elastic-agent/pkg/testing/tools/fleet" "github.com/elastic/elastic-agent/pkg/testing/tools/testcontext" ) @@ -89,6 +89,131 @@ func TestInstallAndCLIUninstallWithEndpointSecurity(t *testing.T) { } } +// Tests that the agent can install and uninstall the endpoint-security service while remaining +// healthy. In this case endpoint-security is uninstalled because the agent was unenrolled, which +// triggers the creation of an empty agent policy removing all inputs (only when not force +// unenrolling). The empty agent policy triggers the uninstall of endpoint because endpoint was +// removed from the policy. +// +// Like the CLI uninstall test, the agent is uninstalled from the command line at the end of the test +// but at this point endpoint is already uninstalled. +func TestInstallAndUnenrollWithEndpointSecurity(t *testing.T) { + info := define.Require(t, define.Requirements{ + Stack: &define.Stack{}, + Local: false, // requires Agent installation + Isolate: false, + Sudo: true, // requires Agent installation + OS: []define.OS{ + {Type: define.Linux}, + }, + }) + + for _, tc := range protectionTests { + t.Run(tc.name, func(t *testing.T) { + testInstallAndUnenrollWithEndpointSecurity(t, info, tc.protected) + }) + } +} + +// Tests that the agent can install and uninstall the endpoint-security service +// after the Elastic Defend integration was removed from the policy +// while remaining healthy. +// +// Installing endpoint-security requires a Fleet managed agent with the Elastic Defend integration +// installed. The endpoint-security service is uninstalled the Elastic Defend integration was removed from the policy. +// +// Like the CLI uninstall test, the agent is uninstalled from the command line at the end of the test +// but at this point endpoint should be already uninstalled. + +func TestInstallWithEndpointSecurityAndRemoveEndpointIntegration(t *testing.T) { + info := define.Require(t, define.Requirements{ + Stack: &define.Stack{}, + Local: false, // requires Agent installation + Isolate: false, + Sudo: true, // requires Agent installation + OS: []define.OS{ + {Type: define.Linux}, + }, + }) + + for _, tc := range protectionTests { + t.Run(tc.name, func(t *testing.T) { + testInstallWithEndpointSecurityAndRemoveEndpointIntegration(t, info, tc.protected) + }) + } +} + +// Tests that install of Elastic Defend fails if Agent is installed in a base +// path other than default +func TestEndpointSecurityNonDefaultBasePath(t *testing.T) { + info := define.Require(t, define.Requirements{ + Stack: &define.Stack{}, + Local: false, // requires Agent installation + Isolate: false, + Sudo: true, // requires Agent installation + }) + + ctx, cn := context.WithCancel(context.Background()) + defer cn() + + // Get path to agent executable. + fixture, err := define.NewFixture(t, define.Version()) + require.NoError(t, err) + + t.Log("Enrolling the agent in Fleet") + policyUUID := uuid.New().String() + createPolicyReq := kibana.AgentPolicy{ + Name: "test-policy-" + policyUUID, + Namespace: "default", + Description: "Test policy " + policyUUID, + MonitoringEnabled: []kibana.MonitoringEnabledOption{ + kibana.MonitoringEnabledLogs, + kibana.MonitoringEnabledMetrics, + }, + } + installOpts := atesting.InstallOpts{ + NonInteractive: true, + Force: true, + BasePath: filepath.Join(paths.DefaultBasePath, "not_default"), + } + policyResp, err := tools.InstallAgentWithPolicy(t, ctx, installOpts, fixture, info.KibanaClient, createPolicyReq) + require.NoErrorf(t, err, "Policy Response was: %v", policyResp) + + t.Log("Installing Elastic Defend") + pkgPolicyResp, err := installElasticDefendPackage(t, info, policyResp.ID) + require.NoErrorf(t, err, "Policy Response was: %v", pkgPolicyResp) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + c := fixture.Client() + + require.Eventually(t, func() bool { + err := c.Connect(ctx) + if err != nil { + t.Logf("connecting client to agent: %v", err) + return false + } + defer c.Disconnect() + state, err := c.State(ctx) + if err != nil { + t.Logf("error getting the agent state: %v", err) + return false + } + t.Logf("agent state: %+v", state) + if state.State != cproto.State_DEGRADED { + return false + } + for _, c := range state.Components { + if strings.Contains(c.Message, + "Elastic Defend requires Elastic Agent be installed at the default installation path") { + return true + } + } + return false + }, 2*time.Minute, 10*time.Second, "Agent never became DEGRADED with default install message") +} + // buildPolicyWithTamperProtection helper function to build the policy request with or without tamper protection func buildPolicyWithTamperProtection(policy kibana.AgentPolicy, protected bool) kibana.AgentPolicy { if protected { @@ -108,7 +233,7 @@ func testInstallAndCLIUninstallWithEndpointSecurity(t *testing.T, info *define.I // Get path to agent executable. fixture, err := define.NewFixture(t, define.Version()) - require.NoError(t, err) + require.NoError(t, err, "could not create agent fixture") t.Log("Enrolling the agent in Fleet") policyUUID := uuid.New().String() @@ -145,7 +270,7 @@ func testInstallAndCLIUninstallWithEndpointSecurity(t *testing.T, info *define.I agentClient := fixture.Client() err = agentClient.Connect(ctx) - require.NoError(t, err) + require.NoError(t, err, "could not connect to local agent") require.Eventually(t, func() bool { return agentAndEndpointAreHealthy(t, ctx, agentClient) }, @@ -156,32 +281,6 @@ func testInstallAndCLIUninstallWithEndpointSecurity(t *testing.T, info *define.I t.Log("Verified endpoint component and units are healthy") } -// Tests that the agent can install and uninstall the endpoint-security service while remaining -// healthy. In this case endpoint-security is uninstalled because the agent was unenrolled, which -// triggers the creation of an empty agent policy removing all inputs (only when not force -// unenrolling). The empty agent policy triggers the uninstall of endpoint because endpoint was -// removed from the policy. -// -// Like the CLI uninstall test, the agent is uninstalled from the command line at the end of the test -// but at this point endpoint is already uninstalled. -func TestInstallAndUnenrollWithEndpointSecurity(t *testing.T) { - info := define.Require(t, define.Requirements{ - Stack: &define.Stack{}, - Local: false, // requires Agent installation - Isolate: false, - Sudo: true, // requires Agent installation - OS: []define.OS{ - {Type: define.Linux}, - }, - }) - - for _, tc := range protectionTests { - t.Run(tc.name, func(t *testing.T) { - testInstallAndUnenrollWithEndpointSecurity(t, info, tc.protected) - }) - } -} - func testInstallAndUnenrollWithEndpointSecurity(t *testing.T, info *define.Info, protected bool) { // Get path to agent executable. fixture, err := define.NewFixture(t, define.Version()) @@ -238,7 +337,7 @@ func testInstallAndUnenrollWithEndpointSecurity(t *testing.T, info *define.Info, hostname, err := os.Hostname() require.NoError(t, err) - agentID, err := tools.GetAgentIDByHostname(info.KibanaClient, hostname) + agentID, err := fleet.AgentIDByHostname(info.KibanaClient, hostname) require.NoError(t, err) _, err = info.KibanaClient.UnEnrollAgent(ctx, kibana.UnEnrollAgentRequest{ID: agentID}) @@ -293,34 +392,6 @@ func testInstallAndUnenrollWithEndpointSecurity(t *testing.T, info *define.Info, } } -// Tests that the agent can install and uninstall the endpoint-security service -// after the Elastic Defend integration was removed from the policy -// while remaining healthy. -// -// Installing endpoint-security requires a Fleet managed agent with the Elastic Defend integration -// installed. The endpoint-security service is uninstalled the Elastic Defend integration was removed from the policy. -// -// Like the CLI uninstall test, the agent is uninstalled from the command line at the end of the test -// but at this point endpoint should be already uninstalled. - -func TestInstallWithEndpointSecurityAndRemoveEndpointIntegration(t *testing.T) { - info := define.Require(t, define.Requirements{ - Stack: &define.Stack{}, - Local: false, // requires Agent installation - Isolate: false, - Sudo: true, // requires Agent installation - OS: []define.OS{ - {Type: define.Linux}, - }, - }) - - for _, tc := range protectionTests { - t.Run(tc.name, func(t *testing.T) { - testInstallWithEndpointSecurityAndRemoveEndpointIntegration(t, info, tc.protected) - }) - } -} - func testInstallWithEndpointSecurityAndRemoveEndpointIntegration(t *testing.T, info *define.Info, protected bool) { // Get path to agent executable. fixture, err := define.NewFixture(t, define.Version()) @@ -458,77 +529,6 @@ func installElasticDefendPackage(t *testing.T, info *define.Info, policyID strin return pkgResp, err } -// Tests that install of Elastic Defend fails if Agent is installed in a base -// path other than default -func TestEndpointSecurityNonDefaultBasePath(t *testing.T) { - info := define.Require(t, define.Requirements{ - Stack: &define.Stack{}, - Local: false, // requires Agent installation - Isolate: false, - Sudo: true, // requires Agent installation - }) - - ctx, cn := context.WithCancel(context.Background()) - defer cn() - - // Get path to agent executable. - fixture, err := define.NewFixture(t, define.Version()) - require.NoError(t, err) - - t.Log("Enrolling the agent in Fleet") - policyUUID := uuid.New().String() - createPolicyReq := kibana.AgentPolicy{ - Name: "test-policy-" + policyUUID, - Namespace: "default", - Description: "Test policy " + policyUUID, - MonitoringEnabled: []kibana.MonitoringEnabledOption{ - kibana.MonitoringEnabledLogs, - kibana.MonitoringEnabledMetrics, - }, - } - installOpts := atesting.InstallOpts{ - NonInteractive: true, - Force: true, - BasePath: filepath.Join(paths.DefaultBasePath, "not_default"), - } - policyResp, err := tools.InstallAgentWithPolicy(t, ctx, installOpts, fixture, info.KibanaClient, createPolicyReq) - require.NoErrorf(t, err, "Policy Response was: %v", policyResp) - - t.Log("Installing Elastic Defend") - pkgPolicyResp, err := installElasticDefendPackage(t, info, policyResp.ID) - require.NoErrorf(t, err, "Policy Response was: %v", pkgPolicyResp) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - c := fixture.Client() - - require.Eventually(t, func() bool { - err := c.Connect(ctx) - if err != nil { - t.Logf("connecting client to agent: %v", err) - return false - } - defer c.Disconnect() - state, err := c.State(ctx) - if err != nil { - t.Logf("error getting the agent state: %v", err) - return false - } - t.Logf("agent state: %+v", state) - if state.State != cproto.State_DEGRADED { - return false - } - for _, c := range state.Components { - if strings.Contains(c.Message, - "Elastic Defend requires Elastic Agent be installed at the default installation path") { - return true - } - } - return false - }, 2*time.Minute, 10*time.Second, "Agent never became DEGRADED with default install message") -} - func agentAndEndpointAreHealthy(t *testing.T, ctx context.Context, agentClient client.Client) bool { t.Helper() @@ -539,7 +539,7 @@ func agentAndEndpointAreHealthy(t *testing.T, ctx context.Context, agentClient c } if state.State != client.Healthy { - t.Logf("Agent is not Healthy\n%+v", state) + t.Logf("local Agent is not Healthy: current state: %+v", state) return false } @@ -548,7 +548,7 @@ func agentAndEndpointAreHealthy(t *testing.T, ctx context.Context, agentClient c for _, comp := range state.Components { isEndpointComponent := strings.Contains(comp.Name, "endpoint") if comp.State != client.Healthy { - t.Logf("Component is not Healthy\n%+v", comp) + t.Logf("endpoint component is not Healthy: current state: %+v", comp) return false } @@ -563,7 +563,7 @@ func agentAndEndpointAreHealthy(t *testing.T, ctx context.Context, agentClient c } if unit.State != client.Healthy { - t.Logf("Unit is not Healthy\n%+v", unit) + t.Logf("unit %q is not Healthy\n%+v", unit.UnitID, unit) return false } } @@ -571,7 +571,7 @@ func agentAndEndpointAreHealthy(t *testing.T, ctx context.Context, agentClient c // Ensure both the endpoint input and output units were found and healthy. if !foundEndpointInputUnit || !foundEndpointOutputUnit { - t.Logf("State did not contain endpoint units!\n%+v", state) + t.Logf("State did not contain endpoint units. state: %+v", state) return false } diff --git a/testing/integration/fqdn_test.go b/testing/integration/fqdn_test.go index b280f1e6e5b..35a95aab397 100644 --- a/testing/integration/fqdn_test.go +++ b/testing/integration/fqdn_test.go @@ -19,6 +19,7 @@ import ( "testing" "time" + "github.com/elastic/elastic-agent/pkg/testing/tools/fleet" "github.com/elastic/go-elasticsearch/v8" "github.com/elastic/elastic-agent-libs/kibana" @@ -58,7 +59,7 @@ func TestFQDN(t *testing.T) { t.Cleanup(func() { t.Log("Un-enrolling Elastic Agent...") - assert.NoError(t, tools.UnEnrollAgent(info.KibanaClient)) + assert.NoError(t, fleet.UnenrollAgent(info.KibanaClient)) t.Log("Restoring hostname...") err := setHostname(context.Background(), origHostname, t.Log) @@ -182,7 +183,7 @@ func verifyAgentName(t *testing.T, hostname string, kibClient *kibana.Client) *k require.Eventually( t, func() bool { - agent, err = tools.GetAgentByHostnameFromList(kibClient, hostname) + agent, err = fleet.AgentByHostnameFromList(kibClient, hostname) return err == nil && agent != nil }, 5*time.Minute, diff --git a/testing/integration/monitoring_logs_test.go b/testing/integration/monitoring_logs_test.go index 368462ed92b..3afbd8483d6 100644 --- a/testing/integration/monitoring_logs_test.go +++ b/testing/integration/monitoring_logs_test.go @@ -24,6 +24,7 @@ import ( "github.com/elastic/elastic-agent/pkg/testing/define" "github.com/elastic/elastic-agent/pkg/testing/tools" "github.com/elastic/elastic-agent/pkg/testing/tools/check" + "github.com/elastic/elastic-agent/pkg/testing/tools/fleet" ) func TestMonitoringLogsShipped(t *testing.T) { @@ -69,7 +70,7 @@ func TestMonitoringLogsShipped(t *testing.T) { require.NoError(t, err) t.Logf("created policy: %s", policy.ID) - check.ConnectedToFleet(t, agentFixture) + check.ConnectedToFleet(t, agentFixture, 5*time.Minute) // Stage 2: check indices // This is mostly for debugging @@ -114,7 +115,7 @@ func TestMonitoringLogsShipped(t *testing.T) { t.Fatalf("could not get hostname to filter Agent: %s", err) } - agentID, err := tools.GetAgentIDByHostname(info.KibanaClient, hostname) + agentID, err := fleet.AgentIDByHostname(info.KibanaClient, hostname) require.NoError(t, err, "could not get Agent ID by hostname") t.Logf("Agent ID: %q", agentID) diff --git a/testing/integration/proxy_url_test.go b/testing/integration/proxy_url_test.go index f37d3db945b..e95469405be 100644 --- a/testing/integration/proxy_url_test.go +++ b/testing/integration/proxy_url_test.go @@ -130,7 +130,7 @@ func TestProxyURL_EnrollProxyAndNoProxyInThePolicy(t *testing.T) { require.NoError(t, err, "failed to install agent") } - check.ConnectedToFleet(t, p.fixture) + check.ConnectedToFleet(t, p.fixture, 5*time.Minute) } func TestProxyURL_EnrollProxyAndEmptyProxyInThePolicy(t *testing.T) { @@ -175,7 +175,7 @@ func TestProxyURL_EnrollProxyAndEmptyProxyInThePolicy(t *testing.T) { require.NoError(t, err, "failed to install agent") } - check.ConnectedToFleet(t, p.fixture) + check.ConnectedToFleet(t, p.fixture, 5*time.Minute) } func TestProxyURL_ProxyInThePolicyTakesPrecedence(t *testing.T) { @@ -220,7 +220,7 @@ func TestProxyURL_ProxyInThePolicyTakesPrecedence(t *testing.T) { require.NoError(t, err, "failed to install agent") } - check.ConnectedToFleet(t, p.fixture) + check.ConnectedToFleet(t, p.fixture, 5*time.Minute) // ensure the agent is communicating through the proxy set in the policy want := fleetservertest.NewPathCheckin(p.policyData.AgentID) @@ -282,7 +282,7 @@ func TestProxyURL_NoEnrollProxyAndProxyInThePolicy(t *testing.T) { require.NoError(t, err, "failed to install agent") } - check.ConnectedToFleet(t, p.fixture) + check.ConnectedToFleet(t, p.fixture, 5*time.Minute) // ensure the agent is communicating through the new proxy if !assert.Eventually(t, func() bool { @@ -343,7 +343,7 @@ func TestProxyURL_RemoveProxyFromThePolicy(t *testing.T) { } // assert the agent is actually connected to fleet. - check.ConnectedToFleet(t, p.fixture) + check.ConnectedToFleet(t, p.fixture, 5*time.Minute) // ensure the agent is communicating through the proxy set in the policy if !assert.Eventually(t, func() bool { @@ -389,7 +389,7 @@ func TestProxyURL_RemoveProxyFromThePolicy(t *testing.T) { assert.Equal(t, inspect.Fleet.ProxyURL, want) // assert, again, the agent is actually connected to fleet. - check.ConnectedToFleet(t, p.fixture) + check.ConnectedToFleet(t, p.fixture, 5*time.Minute) } func (p *ProxyURL) setupFleet(t *testing.T, fleetHost string) { diff --git a/testing/integration/upgrade_test.go b/testing/integration/upgrade_test.go index 18aa028bd5f..3fa4f9d15c1 100644 --- a/testing/integration/upgrade_test.go +++ b/testing/integration/upgrade_test.go @@ -31,7 +31,6 @@ import ( "github.com/google/uuid" "github.com/elastic/elastic-agent-libs/kibana" - "github.com/elastic/elastic-agent/internal/pkg/agent/application/paths" cmdVersion "github.com/elastic/elastic-agent/internal/pkg/basecmd/version" "github.com/elastic/elastic-agent/internal/pkg/release" @@ -41,6 +40,8 @@ import ( atesting "github.com/elastic/elastic-agent/pkg/testing" "github.com/elastic/elastic-agent/pkg/testing/define" "github.com/elastic/elastic-agent/pkg/testing/tools" + "github.com/elastic/elastic-agent/pkg/testing/tools/check" + "github.com/elastic/elastic-agent/pkg/testing/tools/fleet" "github.com/elastic/elastic-agent/pkg/version" agtversion "github.com/elastic/elastic-agent/version" ) @@ -80,32 +81,43 @@ func TestFleetManagedUpgrade(t *testing.T) { ctx, cancel := context.WithCancel(context.TODO()) defer cancel() - upgradableVersions := getUpgradableVersions(ctx, t, define.Version()) - + // upgradableVersions := getUpgradableVersions(ctx, t, define.Version()) + v, err := version.ParseVersion("8.10.0") + require.NoError(t, err, "could not parse agent version") + upgradableVersions := []*version.ParsedSemVer{v} for _, parsedVersion := range upgradableVersions { - t.Run(fmt.Sprintf("Upgrade managed agent from %s to %s", parsedVersion, define.Version()), func(t *testing.T) { - agentFixture, err := atesting.NewFixture( - t, - parsedVersion.String(), - atesting.WithFetcher(atesting.ArtifactFetcher()), - ) - require.NoError(t, err) - err = agentFixture.Prepare(ctx) - require.NoError(t, err, "error preparing agent fixture") - - err = agentFixture.Configure(ctx, []byte(fastWatcherCfg)) - require.NoError(t, err, "error configuring agent fixture") - testUpgradeFleetManagedElasticAgent(t, ctx, info, agentFixture, parsedVersion, define.Version()) - }) + t.Run(fmt.Sprintf("Upgrade managed agent from %s to %s", + parsedVersion, define.Version()), + func(t *testing.T) { + agentFixture, err := atesting.NewFixture( + t, + parsedVersion.String(), + atesting.WithFetcher(atesting.ArtifactFetcher()), + ) + require.NoError(t, err) + err = agentFixture.Prepare(ctx) + require.NoError(t, err, "error preparing agent fixture") + + err = agentFixture.Configure(ctx, []byte(fastWatcherCfg)) + require.NoError(t, err, "error configuring agent fixture") + testUpgradeFleetManagedElasticAgent(t, ctx, + info, agentFixture, parsedVersion, define.Version()) + }) } } -func testUpgradeFleetManagedElasticAgent(t *testing.T, ctx context.Context, info *define.Info, agentFixture *atesting.Fixture, parsedFromVersion *version.ParsedSemVer, toVersion string) { +func testUpgradeFleetManagedElasticAgent( + t *testing.T, + ctx context.Context, + info *define.Info, + agentFixture *atesting.Fixture, + parsedFromVersion *version.ParsedSemVer, + toVersion string) { + kibClient := info.KibanaClient policyUUID := uuid.New().String() - t.Log("Creating Agent policy...") createPolicyReq := kibana.AgentPolicy{ Name: "test-policy-" + policyUUID, Namespace: "default", @@ -116,20 +128,18 @@ func testUpgradeFleetManagedElasticAgent(t *testing.T, ctx context.Context, info }, } policy, err := kibClient.CreatePolicy(ctx, createPolicyReq) - require.NoError(t, err) + require.NoError(t, err, "could not create policy") - t.Log("Creating Agent enrollment API key...") createEnrollmentApiKeyReq := kibana.CreateEnrollmentAPIKeyRequest{ PolicyID: policy.ID, } enrollmentToken, err := kibClient.CreateEnrollmentAPIKey(ctx, createEnrollmentApiKeyReq) - require.NoError(t, err) + require.NoError(t, err, "could not create agent's enrollment API key") - t.Log("Getting default Fleet Server URL...") - fleetServerURL, err := tools.GetDefaultFleetServerURL(kibClient) - require.NoError(t, err) + fleetServerURL, err := fleet.DefaultURL(kibClient) + require.NoError(t, err, "could not get default fleet-server URL") - t.Log("Enrolling Elastic Agent...") + t.Log("Installing Elastic Agent...") var nonInteractiveFlag bool if version_8_2_0.Less(*parsedFromVersion) { nonInteractiveFlag = true @@ -142,25 +152,27 @@ func testUpgradeFleetManagedElasticAgent(t *testing.T, ctx context.Context, info EnrollmentToken: enrollmentToken.APIKey, }, } - output, err := tools.InstallAgent(installOpts, agentFixture) + output, err := agentFixture.Install(ctx, &installOpts) if err != nil { t.Log(string(output)) } - require.NoError(t, err) - t.Cleanup(func() { - t.Log("Un-enrolling Elastic Agent...") - assert.NoError(t, tools.UnEnrollAgent(info.KibanaClient)) - }) + require.NoError(t, err, "failed to install the agent") - t.Log(`Waiting for enrolled Agent status to be "online"...`) - require.Eventually(t, tools.WaitForAgentStatus(t, kibClient, "online"), 2*time.Minute, 10*time.Second, "Agent status is not online") + t.Log(`Waiting for installed Agent status to be "online"...`) + require.Eventually(t, check.FleetAgentStatus(t, kibClient, "online"), + 2*time.Minute, 10*time.Second, "Agent status is not online") - t.Logf("Upgrade Elastic Agent to version %s...", toVersion) - err = tools.UpgradeAgent(kibClient, toVersion) - require.NoError(t, err) + t.Logf("Upgrade Elastic Agent to version from %s to %s...", + parsedFromVersion, toVersion) + err = fleet.UpgradeAgent(kibClient, toVersion) + require.NoError(t, err, "failed to start agent upgrade from fleet") - t.Log(`Waiting for enrolled Agent status to be "online"...`) - require.Eventually(t, tools.WaitForAgentStatus(t, kibClient, "online"), 10*time.Minute, 15*time.Second, "Agent status is not online") + t.Log(`Waiting for fleet Agent status to be "online" after upgrade...`) + assert.Eventually(t, // do not use require, the version check below must happen + check.FleetAgentStatus(t, kibClient, "online"), + 10*time.Minute, + 15*time.Second, + "fleet Agent status is not 'online'") // Upgrade Watcher check disabled until // https://github.com/elastic/elastic-agent/issues/2977 is resolved. @@ -169,11 +181,11 @@ func testUpgradeFleetManagedElasticAgent(t *testing.T, ctx context.Context, info // We remove the `-SNAPSHOT` suffix because, post-upgrade, the version reported // by the Agent will not contain this suffix, even if a `-SNAPSHOT`-suffixed // version was used as the target version for the upgrade. - require.Eventually(t, func() bool { + assert.Eventually(t, func() bool { t.Log("Getting Agent version...") - newVersion, err := tools.GetAgentVersion(kibClient) + newVersion, err := fleet.AgentVersion(kibClient) if err != nil { - t.Logf("error getting agent version: %v", err) + t.Logf("error getting fleet agent version: %v", err) return false } return strings.TrimRight(toVersion, `-SNAPSHOT`) == newVersion @@ -420,17 +432,16 @@ func testStandaloneUpgrade( if version_8_2_0.Less(*parsedFromVersion) { nonInteractiveFlag = true } + installOpts := atesting.InstallOpts{ NonInteractive: nonInteractiveFlag, Force: true, } - - output, err := tools.InstallAgent(installOpts, f) + output, err := f.Install(ctx, &installOpts) t.Logf("Agent installation output: %q", string(output)) require.NoError(t, err) c := f.Client() - err = c.Connect(ctx) require.NoError(t, err, "error connecting client to agent") defer c.Disconnect() @@ -587,12 +598,15 @@ func extractCommitHashFromArtifact(t *testing.T, ctx context.Context, artifactVe architecture := runtime.GOARCH suffix, err := atesting.GetPackageSuffix(operatingSystem, architecture) require.NoErrorf(t, err, "error determining suffix for OS %q and arch %q", operatingSystem, architecture) + prefix := fmt.Sprintf("elastic-agent-%s", artifactVersion.VersionWithPrerelease()) pkgName := fmt.Sprintf("%s-%s", prefix, suffix) require.Containsf(t, agentProject.Packages, pkgName, "Artifact API response does not contain pkg %s", pkgName) + artifactFilePath := filepath.Join(tmpDownloadDir, pkgName) err = atesting.DownloadPackage(ctx, t, http.DefaultClient, agentProject.Packages[pkgName].URL, artifactFilePath) require.NoError(t, err, "error downloading package") + err = atesting.ExtractArtifact(t, artifactFilePath, tmpDownloadDir) require.NoError(t, err, "error extracting artifact") @@ -659,8 +673,10 @@ func TestStandaloneUpgradeRetryDownload(t *testing.T) { require.NoError(t, err, "error configuring agent fixture") t.Log("Install the built Agent") - output, err := tools.InstallStandaloneAgent(agentFixture) - t.Log(string(output)) + output, err := agentFixture.Install(ctx, &atesting.InstallOpts{ + Force: true, + NonInteractive: true}) + t.Log("agen installation output:", string(output)) require.NoError(t, err) t.Log("Ensure the correct version is running") @@ -814,7 +830,9 @@ func TestUpgradeBrokenPackageVersion(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - output, err := tools.InstallStandaloneAgent(f) + output, err := f.Install(ctx, &atesting.InstallOpts{ + Force: true, + NonInteractive: true}) t.Logf("Agent installation output: %q", string(output)) require.NoError(t, err)