Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

(fleet) stop the previous installer/agent version on an upgrade #32156

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/fleet/installer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,8 @@ func (i *installerImpl) promoteExperiment(ctx context.Context, pkg string) error

func (i *installerImpl) preparePackage(ctx context.Context, pkg string, _ []string) error {
switch pkg {
case packageDatadogInstaller:
return packages.PrepareInstaller(ctx)
case packageDatadogAgent:
return packages.PrepareAgent(ctx)
default:
Expand Down
40 changes: 11 additions & 29 deletions pkg/fleet/installer/packages/datadog_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

const (
agentPackage = "datadog-agent"
pathOldAgent = "/opt/datadog-agent"
agentSymlink = "/usr/bin/datadog-agent"
agentUnit = "datadog-agent.service"
traceAgentUnit = "datadog-agent-trace.service"
Expand Down Expand Up @@ -75,13 +74,18 @@ func PrepareAgent(ctx context.Context) (err error) {
span, ctx := tracer.StartSpanFromContext(ctx, "prepare_agent")
defer func() { span.Finish(tracer.WithError(err)) }()

// Check if the agent has been installed by a package manager, if yes remove it
if !oldAgentInstalled() {
return nil // Nothing to do
}
err = stopOldAgentUnits(ctx)
err = removeDebRPMPackage(ctx, "datadog-agent")
if err != nil {
return fmt.Errorf("failed to stop old agent units: %w", err)
return fmt.Errorf("failed to remove deb/rpm datadog-agent package: %w", err)
}

for _, unit := range stableUnits {
if err := stopUnit(ctx, unit); err != nil {
log.Warnf("Failed to stop %s: %s", unit, err)
}
if err := disableUnit(ctx, unit); err != nil {
log.Warnf("Failed to disable %s: %s", unit, err)
}
}
return removeDebRPMPackage(ctx, agentPackage)
}
Expand Down Expand Up @@ -197,28 +201,6 @@ func RemoveAgent(ctx context.Context) error {
return nil
}

func oldAgentInstalled() bool {
_, err := os.Stat(pathOldAgent)
return err == nil
}

func stopOldAgentUnits(ctx context.Context) error {
if !oldAgentInstalled() {
return nil
}
span, ctx := tracer.StartSpanFromContext(ctx, "remove_old_agent_units")
defer span.Finish()
for _, unit := range stableUnits {
if err := stopUnit(ctx, unit); err != nil {
return fmt.Errorf("failed to stop %s: %v", unit, err)
}
if err := disableUnit(ctx, unit); err != nil {
return fmt.Errorf("failed to disable %s: %v", unit, err)
}
}
return nil
}

func chownRecursive(path string, uid int, gid int, ignorePaths []string) error {
return filepath.Walk(path, func(p string, _ os.FileInfo, err error) error {
if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions pkg/fleet/installer/packages/datadog_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ func addDDAgentGroup(ctx context.Context) error {
return exec.CommandContext(ctx, "groupadd", "--system", "dd-agent").Run()
}

func PrepareInstaller(ctx context.Context) error {
if err := stopUnit(ctx, installerUnit); err != nil {
log.Warnf("Failed to stop unit %s: %s", installerUnit, err)
}
if err := disableUnit(ctx, installerUnit); err != nil {
log.Warnf("Failed to disable %s: %s", installerUnit, err)
}
return nil
}

// SetupInstaller installs and starts the installer systemd units
func SetupInstaller(ctx context.Context) (err error) {
defer func() {
Expand Down
64 changes: 41 additions & 23 deletions pkg/fleet/installer/packages/pkg_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,62 @@
package packages

import (
"bytes"
"context"
"errors"
"fmt"
"os/exec"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func dpkgInstalled() (bool, error) {
_, err := exec.LookPath("dpkg")
if err != nil && !errors.Is(err, exec.ErrNotFound) {
return false, err
}
return err == nil, nil
}

func rpmInstalled() (bool, error) {
_, err := exec.LookPath("rpm")
if err != nil && !errors.Is(err, exec.ErrNotFound) {
return false, err
}
return err == nil, nil
}

// removeDebRPMPackage removes a package installed via deb/rpm package manager
// It doesn't remove dependencies or purge as we want to keep existing configuration files
// and reinstall the package using the installer.
// Note: we don't run the pre/post remove scripts as we want to avoid surprises for older agent versions (like removing config)
func removeDebRPMPackage(ctx context.Context, pkg string) (err error) {
span, _ := tracer.StartSpanFromContext(ctx, "remove_deb_rpm_package")
span, _ := tracer.StartSpanFromContext(ctx, "removeDebRPMPackage")
defer func() { span.Finish(tracer.WithError(err)) }()
// Compute the right command depending on the package manager
var cmd *exec.Cmd
if _, pathErr := exec.LookPath("dpkg"); pathErr == nil {
// Doesn't fail if the package isn't installed
cmd = exec.Command("dpkg", "-r", "--no-triggers", agentPackage)
} else if _, pathErr := exec.LookPath("rpm"); pathErr == nil {
// Check if package exist, else the command will fail
pkgErr := exec.Command("rpm", "-q", agentPackage).Run()
if pkgErr == nil {
cmd = exec.Command("rpm", "-e", "--nodeps", "--noscripts", agentPackage)
}
}

if cmd == nil {
// If we can't find a package manager or the package is not installed, ignore this step

dpkgInstalled, err := dpkgInstalled()
if err != nil {
return err
}
rpmInstalled, err := rpmInstalled()
if err != nil {
return err
}
var packageInstalled bool
var removeCmd *exec.Cmd
if dpkgInstalled {
removeCmd = exec.Command("dpkg", "-r", pkg)
packageInstalled = exec.Command("dpkg", "-s", pkg).Run() == nil
}
if rpmInstalled {
removeCmd = exec.Command("rpm", "-e", pkg)
packageInstalled = exec.Command("rpm", "-q", pkg).Run() == nil
}
if !packageInstalled {
return nil
}

// Run the command
var buf bytes.Buffer
cmd.Stderr = &buf
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to uninstall deb/rpm package %s (%w): %s", pkg, err, buf.String())
out, err := removeCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to uninstall deb/rpm package %s (%w): %s", pkg, err, out)
}
return nil
}
19 changes: 15 additions & 4 deletions test/new-e2e/tests/installer/unix/package_installer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
package installer

import (
"strings"
"time"

awshost "github.com/DataDog/datadog-agent/test/new-e2e/pkg/environments/aws/host"
e2eos "github.com/DataDog/test-infra-definitions/components/os"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -107,15 +110,23 @@ func (s *packageInstallerSuite) TestUpdateInstallerOCI() {
defer s.Purge()
assert.NoError(s.T(), err)

version := s.Env().RemoteHost.MustExecute("/opt/datadog-packages/datadog-installer/stable/bin/installer/installer version")
assert.Equal(s.T(), "7.58.0-installer-0.5.1\n", version)
versionDisk := s.Env().RemoteHost.MustExecute("/opt/datadog-packages/datadog-installer/stable/bin/installer/installer version")
assert.Equal(s.T(), "7.58.0-installer-0.5.1\n", versionDisk)
assert.Eventually(s.T(), func() bool {
versionRunning, err := s.Env().RemoteHost.Execute("datadog-installer status")
return err == nil && strings.Contains(versionRunning, "7.58.0-installer-0.5.1")
}, 30*time.Second, 1*time.Second)

// Install from QA registry
err = s.RunInstallScriptWithError()
assert.NoError(s.T(), err)

version = s.Env().RemoteHost.MustExecute("/opt/datadog-packages/datadog-installer/stable/bin/installer/installer version")
assert.NotEqual(s.T(), "7.58.0-installer-0.5.1\n", version)
versionDisk = s.Env().RemoteHost.MustExecute("/opt/datadog-packages/datadog-installer/stable/bin/installer/installer version")
assert.NotEqual(s.T(), "7.58.0-installer-0.5.1\n", versionDisk)
assert.Eventually(s.T(), func() bool {
versionRunning, err := s.Env().RemoteHost.Execute("datadog-installer status")
return err == nil && !strings.Contains(versionRunning, "7.58.0-installer-0.5.1")
}, 30*time.Second, 1*time.Second)
}

func (s *packageInstallerSuite) TestInstallWithUmask() {
Expand Down
Loading