From e6fdd09b284c96ca58c5f68376545581b6bf369b Mon Sep 17 00:00:00 2001 From: "Lee E. Hinman" Date: Mon, 25 Mar 2024 17:00:47 -0500 Subject: [PATCH 1/2] Add RPM integration tests - add sles runner - add rhel runner - add test that uses rhel runner - add logging to ssh --- pkg/testing/fixture.go | 2 +- pkg/testing/fixture_install.go | 92 ++++++++++++ pkg/testing/ogc/supported.go | 26 ++++ pkg/testing/runner/debian.go | 138 +----------------- pkg/testing/runner/linux.go | 154 +++++++++++++++++++++ pkg/testing/runner/rhel.go | 112 +++++++++++++++ pkg/testing/runner/runner.go | 2 +- pkg/testing/runner/sles.go | 112 +++++++++++++++ pkg/testing/runner/ssh.go | 71 ++++++++-- pkg/testing/runner/supported.go | 24 ++++ pkg/testing/runner/supported_test.go | 28 +++- testing/integration/groups_test.go | 3 + testing/integration/logs_ingestion_test.go | 70 +++++++++- 13 files changed, 679 insertions(+), 155 deletions(-) create mode 100644 pkg/testing/runner/linux.go create mode 100644 pkg/testing/runner/rhel.go create mode 100644 pkg/testing/runner/sles.go diff --git a/pkg/testing/fixture.go b/pkg/testing/fixture.go index 1f74eac5ad2..de4555dea37 100644 --- a/pkg/testing/fixture.go +++ b/pkg/testing/fixture.go @@ -837,7 +837,7 @@ func (f *Fixture) binaryPath() string { workDir = filepath.Join(paths.DefaultBasePath, "Elastic", "Agent") } } - if f.packageFormat == "deb" { + if f.packageFormat == "deb" || f.packageFormat == "rpm" { workDir = "/usr/bin" } defaultBin := "elastic-agent" diff --git a/pkg/testing/fixture_install.go b/pkg/testing/fixture_install.go index c846874a068..036f02740d0 100644 --- a/pkg/testing/fixture_install.go +++ b/pkg/testing/fixture_install.go @@ -138,6 +138,8 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts .. return f.installNoPkgManager(ctx, installOpts, opts) case "deb": return f.installDeb(ctx, installOpts, opts) + case "rpm": + return f.installRpm(ctx, installOpts, opts) default: return nil, fmt.Errorf("package format %s isn't supported yet", f.packageFormat) } @@ -435,6 +437,81 @@ func (f *Fixture) installDeb(ctx context.Context, installOpts *InstallOpts, opts return nil, nil } +// installRpm installs the prepared Elastic Agent binary from the rpm +// package and registers a t.Cleanup function to uninstall the agent if +// it hasn't been uninstalled. It also takes care 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) installRpm(ctx context.Context, installOpts *InstallOpts, opts []process.CmdOption) ([]byte, error) { + f.t.Logf("[test %s] Inside fixture installRpm function", f.t.Name()) + //Prepare so that the f.srcPackage string is populated + err := f.EnsurePrepared(ctx) + if err != nil { + return nil, fmt.Errorf("failed to prepare: %w", err) + } + + // sudo rpm -iv elastic-agent rpm + out, err := exec.CommandContext(ctx, "sudo", "rpm", "-i", "-v", f.srcPackage).CombinedOutput() // #nosec G204 -- Need to pass in name of package + if err != nil { + return out, fmt.Errorf("rpm install failed: %w output:%s", err, string(out)) + } + + f.t.Cleanup(func() { + f.t.Logf("[test %s] Inside fixture installRpm cleanup function", f.t.Name()) + uninstallCtx, uninstallCancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer uninstallCancel() + // stop elastic-agent, non fatal if error, might have been stopped before this. + f.t.Logf("running 'sudo systemctl stop elastic-agent'") + out, err := exec.CommandContext(uninstallCtx, "sudo", "systemctl", "stop", "elastic-agent").CombinedOutput() + if err != nil { + f.t.Logf("error systemctl stop elastic-agent: %s, output: %s", err, string(out)) + } + // rpm -e elastic-agent rpm + f.t.Logf("running 'sudo rpm -e elastic-agent'") + out, err = exec.CommandContext(uninstallCtx, "sudo", "rpm", "-e", "elastic-agent").CombinedOutput() + if err != nil { + f.t.Logf("failed to 'sudo rpm -e elastic-agent': %s, output: %s", err, string(out)) + f.t.FailNow() + } + }) + + // start elastic-agent + out, err = exec.CommandContext(ctx, "sudo", "systemctl", "start", "elastic-agent").CombinedOutput() + if err != nil { + return out, fmt.Errorf("systemctl start elastic-agent failed: %w", err) + } + + // rpm install doesn't enroll, so need to do that + enrollArgs := []string{"elastic-agent", "enroll"} + if installOpts.Force { + enrollArgs = append(enrollArgs, "--force") + } + if installOpts.Insecure { + enrollArgs = append(enrollArgs, "--insecure") + } + if installOpts.ProxyURL != "" { + enrollArgs = append(enrollArgs, "--proxy-url="+installOpts.ProxyURL) + } + if installOpts.DelayEnroll { + enrollArgs = append(enrollArgs, "--delay-enroll") + } + if installOpts.EnrollOpts.URL != "" { + enrollArgs = append(enrollArgs, "--url", installOpts.EnrollOpts.URL) + } + if installOpts.EnrollOpts.EnrollmentToken != "" { + enrollArgs = append(enrollArgs, "--enrollment-token", installOpts.EnrollOpts.EnrollmentToken) + } + // run sudo elastic-agent enroll + out, err = exec.CommandContext(ctx, "sudo", enrollArgs...).CombinedOutput() + if err != nil { + return out, fmt.Errorf("elastic-agent enroll failed: %w, output: %s args: %v", err, string(out), enrollArgs) + } + + return nil, nil +} + type UninstallOpts struct { Force bool // --force UninstallToken string @@ -460,6 +537,8 @@ func (f *Fixture) Uninstall(ctx context.Context, uninstallOpts *UninstallOpts, o return f.uninstallNoPkgManager(ctx, uninstallOpts, opts) case "deb": return f.uninstallDeb(ctx, uninstallOpts, opts) + case "rpm": + return f.uninstallRpm(ctx, uninstallOpts, opts) default: return nil, fmt.Errorf("uninstall of package format '%s' not supported yet", f.packageFormat) } @@ -478,6 +557,19 @@ func (f *Fixture) uninstallDeb(ctx context.Context, uninstallOpts *UninstallOpts return out, nil } +func (f *Fixture) uninstallRpm(ctx context.Context, uninstallOpts *UninstallOpts, opts []process.CmdOption) ([]byte, error) { + // stop elastic-agent, non fatal if error, might have been stopped before this. + out, err := exec.CommandContext(ctx, "sudo", "systemctl", "stop", "elastic-agent").CombinedOutput() + if err != nil { + f.t.Logf("error systemctl stop elastic-agent: %s, output: %s", err, string(out)) + } + out, err = exec.CommandContext(ctx, "sudo", "rpm", "-e", "elastic-agent").CombinedOutput() + if err != nil { + return out, fmt.Errorf("error running 'sudo rpm -e elastic-agent': %w", err) + } + return out, nil +} + func (f *Fixture) uninstallNoPkgManager(ctx context.Context, uninstallOpts *UninstallOpts, opts []process.CmdOption) ([]byte, error) { if !f.installed { return nil, ErrNotInstalled diff --git a/pkg/testing/ogc/supported.go b/pkg/testing/ogc/supported.go index 34ae7d86c89..ec4074dc0e2 100644 --- a/pkg/testing/ogc/supported.go +++ b/pkg/testing/ogc/supported.go @@ -72,6 +72,32 @@ var ogcSupported = []LayoutOS{ Username: "ubuntu", RemotePath: "/home/ubuntu/agent", }, + { + OS: define.OS{ + Type: define.Linux, + Arch: define.AMD64, + Distro: runner.Sles, + Version: "15", + }, + Provider: Google, + InstanceSize: "e2-standard-2", // 2 amd64 cpus + RunsOn: "sles-15", + Username: "sles", + RemotePath: "/home/sles/agent", + }, + { + OS: define.OS{ + Type: define.Linux, + Arch: define.AMD64, + Distro: runner.Rhel, + Version: "8", + }, + Provider: Google, + InstanceSize: "e2-standard-2", // 2 amd64 cpus + RunsOn: "rhel-8", + Username: "rhel", + RemotePath: "/home/rhel/agent", + }, { OS: define.OS{ Type: define.Windows, diff --git a/pkg/testing/runner/debian.go b/pkg/testing/runner/debian.go index a3995efd602..0d52f70eb4d 100644 --- a/pkg/testing/runner/debian.go +++ b/pkg/testing/runner/debian.go @@ -7,7 +7,6 @@ package runner import ( "context" "fmt" - "os" "path" "path/filepath" "strings" @@ -88,108 +87,7 @@ func (DebianRunner) Prepare(ctx context.Context, sshClient SSHClient, logger Log // Copy places the required files on the host. func (DebianRunner) Copy(ctx context.Context, sshClient SSHClient, logger Logger, repoArchive string, builds []Build) error { - // copy the archive and extract it on the host - logger.Logf("Copying repo") - destRepoName := filepath.Base(repoArchive) - err := sshClient.Copy(repoArchive, destRepoName) - if err != nil { - return fmt.Errorf("failed to SCP repo archive %s: %w", repoArchive, err) - } - - // remove build paths, on cases where the build path is different from agent. - for _, build := range builds { - for _, remoteBuildPath := range []string{build.Path, build.SHA512Path} { - relativeAgentDir := filepath.Join("agent", remoteBuildPath) - _, _, err := sshClient.Exec(ctx, "sudo", []string{"rm", "-rf", relativeAgentDir}, nil) - // doesn't need to be a fatal error. - if err != nil { - logger.Logf("error removing build dir %s: %w", relativeAgentDir, err) - } - } - } - - // ensure that agent directory is removed (possible it already exists if instance already used) - stdout, stderr, err := sshClient.Exec(ctx, - "sudo", []string{"rm", "-rf", "agent"}, nil) - if err != nil { - return fmt.Errorf( - "failed to remove agent directory before unziping new one: %w. stdout: %q, stderr: %q", - err, stdout, stderr) - } - - stdOut, errOut, err := sshClient.Exec(ctx, "unzip", []string{destRepoName, "-d", "agent"}, nil) - if err != nil { - return fmt.Errorf("failed to unzip %s to agent directory: %w (stdout: %s, stderr: %s)", destRepoName, err, stdOut, errOut) - } - - // prepare for testing - logger.Logf("Running make mage and prepareOnRemote") - envs := `GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH"` - installMage := strings.NewReader(fmt.Sprintf(`cd agent && %s make mage && %s mage integration:prepareOnRemote`, envs, envs)) - stdOut, errOut, err = sshClient.Exec(ctx, "bash", nil, installMage) - if err != nil { - return fmt.Errorf("failed to perform make mage and prepareOnRemote: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) - } - - // determine if the build needs to be replaced on the host - // if it already exists and the SHA512 are the same contents, then - // there is no reason to waste time uploading the build - for _, build := range builds { - copyBuild := true - localSHA512, err := os.ReadFile(build.SHA512Path) - if err != nil { - return fmt.Errorf("failed to read local SHA52 contents %s: %w", build.SHA512Path, err) - } - hostSHA512Path := filepath.Base(build.SHA512Path) - hostSHA512, err := sshClient.GetFileContents(ctx, hostSHA512Path) - if err == nil { - if string(localSHA512) == string(hostSHA512) { - logger.Logf("Skipping copy agent build %s; already the same", filepath.Base(build.Path)) - copyBuild = false - } - } - - if copyBuild { - // ensure the existing copies are removed first - toRemove := filepath.Base(build.Path) - stdOut, errOut, err = sshClient.Exec(ctx, - "sudo", []string{"rm", "-f", toRemove}, nil) - if err != nil { - return fmt.Errorf("failed to remove %q: %w (stdout: %q, stderr: %q)", - toRemove, err, stdOut, errOut) - } - - toRemove = filepath.Base(build.SHA512Path) - stdOut, errOut, err = sshClient.Exec(ctx, - "sudo", []string{"rm", "-f", toRemove}, nil) - if err != nil { - return fmt.Errorf("failed to remove %q: %w (stdout: %q, stderr: %q)", - toRemove, err, stdOut, errOut) - } - - logger.Logf("Copying agent build %s", filepath.Base(build.Path)) - } - - for _, buildPath := range []string{build.Path, build.SHA512Path} { - if copyBuild { - err = sshClient.Copy(buildPath, filepath.Base(buildPath)) - if err != nil { - return fmt.Errorf("failed to SCP build %s: %w", filepath.Base(buildPath), err) - } - } - insideAgentDir := filepath.Join("agent", buildPath) - stdOut, errOut, err = sshClient.Exec(ctx, "mkdir", []string{"-p", filepath.Dir(insideAgentDir)}, nil) - if err != nil { - return fmt.Errorf("failed to create %s directory: %w (stdout: %s, stderr: %s)", filepath.Dir(insideAgentDir), err, stdOut, errOut) - } - stdOut, errOut, err = sshClient.Exec(ctx, "ln", []string{filepath.Base(buildPath), insideAgentDir}, nil) - if err != nil { - return fmt.Errorf("failed to hard link %s to %s: %w (stdout: %s, stderr: %s)", filepath.Base(buildPath), insideAgentDir, err, stdOut, errOut) - } - } - } - - return nil + return linuxCopy(ctx, sshClient, logger, repoArchive, builds) } // Run the test @@ -242,39 +140,7 @@ func (DebianRunner) Run(ctx context.Context, verbose bool, sshClient SSHClient, // Diagnostics gathers any diagnostics from the host. func (DebianRunner) Diagnostics(ctx context.Context, sshClient SSHClient, logger Logger, destination string) error { - // take ownership, as sudo tests will create with root permissions (allow to fail in the case it doesn't exist) - diagnosticDir := "$HOME/agent/build/diagnostics" - _, _, _ = sshClient.Exec(ctx, "sudo", []string{"chown", "-R", "$USER:$USER", diagnosticDir}, nil) - stdOut, _, err := sshClient.Exec(ctx, "ls", []string{"-1", diagnosticDir}, nil) - if err != nil { - //nolint:nilerr // failed to list the directory, probably don't have any diagnostics (do nothing) - return nil - } - eachDiagnostic := strings.Split(string(stdOut), "\n") - for _, filename := range eachDiagnostic { - filename = strings.TrimSpace(filename) - if filename == "" { - continue - } - - // don't use filepath.Join as we need this to work in Windows as well - // this is because if we use `filepath.Join` on a Windows host connected to a Linux host - // it will use a `\` and that will be incorrect for Linux - fp := fmt.Sprintf("%s/%s", diagnosticDir, filename) - // use filepath.Join on this path because it's a path on this specific host platform - dp := filepath.Join(destination, filename) - logger.Logf("Copying diagnostic %s", filename) - out, err := os.Create(dp) - if err != nil { - return fmt.Errorf("failed to create file %s: %w", dp, err) - } - err = sshClient.GetFileContentsOutput(ctx, fp, out) - _ = out.Close() - if err != nil { - return fmt.Errorf("failed to copy file from remote host to %s: %w", dp, err) - } - } - return nil + return linuxDiagnostics(ctx, sshClient, logger, destination) } func runTests(ctx context.Context, logger Logger, name string, prefix string, script string, sshClient SSHClient, tests []define.BatchPackageTests) ([]OSRunnerPackageResult, error) { diff --git a/pkg/testing/runner/linux.go b/pkg/testing/runner/linux.go new file mode 100644 index 00000000000..45ec2310290 --- /dev/null +++ b/pkg/testing/runner/linux.go @@ -0,0 +1,154 @@ +// 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 runner + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" +) + +func linuxDiagnostics(ctx context.Context, sshClient SSHClient, logger Logger, destination string) error { + // take ownership, as sudo tests will create with root permissions (allow to fail in the case it doesn't exist) + diagnosticDir := "$HOME/agent/build/diagnostics" + _, _, _ = sshClient.Exec(ctx, "sudo", []string{"chown", "-R", "$USER:$USER", diagnosticDir}, nil) + stdOut, _, err := sshClient.Exec(ctx, "ls", []string{"-1", diagnosticDir}, nil) + if err != nil { + //nolint:nilerr // failed to list the directory, probably don't have any diagnostics (do nothing) + return nil + } + eachDiagnostic := strings.Split(string(stdOut), "\n") + for _, filename := range eachDiagnostic { + filename = strings.TrimSpace(filename) + if filename == "" { + continue + } + + // don't use filepath.Join as we need this to work in Windows as well + // this is because if we use `filepath.Join` on a Windows host connected to a Linux host + // it will use a `\` and that will be incorrect for Linux + fp := fmt.Sprintf("%s/%s", diagnosticDir, filename) + // use filepath.Join on this path because it's a path on this specific host platform + dp := filepath.Join(destination, filename) + logger.Logf("Copying diagnostic %s", filename) + out, err := os.Create(dp) + if err != nil { + return fmt.Errorf("failed to create file %s: %w", dp, err) + } + err = sshClient.GetFileContentsOutput(ctx, fp, out) + _ = out.Close() + if err != nil { + return fmt.Errorf("failed to copy file from remote host to %s: %w", dp, err) + } + } + return nil +} + +func linuxCopy(ctx context.Context, sshClient SSHClient, logger Logger, repoArchive string, builds []Build) error { + // copy the archive and extract it on the host + logger.Logf("Copying repo") + destRepoName := filepath.Base(repoArchive) + err := sshClient.Copy(repoArchive, destRepoName) + if err != nil { + return fmt.Errorf("failed to SCP repo archive %s: %w", repoArchive, err) + } + + // remove build paths, on cases where the build path is different from agent. + for _, build := range builds { + for _, remoteBuildPath := range []string{build.Path, build.SHA512Path} { + relativeAgentDir := filepath.Join("agent", remoteBuildPath) + _, _, err := sshClient.Exec(ctx, "sudo", []string{"rm", "-rf", relativeAgentDir}, nil) + // doesn't need to be a fatal error. + if err != nil { + logger.Logf("error removing build dir %s: %w", relativeAgentDir, err) + } + } + } + + // ensure that agent directory is removed (possible it already exists if instance already used) + stdout, stderr, err := sshClient.Exec(ctx, + "sudo", []string{"rm", "-rf", "agent"}, nil) + if err != nil { + return fmt.Errorf( + "failed to remove agent directory before unziping new one: %w. stdout: %q, stderr: %q", + err, stdout, stderr) + } + + stdOut, errOut, err := sshClient.Exec(ctx, "unzip", []string{destRepoName, "-d", "agent"}, nil) + if err != nil { + return fmt.Errorf("failed to unzip %s to agent directory: %w (stdout: %s, stderr: %s)", destRepoName, err, stdOut, errOut) + } + + // prepare for testing + logger.Logf("Running make mage and prepareOnRemote") + envs := `GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH"` + installMage := strings.NewReader(fmt.Sprintf(`cd agent && %s make mage && %s mage integration:prepareOnRemote`, envs, envs)) + stdOut, errOut, err = sshClient.Exec(ctx, "bash", nil, installMage) + if err != nil { + return fmt.Errorf("failed to perform make mage and prepareOnRemote: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + + // determine if the build needs to be replaced on the host + // if it already exists and the SHA512 are the same contents, then + // there is no reason to waste time uploading the build + for _, build := range builds { + copyBuild := true + localSHA512, err := os.ReadFile(build.SHA512Path) + if err != nil { + return fmt.Errorf("failed to read local SHA52 contents %s: %w", build.SHA512Path, err) + } + hostSHA512Path := filepath.Base(build.SHA512Path) + hostSHA512, err := sshClient.GetFileContents(ctx, hostSHA512Path) + if err == nil { + if string(localSHA512) == string(hostSHA512) { + logger.Logf("Skipping copy agent build %s; already the same", filepath.Base(build.Path)) + copyBuild = false + } + } + + if copyBuild { + // ensure the existing copies are removed first + toRemove := filepath.Base(build.Path) + stdOut, errOut, err = sshClient.Exec(ctx, + "sudo", []string{"rm", "-f", toRemove}, nil) + if err != nil { + return fmt.Errorf("failed to remove %q: %w (stdout: %q, stderr: %q)", + toRemove, err, stdOut, errOut) + } + + toRemove = filepath.Base(build.SHA512Path) + stdOut, errOut, err = sshClient.Exec(ctx, + "sudo", []string{"rm", "-f", toRemove}, nil) + if err != nil { + return fmt.Errorf("failed to remove %q: %w (stdout: %q, stderr: %q)", + toRemove, err, stdOut, errOut) + } + + logger.Logf("Copying agent build %s", filepath.Base(build.Path)) + } + + for _, buildPath := range []string{build.Path, build.SHA512Path} { + if copyBuild { + err = sshClient.Copy(buildPath, filepath.Base(buildPath)) + if err != nil { + return fmt.Errorf("failed to SCP build %s: %w", filepath.Base(buildPath), err) + } + } + insideAgentDir := filepath.Join("agent", buildPath) + stdOut, errOut, err = sshClient.Exec(ctx, "mkdir", []string{"-p", filepath.Dir(insideAgentDir)}, nil) + if err != nil { + return fmt.Errorf("failed to create %s directory: %w (stdout: %s, stderr: %s)", filepath.Dir(insideAgentDir), err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(ctx, "ln", []string{filepath.Base(buildPath), insideAgentDir}, nil) + if err != nil { + return fmt.Errorf("failed to hard link %s to %s: %w (stdout: %s, stderr: %s)", filepath.Base(buildPath), insideAgentDir, err, stdOut, errOut) + } + } + } + + return nil +} diff --git a/pkg/testing/runner/rhel.go b/pkg/testing/runner/rhel.go new file mode 100644 index 00000000000..5d8a63bbc61 --- /dev/null +++ b/pkg/testing/runner/rhel.go @@ -0,0 +1,112 @@ +// 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 runner + +import ( + "context" + "fmt" + "path" + "strings" + "time" + + "github.com/elastic/elastic-agent/pkg/testing/define" +) + +// RhelRunner is a handler for running tests on SUSE Linux Enterpriser Server +type RhelRunner struct{} + +// Prepare configures the host for running the test +func (RhelRunner) Prepare(ctx context.Context, sshClient SSHClient, logger Logger, arch string, goVersion string) error { + logger.Logf("Install development tools") + dnfCtx, dnfCancel := context.WithTimeout(ctx, 20*time.Minute) + defer dnfCancel() + stdOut, errOut, err := sshClient.ExecWithRetry(dnfCtx, "sudo", []string{"dnf", "-y", "-v", "group", "install", "\"Development Tools\""}, 15*time.Second) + if err != nil { + return fmt.Errorf("failed to run 'dnf group install \"Development Tools\"': %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + + // install golang + logger.Logf("Install golang %s (%s)", goVersion, arch) + goCtx, goCancel := context.WithTimeout(ctx, 20*time.Minute) + defer goCancel() + downloadURL := fmt.Sprintf("https://go.dev/dl/go%s.linux-%s.tar.gz", goVersion, arch) + filename := path.Base(downloadURL) + stdOut, errOut, err = sshClient.Exec(goCtx, "curl", []string{"-Ls", downloadURL, "--output", filename}, nil) + if err != nil { + return fmt.Errorf("failed to download go from %s with curl: %w (stdout: %s, stderr: %s)", downloadURL, err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"tar", "-C", "/usr/local", "-xzf", filename}, nil) + if err != nil { + return fmt.Errorf("failed to extract go to /usr/local with tar: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"ln", "-s", "/usr/local/go/bin/go", "/usr/bin/go"}, nil) + if err != nil { + return fmt.Errorf("failed to symlink /usr/local/go/bin/go to /usr/bin/go: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"ln", "-s", "/usr/local/go/bin/gofmt", "/usr/bin/gofmt"}, nil) + if err != nil { + return fmt.Errorf("failed to symlink /usr/local/go/bin/gofmt to /usr/bin/gofmt: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + + return nil +} + +// Copy places the required files on the host +func (RhelRunner) Copy(ctx context.Context, sshClient SSHClient, logger Logger, repoArchive string, builds []Build) error { + return linuxCopy(ctx, sshClient, logger, repoArchive, builds) +} + +// Run the test +func (RhelRunner) Run(ctx context.Context, verbose bool, sshClient SSHClient, logger Logger, agentVersion string, prefix string, batch define.Batch, env map[string]string) (OSRunnerResult, error) { + var tests []string + for _, pkg := range batch.Tests { + for _, test := range pkg.Tests { + tests = append(tests, fmt.Sprintf("%s:%s", pkg.Name, test.Name)) + } + } + var sudoTests []string + for _, pkg := range batch.SudoTests { + for _, test := range pkg.Tests { + sudoTests = append(sudoTests, fmt.Sprintf("%s:%s", pkg.Name, test.Name)) + } + } + + logArg := "" + if verbose { + logArg = "-v" + } + var result OSRunnerResult + if len(tests) > 0 { + vars := fmt.Sprintf(`GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH" AGENT_VERSION="%s" TEST_DEFINE_PREFIX="%s" TEST_DEFINE_TESTS="%s"`, agentVersion, prefix, strings.Join(tests, ",")) + vars = extendVars(vars, env) + + script := fmt.Sprintf(`cd agent && %s ~/go/bin/mage %s integration:testOnRemote`, vars, logArg) + results, err := runTests(ctx, logger, "non-sudo", prefix, script, sshClient, batch.Tests) + if err != nil { + return OSRunnerResult{}, fmt.Errorf("error running non-sudo tests: %w", err) + } + result.Packages = results + } + + if len(sudoTests) > 0 { + prefix := fmt.Sprintf("%s-sudo", prefix) + vars := fmt.Sprintf(`GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH:/usr/sbin" AGENT_VERSION="%s" TEST_DEFINE_PREFIX="%s" TEST_DEFINE_TESTS="%s"`, agentVersion, prefix, strings.Join(sudoTests, ",")) + vars = extendVars(vars, env) + script := fmt.Sprintf(`cd agent && sudo %s ~/go/bin/mage %s integration:testOnRemote`, vars, logArg) + + results, err := runTests(ctx, logger, "sudo", prefix, script, sshClient, batch.SudoTests) + if err != nil { + return OSRunnerResult{}, fmt.Errorf("error running sudo tests: %w", err) + } + result.SudoPackages = results + } + + return result, nil +} + +// Diagnostics gathers any diagnostics from the host. +func (RhelRunner) Diagnostics(ctx context.Context, sshClient SSHClient, logger Logger, destination string) error { + return linuxDiagnostics(ctx, sshClient, logger, destination) +} diff --git a/pkg/testing/runner/runner.go b/pkg/testing/runner/runner.go index 639a908d0f5..9ddcecbd24a 100644 --- a/pkg/testing/runner/runner.go +++ b/pkg/testing/runner/runner.go @@ -333,7 +333,7 @@ func (r *Runner) runInstance(ctx context.Context, sshAuth ssh.AuthMethod, logger } logger.Logf("Starting SSH; connect with `ssh -i %s %s@%s`", sshPrivateKeyPath, instance.Username, instance.IP) - client := NewSSHClient(instance.IP, instance.Username, sshAuth) + client := NewSSHClient(instance.IP, instance.Username, sshAuth, logger) connectCtx, connectCancel := context.WithTimeout(ctx, 10*time.Minute) defer connectCancel() err = client.Connect(connectCtx) diff --git a/pkg/testing/runner/sles.go b/pkg/testing/runner/sles.go new file mode 100644 index 00000000000..ac634f6c50a --- /dev/null +++ b/pkg/testing/runner/sles.go @@ -0,0 +1,112 @@ +// 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 runner + +import ( + "context" + "fmt" + "path" + "strings" + "time" + + "github.com/elastic/elastic-agent/pkg/testing/define" +) + +// SlesRunner is a handler for running tests on SUSE Linux Enterpriser Server +type SlesRunner struct{} + +// Prepare configures the host for running the test +func (SlesRunner) Prepare(ctx context.Context, sshClient SSHClient, logger Logger, arch string, goVersion string) error { + logger.Logf("install devel_basis") + zypperCtx, zypperCancel := context.WithTimeout(ctx, 20*time.Minute) + defer zypperCancel() + stdOut, errOut, err := sshClient.ExecWithRetry(zypperCtx, "sudo", []string{"zypper", "install", "-y ", "-t", "pattern", "devel_basis"}, 15*time.Second) + if err != nil { + return fmt.Errorf("failed to run zypper install devel_basis: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + + // install golang + logger.Logf("Install golang %s (%s)", goVersion, arch) + goCtx, goCancel := context.WithTimeout(ctx, 20*time.Minute) + defer goCancel() + downloadURL := fmt.Sprintf("https://go.dev/dl/go%s.linux-%s.tar.gz", goVersion, arch) + filename := path.Base(downloadURL) + stdOut, errOut, err = sshClient.Exec(goCtx, "curl", []string{"-Ls", downloadURL, "--output", filename}, nil) + if err != nil { + return fmt.Errorf("failed to download go from %s with curl: %w (stdout: %s, stderr: %s)", downloadURL, err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"tar", "-C", "/usr/local", "-xzf", filename}, nil) + if err != nil { + return fmt.Errorf("failed to extract go to /usr/local with tar: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"ln", "-s", "/usr/local/go/bin/go", "/usr/bin/go"}, nil) + if err != nil { + return fmt.Errorf("failed to symlink /usr/local/go/bin/go to /usr/bin/go: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"ln", "-s", "/usr/local/go/bin/gofmt", "/usr/bin/gofmt"}, nil) + if err != nil { + return fmt.Errorf("failed to symlink /usr/local/go/bin/gofmt to /usr/bin/gofmt: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) + } + + return nil +} + +// Copy places the required files on the host +func (SlesRunner) Copy(ctx context.Context, sshClient SSHClient, logger Logger, repoArchive string, builds []Build) error { + return linuxCopy(ctx, sshClient, logger, repoArchive, builds) +} + +// Run the test +func (SlesRunner) Run(ctx context.Context, verbose bool, sshClient SSHClient, logger Logger, agentVersion string, prefix string, batch define.Batch, env map[string]string) (OSRunnerResult, error) { + var tests []string + for _, pkg := range batch.Tests { + for _, test := range pkg.Tests { + tests = append(tests, fmt.Sprintf("%s:%s", pkg.Name, test.Name)) + } + } + var sudoTests []string + for _, pkg := range batch.SudoTests { + for _, test := range pkg.Tests { + sudoTests = append(sudoTests, fmt.Sprintf("%s:%s", pkg.Name, test.Name)) + } + } + + logArg := "" + if verbose { + logArg = "-v" + } + var result OSRunnerResult + if len(tests) > 0 { + vars := fmt.Sprintf(`GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH" AGENT_VERSION="%s" TEST_DEFINE_PREFIX="%s" TEST_DEFINE_TESTS="%s"`, agentVersion, prefix, strings.Join(tests, ",")) + vars = extendVars(vars, env) + + script := fmt.Sprintf(`cd agent && %s ~/go/bin/mage %s integration:testOnRemote`, vars, logArg) + results, err := runTests(ctx, logger, "non-sudo", prefix, script, sshClient, batch.Tests) + if err != nil { + return OSRunnerResult{}, fmt.Errorf("error running non-sudo tests: %w", err) + } + result.Packages = results + } + + if len(sudoTests) > 0 { + prefix := fmt.Sprintf("%s-sudo", prefix) + vars := fmt.Sprintf(`GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH:/usr/sbin" AGENT_VERSION="%s" TEST_DEFINE_PREFIX="%s" TEST_DEFINE_TESTS="%s"`, agentVersion, prefix, strings.Join(sudoTests, ",")) + vars = extendVars(vars, env) + script := fmt.Sprintf(`cd agent && sudo %s ~/go/bin/mage %s integration:testOnRemote`, vars, logArg) + + results, err := runTests(ctx, logger, "sudo", prefix, script, sshClient, batch.SudoTests) + if err != nil { + return OSRunnerResult{}, fmt.Errorf("error running sudo tests: %w", err) + } + result.SudoPackages = results + } + + return result, nil +} + +// Diagnostics gathers any diagnostics from the host. +func (SlesRunner) Diagnostics(ctx context.Context, sshClient SSHClient, logger Logger, destination string) error { + return linuxDiagnostics(ctx, sshClient, logger, destination) +} diff --git a/pkg/testing/runner/ssh.go b/pkg/testing/runner/ssh.go index ebb9fcd96da..7e42ffacf1a 100644 --- a/pkg/testing/runner/ssh.go +++ b/pkg/testing/runner/ssh.go @@ -110,22 +110,36 @@ type sshClient struct { ip string username string auth ssh.AuthMethod - - c *ssh.Client + logger Logger + c *ssh.Client } // NewSSHClient creates a new SSH client connection to the host. -func NewSSHClient(ip string, username string, sshAuth ssh.AuthMethod) SSHClient { +func NewSSHClient(ip string, username string, sshAuth ssh.AuthMethod, logger Logger) SSHClient { return &sshClient{ ip: ip, username: username, auth: sshAuth, + logger: logger, } } // Connect connects to the host. func (s *sshClient) Connect(ctx context.Context) error { var lastErr error + config := &ssh.ClientConfig{ + User: s.username, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), //nolint:gosec // it's the tests framework test + Auth: []ssh.AuthMethod{s.auth}, + Timeout: 30 * time.Second, + } + addr := net.JoinHostPort(s.ip, "22") + + tcpAddr, err := net.ResolveTCPAddr("tcp", addr) + if err != nil { + return fmt.Errorf("unable to resolve ssh address %q :%w", addr, err) + } + delay := 1 * time.Second for { if ctx.Err() != nil { if lastErr == nil { @@ -133,18 +147,37 @@ func (s *sshClient) Connect(ctx context.Context) error { } return lastErr } - config := &ssh.ClientConfig{ - User: s.username, - HostKeyCallback: ssh.InsecureIgnoreHostKey(), //nolint:gosec // it's the tests framework test - Auth: []ssh.AuthMethod{s.auth}, - Timeout: 30 * time.Second, + if lastErr != nil { + s.logger.Logf("ssh connect error: %q, will try again in %s", lastErr, delay) + time.Sleep(delay) + delay = 2 * delay + } - client, err := ssh.Dial("tcp", net.JoinHostPort(s.ip, "22"), config) - if err == nil { - s.c = client - return nil + conn, err := net.DialTCP("tcp", nil, tcpAddr) + if err != nil { + lastErr = fmt.Errorf("error dialing tcp address %q :%w", addr, err) + continue } - lastErr = err + err = conn.SetKeepAlive(true) + if err != nil { + _ = conn.Close() + lastErr = fmt.Errorf("error setting TCP keepalive for ssh to %q :%w", addr, err) + continue + } + err = conn.SetKeepAlivePeriod(config.Timeout) + if err != nil { + _ = conn.Close() + lastErr = fmt.Errorf("error setting TCP keepalive period for ssh to %q :%w", addr, err) + continue + } + sshConn, chans, reqs, err := ssh.NewClientConn(conn, addr, config) + if err != nil { + _ = conn.Close() + lastErr = fmt.Errorf("error NewClientConn for ssh to %q :%w", addr, err) + continue + } + s.c = ssh.NewClient(sshConn, chans, reqs) + return nil } } @@ -189,12 +222,21 @@ func (s *sshClient) Exec(ctx context.Context, cmd string, args []string, stdin i return nil, nil, ctx.Err() } + var session *ssh.Session cmdArgs := []string{cmd} cmdArgs = append(cmdArgs, args...) cmdStr := strings.Join(cmdArgs, " ") session, err := s.NewSession() if err != nil { - return nil, nil, fmt.Errorf("could not create new SSH session: %w", err) + s.logger.Logf("new session failed: %q, trying reconnect", err) + lErr := s.Reconnect(ctx) + if lErr != nil { + return nil, nil, fmt.Errorf("ssh reconnect failed: %w, after new session failed: %w", lErr, err) + } + session, lErr = s.NewSession() + if lErr != nil { + return nil, nil, fmt.Errorf("new session failed after reconnect: %w, original new session failure was: %w", lErr, err) + } } defer session.Close() @@ -225,6 +267,7 @@ func (s *sshClient) ExecWithRetry(ctx context.Context, cmd string, args []string if err == nil { return stdout, stderr, nil } + s.logger.Logf("ssh exec error: %q, will try again in %s", err, interval) lastErr = err lastStdout = stdout lastStderr = stderr diff --git a/pkg/testing/runner/supported.go b/pkg/testing/runner/supported.go index e08814f4187..b86acfd2c19 100644 --- a/pkg/testing/runner/supported.go +++ b/pkg/testing/runner/supported.go @@ -12,6 +12,8 @@ import ( ) const ( + Rhel = "rhel" + Sles = "sles" // Ubuntu is a Linux distro. Ubuntu = "ubuntu" ) @@ -70,6 +72,26 @@ var ( }, Runner: DebianRunner{}, } + // RhelAMD64_8 - RedHat Enterprise Linux (amd64) 8 + RhelAMD64_8 = SupportedOS{ + OS: define.OS{ + Type: define.Linux, + Arch: define.AMD64, + Distro: Rhel, + Version: "8", + }, + Runner: RhelRunner{}, + } + // SlesAMD64_15 - SUSE Linux Enterprise Server (amd64) 15 + SlesAMD64_15 = SupportedOS{ + OS: define.OS{ + Type: define.Linux, + Arch: define.AMD64, + Distro: Sles, + Version: "15", + }, + Runner: SlesRunner{}, + } // WindowsAMD64_2022 - Windows (amd64) Server 2022 WindowsAMD64_2022 = SupportedOS{ OS: define.OS{ @@ -139,6 +161,8 @@ var supported = []SupportedOS{ UbuntuAMD64_2004, UbuntuARM64_2204, UbuntuARM64_2004, + RhelAMD64_8, + SlesAMD64_15, WindowsAMD64_2022, WindowsAMD64_2022_Core, WindowsAMD64_2019, diff --git a/pkg/testing/runner/supported_test.go b/pkg/testing/runner/supported_test.go index f1df343a70c..d7a29dda5bd 100644 --- a/pkg/testing/runner/supported_test.go +++ b/pkg/testing/runner/supported_test.go @@ -32,8 +32,9 @@ func TestGetSupported(t *testing.T) { { Name: "ubuntu/not specific", OS: define.OS{ - Type: define.Linux, - Arch: define.AMD64, + Type: define.Linux, + Arch: define.AMD64, + Distro: Ubuntu, }, Results: []SupportedOS{ UbuntuAMD64_2204, @@ -77,6 +78,29 @@ func TestGetSupported(t *testing.T) { UbuntuAMD64_2004, }, }, + { + Name: "sles/not specific", + OS: define.OS{ + Type: define.Linux, + Arch: define.AMD64, + Distro: Sles, + }, + Results: []SupportedOS{ + SlesAMD64_15, + }, + }, + { + Name: "sles/specific", + OS: define.OS{ + Type: define.Linux, + Arch: define.AMD64, + Distro: Sles, + Version: "15", + }, + Results: []SupportedOS{ + SlesAMD64_15, + }, + }, } for _, scenario := range scenarios { t.Run(scenario.Name, func(t *testing.T) { diff --git a/testing/integration/groups_test.go b/testing/integration/groups_test.go index 2c0f38b7e53..b4bb4500dad 100644 --- a/testing/integration/groups_test.go +++ b/testing/integration/groups_test.go @@ -33,4 +33,7 @@ const ( // Deb group of tests. Used for testing .deb packages install & upgrades Deb = "deb" + + // RPM group of tests. Used for testing .rpm packages install & upgrades + RPM = "rpm" ) diff --git a/testing/integration/logs_ingestion_test.go b/testing/integration/logs_ingestion_test.go index 5a31b21d95c..1e26da8516c 100644 --- a/testing/integration/logs_ingestion_test.go +++ b/testing/integration/logs_ingestion_test.go @@ -125,7 +125,75 @@ func TestDebLogIngestFleetManaged(t *testing.T) { // name. This policy does not contain any integration. t.Log("Enrolling agent in Fleet with a test policy") createPolicyReq := kibana.AgentPolicy{ - Name: fmt.Sprintf("test-policy-enroll-%d", time.Now().Unix()), + Name: fmt.Sprintf("test-policy-enroll-%s", uuid.New().String()), + Namespace: info.Namespace, + Description: "test policy for agent enrollment", + MonitoringEnabled: []kibana.MonitoringEnabledOption{ + kibana.MonitoringEnabledLogs, + kibana.MonitoringEnabledMetrics, + }, + AgentFeatures: []map[string]interface{}{ + { + "name": "test_enroll", + "enabled": true, + }, + }, + } + + installOpts := atesting.InstallOpts{ + NonInteractive: true, + Force: true, + } + + // 2. Install the Elastic-Agent with the policy that + // was just created. + policy, err := tools.InstallAgentWithPolicy( + ctx, + t, + installOpts, + agentFixture, + info.KibanaClient, + createPolicyReq) + require.NoError(t, err) + t.Logf("created policy: %s", policy.ID) + check.ConnectedToFleet(ctx, t, agentFixture, 5*time.Minute) + + t.Run("Monitoring logs are shipped", func(t *testing.T) { + testMonitoringLogsAreShipped(t, ctx, info, agentFixture, policy) + }) + + t.Run("Normal logs with flattened data_stream are shipped", func(t *testing.T) { + testFlattenedDatastreamFleetPolicy(t, ctx, info, policy) + }) +} + +func TestRpmLogIngestFleetManaged(t *testing.T) { + info := define.Require(t, define.Requirements{ + Group: RPM, + Stack: &define.Stack{}, + OS: []define.OS{ + { + Type: define.Linux, + Distro: "rhel", + }, + }, + Local: false, + Sudo: true, + }) + + ctx, cancel := testcontext.WithDeadline(t, context.Background(), time.Now().Add(10*time.Minute)) + defer cancel() + + agentFixture, err := define.NewFixture(t, define.Version(), atesting.WithPackageFormat("rpm")) + require.NoError(t, err) + + // 1. Create a policy in Fleet with monitoring enabled. + // To ensure there are no conflicts with previous test runs against + // the same ESS stack, we add the current time at the end of the policy + // name. This policy does not contain any integration. + t.Log("Enrolling agent in Fleet with a test policy") + createPolicyReq := kibana.AgentPolicy{ + Name: fmt.Sprintf("test-policy-enroll-%s", uuid.New().String()), Namespace: info.Namespace, Description: "test policy for agent enrollment", MonitoringEnabled: []kibana.MonitoringEnabledOption{ From 1682be0f9db782e5277e3827d6fd2417974fa239 Mon Sep 17 00:00:00 2001 From: "Lee E. Hinman" Date: Wed, 3 Apr 2024 12:32:17 -0500 Subject: [PATCH 2/2] remove sles --- pkg/testing/ogc/supported.go | 13 ---- pkg/testing/runner/sles.go | 112 --------------------------- pkg/testing/runner/supported.go | 12 --- pkg/testing/runner/supported_test.go | 14 ++-- 4 files changed, 7 insertions(+), 144 deletions(-) delete mode 100644 pkg/testing/runner/sles.go diff --git a/pkg/testing/ogc/supported.go b/pkg/testing/ogc/supported.go index ec4074dc0e2..96bbc5cf520 100644 --- a/pkg/testing/ogc/supported.go +++ b/pkg/testing/ogc/supported.go @@ -72,19 +72,6 @@ var ogcSupported = []LayoutOS{ Username: "ubuntu", RemotePath: "/home/ubuntu/agent", }, - { - OS: define.OS{ - Type: define.Linux, - Arch: define.AMD64, - Distro: runner.Sles, - Version: "15", - }, - Provider: Google, - InstanceSize: "e2-standard-2", // 2 amd64 cpus - RunsOn: "sles-15", - Username: "sles", - RemotePath: "/home/sles/agent", - }, { OS: define.OS{ Type: define.Linux, diff --git a/pkg/testing/runner/sles.go b/pkg/testing/runner/sles.go deleted file mode 100644 index ac634f6c50a..00000000000 --- a/pkg/testing/runner/sles.go +++ /dev/null @@ -1,112 +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 runner - -import ( - "context" - "fmt" - "path" - "strings" - "time" - - "github.com/elastic/elastic-agent/pkg/testing/define" -) - -// SlesRunner is a handler for running tests on SUSE Linux Enterpriser Server -type SlesRunner struct{} - -// Prepare configures the host for running the test -func (SlesRunner) Prepare(ctx context.Context, sshClient SSHClient, logger Logger, arch string, goVersion string) error { - logger.Logf("install devel_basis") - zypperCtx, zypperCancel := context.WithTimeout(ctx, 20*time.Minute) - defer zypperCancel() - stdOut, errOut, err := sshClient.ExecWithRetry(zypperCtx, "sudo", []string{"zypper", "install", "-y ", "-t", "pattern", "devel_basis"}, 15*time.Second) - if err != nil { - return fmt.Errorf("failed to run zypper install devel_basis: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) - } - - // install golang - logger.Logf("Install golang %s (%s)", goVersion, arch) - goCtx, goCancel := context.WithTimeout(ctx, 20*time.Minute) - defer goCancel() - downloadURL := fmt.Sprintf("https://go.dev/dl/go%s.linux-%s.tar.gz", goVersion, arch) - filename := path.Base(downloadURL) - stdOut, errOut, err = sshClient.Exec(goCtx, "curl", []string{"-Ls", downloadURL, "--output", filename}, nil) - if err != nil { - return fmt.Errorf("failed to download go from %s with curl: %w (stdout: %s, stderr: %s)", downloadURL, err, stdOut, errOut) - } - stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"tar", "-C", "/usr/local", "-xzf", filename}, nil) - if err != nil { - return fmt.Errorf("failed to extract go to /usr/local with tar: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) - } - stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"ln", "-s", "/usr/local/go/bin/go", "/usr/bin/go"}, nil) - if err != nil { - return fmt.Errorf("failed to symlink /usr/local/go/bin/go to /usr/bin/go: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) - } - stdOut, errOut, err = sshClient.Exec(goCtx, "sudo", []string{"ln", "-s", "/usr/local/go/bin/gofmt", "/usr/bin/gofmt"}, nil) - if err != nil { - return fmt.Errorf("failed to symlink /usr/local/go/bin/gofmt to /usr/bin/gofmt: %w (stdout: %s, stderr: %s)", err, stdOut, errOut) - } - - return nil -} - -// Copy places the required files on the host -func (SlesRunner) Copy(ctx context.Context, sshClient SSHClient, logger Logger, repoArchive string, builds []Build) error { - return linuxCopy(ctx, sshClient, logger, repoArchive, builds) -} - -// Run the test -func (SlesRunner) Run(ctx context.Context, verbose bool, sshClient SSHClient, logger Logger, agentVersion string, prefix string, batch define.Batch, env map[string]string) (OSRunnerResult, error) { - var tests []string - for _, pkg := range batch.Tests { - for _, test := range pkg.Tests { - tests = append(tests, fmt.Sprintf("%s:%s", pkg.Name, test.Name)) - } - } - var sudoTests []string - for _, pkg := range batch.SudoTests { - for _, test := range pkg.Tests { - sudoTests = append(sudoTests, fmt.Sprintf("%s:%s", pkg.Name, test.Name)) - } - } - - logArg := "" - if verbose { - logArg = "-v" - } - var result OSRunnerResult - if len(tests) > 0 { - vars := fmt.Sprintf(`GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH" AGENT_VERSION="%s" TEST_DEFINE_PREFIX="%s" TEST_DEFINE_TESTS="%s"`, agentVersion, prefix, strings.Join(tests, ",")) - vars = extendVars(vars, env) - - script := fmt.Sprintf(`cd agent && %s ~/go/bin/mage %s integration:testOnRemote`, vars, logArg) - results, err := runTests(ctx, logger, "non-sudo", prefix, script, sshClient, batch.Tests) - if err != nil { - return OSRunnerResult{}, fmt.Errorf("error running non-sudo tests: %w", err) - } - result.Packages = results - } - - if len(sudoTests) > 0 { - prefix := fmt.Sprintf("%s-sudo", prefix) - vars := fmt.Sprintf(`GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH:/usr/sbin" AGENT_VERSION="%s" TEST_DEFINE_PREFIX="%s" TEST_DEFINE_TESTS="%s"`, agentVersion, prefix, strings.Join(sudoTests, ",")) - vars = extendVars(vars, env) - script := fmt.Sprintf(`cd agent && sudo %s ~/go/bin/mage %s integration:testOnRemote`, vars, logArg) - - results, err := runTests(ctx, logger, "sudo", prefix, script, sshClient, batch.SudoTests) - if err != nil { - return OSRunnerResult{}, fmt.Errorf("error running sudo tests: %w", err) - } - result.SudoPackages = results - } - - return result, nil -} - -// Diagnostics gathers any diagnostics from the host. -func (SlesRunner) Diagnostics(ctx context.Context, sshClient SSHClient, logger Logger, destination string) error { - return linuxDiagnostics(ctx, sshClient, logger, destination) -} diff --git a/pkg/testing/runner/supported.go b/pkg/testing/runner/supported.go index b86acfd2c19..c872066167c 100644 --- a/pkg/testing/runner/supported.go +++ b/pkg/testing/runner/supported.go @@ -13,7 +13,6 @@ import ( const ( Rhel = "rhel" - Sles = "sles" // Ubuntu is a Linux distro. Ubuntu = "ubuntu" ) @@ -82,16 +81,6 @@ var ( }, Runner: RhelRunner{}, } - // SlesAMD64_15 - SUSE Linux Enterprise Server (amd64) 15 - SlesAMD64_15 = SupportedOS{ - OS: define.OS{ - Type: define.Linux, - Arch: define.AMD64, - Distro: Sles, - Version: "15", - }, - Runner: SlesRunner{}, - } // WindowsAMD64_2022 - Windows (amd64) Server 2022 WindowsAMD64_2022 = SupportedOS{ OS: define.OS{ @@ -162,7 +151,6 @@ var supported = []SupportedOS{ UbuntuARM64_2204, UbuntuARM64_2004, RhelAMD64_8, - SlesAMD64_15, WindowsAMD64_2022, WindowsAMD64_2022_Core, WindowsAMD64_2019, diff --git a/pkg/testing/runner/supported_test.go b/pkg/testing/runner/supported_test.go index d7a29dda5bd..84ca2516a60 100644 --- a/pkg/testing/runner/supported_test.go +++ b/pkg/testing/runner/supported_test.go @@ -79,26 +79,26 @@ func TestGetSupported(t *testing.T) { }, }, { - Name: "sles/not specific", + Name: "rhel/not specific", OS: define.OS{ Type: define.Linux, Arch: define.AMD64, - Distro: Sles, + Distro: Rhel, }, Results: []SupportedOS{ - SlesAMD64_15, + RhelAMD64_8, }, }, { - Name: "sles/specific", + Name: "rhel/specific", OS: define.OS{ Type: define.Linux, Arch: define.AMD64, - Distro: Sles, - Version: "15", + Distro: Rhel, + Version: "8", }, Results: []SupportedOS{ - SlesAMD64_15, + RhelAMD64_8, }, }, }