Skip to content

Commit 815c264

Browse files
[deb/rpm] copy run folder from old agent installation (#7999)
* fix: copy run folder from old agent installation * fix: add debian OS support in deb related integration tests * doc: add changelog fragment * fix: deduplicate similar code and improve code readability * fix: typo * fix: preserve mode,ownership,timestamps during cp
1 parent 9c8280e commit 815c264

File tree

6 files changed

+101
-5
lines changed

6 files changed

+101
-5
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: bug-fix
2+
summary: Preserve agent run state on DEB and RPM upgrades
3+
component: "elastic-agent"
4+
pr: https://github.com/elastic/elastic-agent/pull/7999
5+
issue: https://github.com/elastic/elastic-agent/issues/3832

dev-tools/packaging/templates/linux/preinstall.sh.tmpl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,23 @@ if test -L "$symlink"; then
4141
else
4242
echo "didn't find $enc_path"
4343
fi
44+
45+
old_run_path="$old_agent_dir/run"
46+
new_run_path="$new_agent_dir/run"
47+
if [ -d "$old_run_path" ]; then
48+
echo "found $old_run_path, copy to $new_agent_dir"
49+
mkdir -p "$new_run_path"
50+
cp -rfp "$old_run_path/." "$new_run_path/"
51+
else
52+
echo "didn't find $old_run_path"
53+
fi
4454
fi
4555
else
4656
echo "no previous installation found"
4757

4858
# create dir in case it does not exist
49-
mkdir -p "$new_agent_dir"
50-
59+
mkdir -p "$new_agent_dir"
60+
5161
# 2 is upgrade for Fedora, do not upgrade file when upgrading and file exists
5262
if [[ "$1" != "2" ]]; then
5363
if [[ -n "${ELASTIC_AGENT_FLAVOR}" ]]; then

pkg/testing/fixture.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,8 +1245,8 @@ func getCacheDir(caller string, name string) (string, error) {
12451245
return cacheDir, nil
12461246
}
12471247

1248-
// FindComponentsDir identifies the directory that holds the components.
1249-
func FindComponentsDir(dir, version string) (string, error) {
1248+
// findAgentDataVersionDir identifies the directory that holds the agent data of the given version.
1249+
func findAgentDataVersionDir(dir, version string) (string, error) {
12501250
dataDir := filepath.Join(dir, "data")
12511251
agentVersions, err := os.ReadDir(dataDir)
12521252
if err != nil {
@@ -1256,6 +1256,7 @@ func FindComponentsDir(dir, version string) (string, error) {
12561256
for _, fi := range agentVersions {
12571257
filename := fi.Name()
12581258
if strings.HasPrefix(filename, "elastic-agent-") && fi.IsDir() {
1259+
// Below we exclude the hash suffix (7 characters) of the directory to check the version
12591260
if version != "" && filename[:len(filename)-7] != "elastic-agent-"+version {
12601261
// version specified but version mismatch. in case of upgrade we have multiple
12611262
// directories, we don't want first found
@@ -1268,14 +1269,44 @@ func FindComponentsDir(dir, version string) (string, error) {
12681269
if versionDir == "" {
12691270
return "", fmt.Errorf("failed to find versioned directory for version %q", version)
12701271
}
1271-
componentsDir := filepath.Join(dataDir, versionDir, "components")
1272+
return filepath.Join(dataDir, versionDir), nil
1273+
}
1274+
1275+
// FindComponentsDir identifies the directory that holds the components.
1276+
func FindComponentsDir(dir, version string) (string, error) {
1277+
versionDir, err := findAgentDataVersionDir(dir, version)
1278+
if err != nil {
1279+
return "", err
1280+
}
1281+
componentsDir := filepath.Join(versionDir, "components")
12721282
fi, err := os.Stat(componentsDir)
12731283
if (err != nil && !os.IsExist(err)) || !fi.IsDir() {
12741284
return "", fmt.Errorf("failed to find components directory at %s: %w", componentsDir, err)
12751285
}
12761286
return componentsDir, nil
12771287
}
12781288

1289+
// FindRunDir identifies the directory that holds the run folder.
1290+
func FindRunDir(fixture *Fixture) (string, error) {
1291+
agentWorkDir := fixture.WorkDir()
1292+
if pf := fixture.PackageFormat(); pf == "deb" || pf == "rpm" {
1293+
// these are hardcoded paths in packages.yml
1294+
agentWorkDir = "/var/lib/elastic-agent"
1295+
}
1296+
1297+
version := fixture.Version()
1298+
versionDir, err := findAgentDataVersionDir(agentWorkDir, version)
1299+
if err != nil {
1300+
return "", err
1301+
}
1302+
runDir := filepath.Join(versionDir, "run")
1303+
fi, err := os.Stat(runDir)
1304+
if (err != nil && !os.IsExist(err)) || !fi.IsDir() {
1305+
return "", fmt.Errorf("failed to find run directory at %s: %w", runDir, err)
1306+
}
1307+
return runDir, nil
1308+
}
1309+
12791310
// writeSpecFile writes the specification to a specification file at the defined destination.
12801311
func writeSpecFile(dest string, spec *component.Spec) error {
12811312
data, err := yaml.Marshal(spec)

testing/integration/linux_deb_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ package integration
99
import (
1010
"context"
1111
"fmt"
12+
"os"
1213
"os/exec"
14+
"path/filepath"
1315
"strings"
1416
"testing"
1517
"time"
@@ -39,6 +41,10 @@ func TestDebLogIngestFleetManaged(t *testing.T) {
3941
Type: define.Linux,
4042
Distro: "ubuntu",
4143
},
44+
{
45+
Type: define.Linux,
46+
Distro: "debian",
47+
},
4248
},
4349
Local: false,
4450
Sudo: true,
@@ -83,6 +89,10 @@ func TestDebInstallsServers(t *testing.T) {
8389
Type: define.Linux,
8490
Distro: "ubuntu",
8591
},
92+
{
93+
Type: define.Linux,
94+
Distro: "debian",
95+
},
8696
},
8797
Local: false,
8898
Sudo: true,
@@ -175,6 +185,10 @@ func TestDebFleetUpgrade(t *testing.T) {
175185
Type: define.Linux,
176186
Distro: "ubuntu",
177187
},
188+
{
189+
Type: define.Linux,
190+
Distro: "debian",
191+
},
178192
},
179193
Local: false,
180194
Sudo: true,
@@ -264,6 +278,15 @@ func testDebUpgrade(t *testing.T, upgradeFromVersion *version.ParsedSemVer, info
264278

265279
check.ConnectedToFleet(ctx, t, startFixture, 5*time.Minute)
266280

281+
const migrationMarkerFile = "migration_marker.file"
282+
runDir, err := atesting.FindRunDir(startFixture)
283+
require.NoError(t, err, "failed at getting run dir")
284+
285+
runMigrationMarker := filepath.Join(runDir, migrationMarkerFile)
286+
f, err := os.Create(runMigrationMarker)
287+
require.NoErrorf(t, err, "failed to create %q file", runMigrationMarker)
288+
_ = f.Close()
289+
267290
// 3. Upgrade deb to the build version
268291
srcPackage, err := endFixture.SrcPackage(ctx)
269292
require.NoError(t, err)
@@ -272,6 +295,12 @@ func testDebUpgrade(t *testing.T, upgradeFromVersion *version.ParsedSemVer, info
272295
out, err := cmd.CombinedOutput() // #nosec G204 -- Need to pass in name of package
273296
require.NoError(t, err, string(out))
274297

298+
newRunDir, err := atesting.FindRunDir(endFixture)
299+
require.NoError(t, err, "failed at getting run dir")
300+
require.NotEqual(t, runDir, newRunDir, "the run dirs from upgrade should not match")
301+
newRunMigrationMarker := filepath.Join(newRunDir, migrationMarkerFile)
302+
require.FileExistsf(t, newRunMigrationMarker, "%q is missing", newRunMigrationMarker)
303+
275304
// 4. Wait for version in Fleet to match
276305
// Fleet will not include the `-SNAPSHOT` in the `GetAgentVersion` result
277306
noSnapshotVersion := strings.TrimSuffix(define.Version(), "-SNAPSHOT")

testing/integration/linux_rpm_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ package integration
99
import (
1010
"context"
1111
"fmt"
12+
"os"
1213
"os/exec"
14+
"path/filepath"
1315
"strings"
1416
"testing"
1517
"time"
@@ -264,12 +266,27 @@ func testRpmUpgrade(t *testing.T, upgradeFromVersion *version.ParsedSemVer, info
264266

265267
check.ConnectedToFleet(ctx, t, startFixture, 5*time.Minute)
266268

269+
const migrationMarkerFile = "migration_marker.file"
270+
runDir, err := atesting.FindRunDir(startFixture)
271+
require.NoError(t, err, "failed at getting run dir")
272+
273+
runMigrationMarker := filepath.Join(runDir, migrationMarkerFile)
274+
f, err := os.Create(runMigrationMarker)
275+
require.NoErrorf(t, err, "failed to create %q file", runMigrationMarker)
276+
_ = f.Close()
277+
267278
// 3. Upgrade rpm to the build version
268279
srcPackage, err := endFixture.SrcPackage(ctx)
269280
require.NoError(t, err)
270281
out, err := exec.CommandContext(ctx, "sudo", "rpm", "-U", "-v", srcPackage).CombinedOutput() // #nosec G204 -- Need to pass in name of package
271282
require.NoError(t, err, string(out))
272283

284+
newRunDir, err := atesting.FindRunDir(endFixture)
285+
require.NoError(t, err, "failed at getting run dir")
286+
require.NotEqual(t, runDir, newRunDir, "the run dirs from upgrade should not match")
287+
newRunMigrationMarker := filepath.Join(newRunDir, migrationMarkerFile)
288+
require.FileExistsf(t, newRunMigrationMarker, "%q is missing", newRunMigrationMarker)
289+
273290
// 4. Wait for version in Fleet to match
274291
// Fleet will not include the `-SNAPSHOT` in the `GetAgentVersion` result
275292
noSnapshotVersion := strings.TrimSuffix(define.Version(), "-SNAPSHOT")

testing/integration/restrict_upgrade_deb_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func TestRestrictUpgradeDeb(t *testing.T) {
2828
Type: define.Linux,
2929
Distro: "ubuntu",
3030
},
31+
{
32+
Type: define.Linux,
33+
Distro: "debian",
34+
},
3135
},
3236
})
3337
t.Run("when agent is deployed via deb, a user should not be able to upgrade the agent using the cli", func(t *testing.T) {

0 commit comments

Comments
 (0)