Skip to content

Commit 1921306

Browse files
authored
add SLES as supported platform (#4461)
1 parent 02c4118 commit 1921306

10 files changed

+480
-140
lines changed

pkg/testing/fixture.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ func (f *Fixture) binaryPath() string {
837837
workDir = filepath.Join(paths.DefaultBasePath, "Elastic", "Agent")
838838
}
839839
}
840-
if f.packageFormat == "deb" {
840+
if f.packageFormat == "deb" || f.packageFormat == "rpm" {
841841
workDir = "/usr/bin"
842842
}
843843
defaultBin := "elastic-agent"

pkg/testing/fixture_install.go

+92
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..
138138
return f.installNoPkgManager(ctx, installOpts, opts)
139139
case "deb":
140140
return f.installDeb(ctx, installOpts, opts)
141+
case "rpm":
142+
return f.installRpm(ctx, installOpts, opts)
141143
default:
142144
return nil, fmt.Errorf("package format %s isn't supported yet", f.packageFormat)
143145
}
@@ -435,6 +437,81 @@ func (f *Fixture) installDeb(ctx context.Context, installOpts *InstallOpts, opts
435437
return nil, nil
436438
}
437439

440+
// installRpm installs the prepared Elastic Agent binary from the rpm
441+
// package and registers a t.Cleanup function to uninstall the agent if
442+
// it hasn't been uninstalled. It also takes care of collecting a
443+
// diagnostics when AGENT_COLLECT_DIAG=true or the test has failed.
444+
// It returns:
445+
// - the combined output of Install command stdout and stderr
446+
// - an error if any.
447+
func (f *Fixture) installRpm(ctx context.Context, installOpts *InstallOpts, opts []process.CmdOption) ([]byte, error) {
448+
f.t.Logf("[test %s] Inside fixture installRpm function", f.t.Name())
449+
//Prepare so that the f.srcPackage string is populated
450+
err := f.EnsurePrepared(ctx)
451+
if err != nil {
452+
return nil, fmt.Errorf("failed to prepare: %w", err)
453+
}
454+
455+
// sudo rpm -iv elastic-agent rpm
456+
out, err := exec.CommandContext(ctx, "sudo", "rpm", "-i", "-v", f.srcPackage).CombinedOutput() // #nosec G204 -- Need to pass in name of package
457+
if err != nil {
458+
return out, fmt.Errorf("rpm install failed: %w output:%s", err, string(out))
459+
}
460+
461+
f.t.Cleanup(func() {
462+
f.t.Logf("[test %s] Inside fixture installRpm cleanup function", f.t.Name())
463+
uninstallCtx, uninstallCancel := context.WithTimeout(context.Background(), 5*time.Minute)
464+
defer uninstallCancel()
465+
// stop elastic-agent, non fatal if error, might have been stopped before this.
466+
f.t.Logf("running 'sudo systemctl stop elastic-agent'")
467+
out, err := exec.CommandContext(uninstallCtx, "sudo", "systemctl", "stop", "elastic-agent").CombinedOutput()
468+
if err != nil {
469+
f.t.Logf("error systemctl stop elastic-agent: %s, output: %s", err, string(out))
470+
}
471+
// rpm -e elastic-agent rpm
472+
f.t.Logf("running 'sudo rpm -e elastic-agent'")
473+
out, err = exec.CommandContext(uninstallCtx, "sudo", "rpm", "-e", "elastic-agent").CombinedOutput()
474+
if err != nil {
475+
f.t.Logf("failed to 'sudo rpm -e elastic-agent': %s, output: %s", err, string(out))
476+
f.t.FailNow()
477+
}
478+
})
479+
480+
// start elastic-agent
481+
out, err = exec.CommandContext(ctx, "sudo", "systemctl", "start", "elastic-agent").CombinedOutput()
482+
if err != nil {
483+
return out, fmt.Errorf("systemctl start elastic-agent failed: %w", err)
484+
}
485+
486+
// rpm install doesn't enroll, so need to do that
487+
enrollArgs := []string{"elastic-agent", "enroll"}
488+
if installOpts.Force {
489+
enrollArgs = append(enrollArgs, "--force")
490+
}
491+
if installOpts.Insecure {
492+
enrollArgs = append(enrollArgs, "--insecure")
493+
}
494+
if installOpts.ProxyURL != "" {
495+
enrollArgs = append(enrollArgs, "--proxy-url="+installOpts.ProxyURL)
496+
}
497+
if installOpts.DelayEnroll {
498+
enrollArgs = append(enrollArgs, "--delay-enroll")
499+
}
500+
if installOpts.EnrollOpts.URL != "" {
501+
enrollArgs = append(enrollArgs, "--url", installOpts.EnrollOpts.URL)
502+
}
503+
if installOpts.EnrollOpts.EnrollmentToken != "" {
504+
enrollArgs = append(enrollArgs, "--enrollment-token", installOpts.EnrollOpts.EnrollmentToken)
505+
}
506+
// run sudo elastic-agent enroll
507+
out, err = exec.CommandContext(ctx, "sudo", enrollArgs...).CombinedOutput()
508+
if err != nil {
509+
return out, fmt.Errorf("elastic-agent enroll failed: %w, output: %s args: %v", err, string(out), enrollArgs)
510+
}
511+
512+
return nil, nil
513+
}
514+
438515
type UninstallOpts struct {
439516
Force bool // --force
440517
UninstallToken string
@@ -460,6 +537,8 @@ func (f *Fixture) Uninstall(ctx context.Context, uninstallOpts *UninstallOpts, o
460537
return f.uninstallNoPkgManager(ctx, uninstallOpts, opts)
461538
case "deb":
462539
return f.uninstallDeb(ctx, uninstallOpts, opts)
540+
case "rpm":
541+
return f.uninstallRpm(ctx, uninstallOpts, opts)
463542
default:
464543
return nil, fmt.Errorf("uninstall of package format '%s' not supported yet", f.packageFormat)
465544
}
@@ -478,6 +557,19 @@ func (f *Fixture) uninstallDeb(ctx context.Context, uninstallOpts *UninstallOpts
478557
return out, nil
479558
}
480559

560+
func (f *Fixture) uninstallRpm(ctx context.Context, uninstallOpts *UninstallOpts, opts []process.CmdOption) ([]byte, error) {
561+
// stop elastic-agent, non fatal if error, might have been stopped before this.
562+
out, err := exec.CommandContext(ctx, "sudo", "systemctl", "stop", "elastic-agent").CombinedOutput()
563+
if err != nil {
564+
f.t.Logf("error systemctl stop elastic-agent: %s, output: %s", err, string(out))
565+
}
566+
out, err = exec.CommandContext(ctx, "sudo", "rpm", "-e", "elastic-agent").CombinedOutput()
567+
if err != nil {
568+
return out, fmt.Errorf("error running 'sudo rpm -e elastic-agent': %w", err)
569+
}
570+
return out, nil
571+
}
572+
481573
func (f *Fixture) uninstallNoPkgManager(ctx context.Context, uninstallOpts *UninstallOpts, opts []process.CmdOption) ([]byte, error) {
482574
if !f.installed {
483575
return nil, ErrNotInstalled

pkg/testing/ogc/supported.go

+13
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,19 @@ var ogcSupported = []LayoutOS{
7272
Username: "ubuntu",
7373
RemotePath: "/home/ubuntu/agent",
7474
},
75+
{
76+
OS: define.OS{
77+
Type: define.Linux,
78+
Arch: define.AMD64,
79+
Distro: runner.Sles,
80+
Version: "15",
81+
},
82+
Provider: Google,
83+
InstanceSize: "e2-standard-2", // 2 amd64 cpus
84+
RunsOn: "sles-15",
85+
Username: "sles",
86+
RemotePath: "/home/sles/agent",
87+
},
7588
{
7689
OS: define.OS{
7790
Type: define.Windows,

pkg/testing/runner/debian.go

+2-136
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package runner
77
import (
88
"context"
99
"fmt"
10-
"os"
1110
"path"
1211
"path/filepath"
1312
"strings"
@@ -88,108 +87,7 @@ func (DebianRunner) Prepare(ctx context.Context, sshClient SSHClient, logger Log
8887

8988
// Copy places the required files on the host.
9089
func (DebianRunner) Copy(ctx context.Context, sshClient SSHClient, logger Logger, repoArchive string, builds []Build) error {
91-
// copy the archive and extract it on the host
92-
logger.Logf("Copying repo")
93-
destRepoName := filepath.Base(repoArchive)
94-
err := sshClient.Copy(repoArchive, destRepoName)
95-
if err != nil {
96-
return fmt.Errorf("failed to SCP repo archive %s: %w", repoArchive, err)
97-
}
98-
99-
// remove build paths, on cases where the build path is different from agent.
100-
for _, build := range builds {
101-
for _, remoteBuildPath := range []string{build.Path, build.SHA512Path} {
102-
relativeAgentDir := filepath.Join("agent", remoteBuildPath)
103-
_, _, err := sshClient.Exec(ctx, "sudo", []string{"rm", "-rf", relativeAgentDir}, nil)
104-
// doesn't need to be a fatal error.
105-
if err != nil {
106-
logger.Logf("error removing build dir %s: %w", relativeAgentDir, err)
107-
}
108-
}
109-
}
110-
111-
// ensure that agent directory is removed (possible it already exists if instance already used)
112-
stdout, stderr, err := sshClient.Exec(ctx,
113-
"sudo", []string{"rm", "-rf", "agent"}, nil)
114-
if err != nil {
115-
return fmt.Errorf(
116-
"failed to remove agent directory before unziping new one: %w. stdout: %q, stderr: %q",
117-
err, stdout, stderr)
118-
}
119-
120-
stdOut, errOut, err := sshClient.Exec(ctx, "unzip", []string{destRepoName, "-d", "agent"}, nil)
121-
if err != nil {
122-
return fmt.Errorf("failed to unzip %s to agent directory: %w (stdout: %s, stderr: %s)", destRepoName, err, stdOut, errOut)
123-
}
124-
125-
// prepare for testing
126-
logger.Logf("Running make mage and prepareOnRemote")
127-
envs := `GOPATH="$HOME/go" PATH="$HOME/go/bin:$PATH"`
128-
installMage := strings.NewReader(fmt.Sprintf(`cd agent && %s make mage && %s mage integration:prepareOnRemote`, envs, envs))
129-
stdOut, errOut, err = sshClient.Exec(ctx, "bash", nil, installMage)
130-
if err != nil {
131-
return fmt.Errorf("failed to perform make mage and prepareOnRemote: %w (stdout: %s, stderr: %s)", err, stdOut, errOut)
132-
}
133-
134-
// determine if the build needs to be replaced on the host
135-
// if it already exists and the SHA512 are the same contents, then
136-
// there is no reason to waste time uploading the build
137-
for _, build := range builds {
138-
copyBuild := true
139-
localSHA512, err := os.ReadFile(build.SHA512Path)
140-
if err != nil {
141-
return fmt.Errorf("failed to read local SHA52 contents %s: %w", build.SHA512Path, err)
142-
}
143-
hostSHA512Path := filepath.Base(build.SHA512Path)
144-
hostSHA512, err := sshClient.GetFileContents(ctx, hostSHA512Path)
145-
if err == nil {
146-
if string(localSHA512) == string(hostSHA512) {
147-
logger.Logf("Skipping copy agent build %s; already the same", filepath.Base(build.Path))
148-
copyBuild = false
149-
}
150-
}
151-
152-
if copyBuild {
153-
// ensure the existing copies are removed first
154-
toRemove := filepath.Base(build.Path)
155-
stdOut, errOut, err = sshClient.Exec(ctx,
156-
"sudo", []string{"rm", "-f", toRemove}, nil)
157-
if err != nil {
158-
return fmt.Errorf("failed to remove %q: %w (stdout: %q, stderr: %q)",
159-
toRemove, err, stdOut, errOut)
160-
}
161-
162-
toRemove = filepath.Base(build.SHA512Path)
163-
stdOut, errOut, err = sshClient.Exec(ctx,
164-
"sudo", []string{"rm", "-f", toRemove}, nil)
165-
if err != nil {
166-
return fmt.Errorf("failed to remove %q: %w (stdout: %q, stderr: %q)",
167-
toRemove, err, stdOut, errOut)
168-
}
169-
170-
logger.Logf("Copying agent build %s", filepath.Base(build.Path))
171-
}
172-
173-
for _, buildPath := range []string{build.Path, build.SHA512Path} {
174-
if copyBuild {
175-
err = sshClient.Copy(buildPath, filepath.Base(buildPath))
176-
if err != nil {
177-
return fmt.Errorf("failed to SCP build %s: %w", filepath.Base(buildPath), err)
178-
}
179-
}
180-
insideAgentDir := filepath.Join("agent", buildPath)
181-
stdOut, errOut, err = sshClient.Exec(ctx, "mkdir", []string{"-p", filepath.Dir(insideAgentDir)}, nil)
182-
if err != nil {
183-
return fmt.Errorf("failed to create %s directory: %w (stdout: %s, stderr: %s)", filepath.Dir(insideAgentDir), err, stdOut, errOut)
184-
}
185-
stdOut, errOut, err = sshClient.Exec(ctx, "ln", []string{filepath.Base(buildPath), insideAgentDir}, nil)
186-
if err != nil {
187-
return fmt.Errorf("failed to hard link %s to %s: %w (stdout: %s, stderr: %s)", filepath.Base(buildPath), insideAgentDir, err, stdOut, errOut)
188-
}
189-
}
190-
}
191-
192-
return nil
90+
return linuxCopy(ctx, sshClient, logger, repoArchive, builds)
19391
}
19492

19593
// Run the test
@@ -242,39 +140,7 @@ func (DebianRunner) Run(ctx context.Context, verbose bool, sshClient SSHClient,
242140

243141
// Diagnostics gathers any diagnostics from the host.
244142
func (DebianRunner) Diagnostics(ctx context.Context, sshClient SSHClient, logger Logger, destination string) error {
245-
// take ownership, as sudo tests will create with root permissions (allow to fail in the case it doesn't exist)
246-
diagnosticDir := "$HOME/agent/build/diagnostics"
247-
_, _, _ = sshClient.Exec(ctx, "sudo", []string{"chown", "-R", "$USER:$USER", diagnosticDir}, nil)
248-
stdOut, _, err := sshClient.Exec(ctx, "ls", []string{"-1", diagnosticDir}, nil)
249-
if err != nil {
250-
//nolint:nilerr // failed to list the directory, probably don't have any diagnostics (do nothing)
251-
return nil
252-
}
253-
eachDiagnostic := strings.Split(string(stdOut), "\n")
254-
for _, filename := range eachDiagnostic {
255-
filename = strings.TrimSpace(filename)
256-
if filename == "" {
257-
continue
258-
}
259-
260-
// don't use filepath.Join as we need this to work in Windows as well
261-
// this is because if we use `filepath.Join` on a Windows host connected to a Linux host
262-
// it will use a `\` and that will be incorrect for Linux
263-
fp := fmt.Sprintf("%s/%s", diagnosticDir, filename)
264-
// use filepath.Join on this path because it's a path on this specific host platform
265-
dp := filepath.Join(destination, filename)
266-
logger.Logf("Copying diagnostic %s", filename)
267-
out, err := os.Create(dp)
268-
if err != nil {
269-
return fmt.Errorf("failed to create file %s: %w", dp, err)
270-
}
271-
err = sshClient.GetFileContentsOutput(ctx, fp, out)
272-
_ = out.Close()
273-
if err != nil {
274-
return fmt.Errorf("failed to copy file from remote host to %s: %w", dp, err)
275-
}
276-
}
277-
return nil
143+
return linuxDiagnostics(ctx, sshClient, logger, destination)
278144
}
279145

280146
func runTests(ctx context.Context, logger Logger, name string, prefix string, script string, sshClient SSHClient, tests []define.BatchPackageTests) ([]OSRunnerPackageResult, error) {

0 commit comments

Comments
 (0)