diff --git a/cmd/installer/subcommands/bootstrap/command.go b/cmd/installer/subcommands/bootstrap/command.go index 9212494a998749..a8638c5dd6efdf 100644 --- a/cmd/installer/subcommands/bootstrap/command.go +++ b/cmd/installer/subcommands/bootstrap/command.go @@ -112,30 +112,39 @@ func bootstrapFxWrapper(ctx context.Context, params *cliParams, installScriptPar ) } -func bootstrap(ctx context.Context, params *cliParams, installScriptParams *installScriptParams, config config.Component, log log.Component, _ telemetry.Component) error { - url := packageURL(config.GetString("site"), params.pkg, params.version) - if params.url != "" { - url = params.url - } - ctxCarrier := tracer.TextMapCarrier{ - tracer.DefaultTraceIDHeader: fmt.Sprint(installScriptParams.Telemetry.TraceID), - tracer.DefaultParentIDHeader: fmt.Sprint(installScriptParams.Telemetry.ParentID), - tracer.DefaultPriorityHeader: fmt.Sprint(installScriptParams.Telemetry.Priority), +func bootstrap(ctx context.Context, params *cliParams, installScriptParams *installScriptParams, config config.Component, log log.Component, _ telemetry.Component) (err error) { + var spanOptions []tracer.StartSpanOption + if installScriptParams.Telemetry.TraceID != 0 && installScriptParams.Telemetry.ParentID != 0 { + ctxCarrier := tracer.TextMapCarrier{ + tracer.DefaultTraceIDHeader: fmt.Sprint(installScriptParams.Telemetry.TraceID), + tracer.DefaultParentIDHeader: fmt.Sprint(installScriptParams.Telemetry.ParentID), + tracer.DefaultPriorityHeader: fmt.Sprint(installScriptParams.Telemetry.Priority), + } + spanCtx, err := tracer.Extract(ctxCarrier) + if err != nil { + log.Errorf("failed to extract span context from install script params: %v", err) + } + spanOptions = append(spanOptions, tracer.ChildOf(spanCtx)) } - spanCtx, err := tracer.Extract(ctxCarrier) - if err != nil { - log.Errorf("failed to extract span context from install script params: %v", err) - } - span, ctx := tracer.StartSpanFromContext(ctx, "cmd/bootstrap", tracer.ChildOf(spanCtx)) - defer span.Finish() + + span, ctx := tracer.StartSpanFromContext(ctx, "cmd/bootstrap", spanOptions...) + defer func() { span.Finish(tracer.WithError(err)) }() span.SetTag(ext.ManualKeep, true) - span.SetTag("params.url", params.url) span.SetTag("params.pkg", params.pkg) span.SetTag("params.version", params.version) span.SetTag("script_params.telemetry.trace_id", installScriptParams.Telemetry.TraceID) span.SetTag("script_params.telemetry.span_id", installScriptParams.Telemetry.ParentID) span.SetTag("script_params.features.apm_instrumentation", installScriptParams.Features.APMInstrumentation) + if params.pkg == "" && params.url == "" { + return installer.Bootstrap(ctx, config) + } + + url := packageURL(config.GetString("site"), params.pkg, params.version) + if params.url != "" { + url = params.url + } + span.SetTag("params.url", params.url) return installer.BootstrapURL(ctx, url, config) } diff --git a/cmd/installer/subcommands/purge/command.go b/cmd/installer/subcommands/purge/command.go index 34a408f02ca3fb..b8f879b65ee5e7 100644 --- a/cmd/installer/subcommands/purge/command.go +++ b/cmd/installer/subcommands/purge/command.go @@ -13,8 +13,6 @@ import ( "github.com/DataDog/datadog-agent/cmd/installer/command" "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/log/logimpl" - "github.com/DataDog/datadog-agent/comp/updater/telemetry" - "github.com/DataDog/datadog-agent/comp/updater/telemetry/telemetryimpl" "github.com/DataDog/datadog-agent/pkg/installer" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) @@ -38,11 +36,10 @@ func purgeFxWrapper() error { LogParams: logimpl.ForOneShot("INSTALLER", "info", true), }), core.Bundle(), - telemetryimpl.Module(), ) } -func purge(_ telemetry.Component) error { +func purge() error { installer.Purge() return nil } diff --git a/omnibus/package-scripts/installer-deb/postinst b/omnibus/package-scripts/installer-deb/postinst index 95cb33fa154caa..535c6a6a68dab7 100644 --- a/omnibus/package-scripts/installer-deb/postinst +++ b/omnibus/package-scripts/installer-deb/postinst @@ -7,6 +7,7 @@ readonly PACKAGES_DIR=/opt/datadog-packages readonly INSTALL_DIR=/opt/datadog-installer readonly BOOTSTRAP_INSTALLER=${INSTALL_DIR}/bin/installer/installer +readonly STABLE_INSTALLER=${PACKAGES_DIR}/datadog-installer/stable/bin/installer/installer readonly HELPER=${INSTALL_DIR}/bin/installer/helper readonly LOG_DIR=/var/log/datadog readonly PACKAGES_LOCK_DIR=/var/run/datadog-packages @@ -82,6 +83,7 @@ fi chmod 750 ${HELPER} setcap cap_setuid+ep ${HELPER} -$BOOTSTRAP_INSTALLER bootstrap --url "oci://public.ecr.aws/datadog/installer-package:latest" +$BOOTSTRAP_INSTALLER bootstrap --url "oci://public.ecr.aws/datadog/installer-package:7.54.0-devel.git.366.99b427c.pipeline.32143438-1" +$STABLE_INSTALLER bootstrap exit 0 diff --git a/omnibus/package-scripts/installer-deb/postrm b/omnibus/package-scripts/installer-deb/postrm index d513471f54b16a..936bfdf30dbf17 100644 --- a/omnibus/package-scripts/installer-deb/postrm +++ b/omnibus/package-scripts/installer-deb/postrm @@ -10,15 +10,8 @@ PACKAGES_LOCK_DIR=/var/run/datadog-packages set -e -remove_packages() -{ - echo "Removing packages installed by datadog-installer" - $INSTALL_DIR/bin/installer/installer purge -} - case "$1" in purge) - remove_packages echo "Deleting dd-agent user" deluser dd-agent --quiet deluser dd-installer --quiet @@ -31,7 +24,6 @@ case "$1" in rm -rf $PACKAGES_LOCK_DIR ;; remove) - remove_packages ;; *) ;; diff --git a/omnibus/package-scripts/installer-deb/prerm b/omnibus/package-scripts/installer-deb/prerm index 6c2c35b3d6ac7e..794bfb19949d5e 100644 --- a/omnibus/package-scripts/installer-deb/prerm +++ b/omnibus/package-scripts/installer-deb/prerm @@ -5,13 +5,10 @@ readonly INSTALL_DIR=/opt/datadog-installer -SYSTEMCTL_SKIP_SYSV=true systemctl stop datadog-installer || true -SYSTEMCTL_SKIP_SYSV=true systemctl disable datadog-installer || true - set -e case "$1" in - remove) + remove | purge) $INSTALL_DIR/bin/installer/installer purge ;; *) diff --git a/omnibus/package-scripts/installer-rpm/posttrans b/omnibus/package-scripts/installer-rpm/posttrans index 54e71f22cc124e..c0b56b46d2f0ac 100644 --- a/omnibus/package-scripts/installer-rpm/posttrans +++ b/omnibus/package-scripts/installer-rpm/posttrans @@ -2,6 +2,8 @@ readonly PACKAGES_DIR=/opt/datadog-packages readonly INSTALL_DIR=/opt/datadog-installer +readonly BOOTSTRAP_INSTALLER=${INSTALL_DIR}/bin/installer/installer +readonly STABLE_INSTALLER=${PACKAGES_DIR}/datadog-installer/stable/bin/installer/installer readonly HELPER=${INSTALL_DIR}/bin/installer/helper readonly LOG_DIR=/var/log/datadog readonly PACKAGES_LOCK_DIR=/var/run/datadog-packages @@ -65,7 +67,8 @@ fi chmod 750 ${HELPER} setcap cap_setuid+ep ${HELPER} -$BOOTSTRAP_INSTALLER bootstrap --url "oci://public.ecr.aws/datadog/installer-package:latest" +$BOOTSTRAP_INSTALLER bootstrap --url "oci://public.ecr.aws/datadog/installer-package:7.54.0-devel.git.366.99b427c.pipeline.32143438-1" +$STABLE_INSTALLER bootstrap exit 0 diff --git a/pkg/installer/install.go b/pkg/installer/install.go index 95ab2990aa81ba..4355352e9d977d 100644 --- a/pkg/installer/install.go +++ b/pkg/installer/install.go @@ -63,7 +63,10 @@ func (m *packageManager) installStable(ctx context.Context, pkg string, version if err != nil { return fmt.Errorf("could not create repository: %w", err) } + return m.setupUnits(ctx, pkg) +} +func (m *packageManager) setupUnits(ctx context.Context, pkg string) error { m.installLock.Lock() defer m.installLock.Unlock() switch pkg { @@ -71,8 +74,6 @@ func (m *packageManager) installStable(ctx context.Context, pkg string, version return service.SetupAgentUnits(ctx) case packageAPMInjector: return service.SetupAPMInjector(ctx) - case packageDatadogInstaller: - return service.SetupInstallerUnit(ctx) default: return nil } diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index 116fe1653ad7f0..b8f9dbd3b6c319 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -101,6 +101,26 @@ func BootstrapURL(ctx context.Context, url string, config config.Reader) error { return i.BootstrapURL(ctx, url) } +// Bootstrap is the generic installer bootstrap. +func Bootstrap(ctx context.Context, config config.Reader) error { + rc := newNoopRemoteConfig() + i, err := newInstaller(rc, defaultRepositoriesPath, defaultLocksPath, config) + if err != nil { + return fmt.Errorf("could not create installer: %w", err) + } + err = i.Start(ctx) + if err != nil { + return fmt.Errorf("could not start installer: %w", err) + } + defer func() { + err := i.Stop(ctx) + if err != nil { + log.Errorf("could not stop installer: %v", err) + } + }() + return i.Bootstrap(ctx) +} + // Purge removes files installed by the installer func Purge() { purge(defaultLocksPath, defaultRepositoriesPath) @@ -111,6 +131,7 @@ func purge(locksPath, repositoryPath string) { span, ctx := tracer.StartSpanFromContext(context.Background(), "purge") defer span.Finish(tracer.WithError(err)) service.RemoveAgentUnits(ctx) + service.RemoveInstallerUnits(ctx) if err = service.RemoveAPMInjector(ctx); err != nil { log.Warnf("installer: could not remove APM injector: %v", err) } @@ -237,6 +258,22 @@ func (i *installerImpl) BootstrapVersion(ctx context.Context, pkg string, versio return i.bootstrapPackage(ctx, stablePackage.URL, stablePackage.Name, stablePackage.Version) } +// Bootstrap is the generic bootstrap of the installer +func (i *installerImpl) Bootstrap(ctx context.Context) (err error) { + span, ctx := tracer.StartSpanFromContext(ctx, "bootstrap") + defer func() { span.Finish(tracer.WithError(err)) }() + i.m.Lock() + defer i.m.Unlock() + i.refreshState(ctx) + defer i.refreshState(ctx) + + if err = i.setupInstallerUnits(ctx); err != nil { + return err + } + + return nil +} + // BootstrapURL installs the stable version of the package. func (i *installerImpl) BootstrapURL(ctx context.Context, url string) (err error) { span, ctx := tracer.StartSpanFromContext(ctx, "bootstrap_url") @@ -344,6 +381,26 @@ func (i *installerImpl) StopExperiment(ctx context.Context, pkg string) (err err return nil } +func (i *installerImpl) setupInstallerUnits(ctx context.Context) (err error) { + systemdRunning, err := service.IsSystemdRunning() + if err != nil { + return fmt.Errorf("error checking if systemd is running: %w", err) + } + if !systemdRunning { + log.Infof("Installer: Systemd is not running, skipping unit setup") + return nil + } + err = service.SetupInstallerUnits(ctx) + if err != nil { + return fmt.Errorf("failed to setup datadog-installer systemd units: %w", err) + } + if !i.remoteUpdates { + service.RemoveInstallerUnits(ctx) + return + } + return service.StartInstallerStable(ctx) +} + func (i *installerImpl) handleCatalogUpdate(c catalog) error { i.m.Lock() defer i.m.Unlock() diff --git a/pkg/installer/service/apm_inject.go b/pkg/installer/service/apm_inject.go index 6333e0d33cf6e9..05ef6a6bdd1bf2 100644 --- a/pkg/installer/service/apm_inject.go +++ b/pkg/installer/service/apm_inject.go @@ -142,7 +142,7 @@ func (a *apmInjectorInstaller) setLDPreloadConfig(ctx context.Context) error { return err } - return executeCommand(ctx, string(replaceLDPreloadCommand)) + return executeHelperCommand(ctx, string(replaceLDPreloadCommand)) } // setLDPreloadConfigContent sets the content of the LD preload configuration @@ -195,7 +195,7 @@ func (a *apmInjectorInstaller) deleteLDPreloadConfig(ctx context.Context) error return err } - return executeCommand(ctx, string(replaceLDPreloadCommand)) + return executeHelperCommand(ctx, string(replaceLDPreloadCommand)) } // deleteLDPreloadConfigContent deletes the content of the LD preload configuration diff --git a/pkg/installer/service/cmd_executor.go b/pkg/installer/service/cmd_executor.go index 999628ebd9aed3..002b5c387092c9 100644 --- a/pkg/installer/service/cmd_executor.go +++ b/pkg/installer/service/cmd_executor.go @@ -29,28 +29,28 @@ const execTimeout = 30 * time.Second // ChownDDAgent changes the owner of the given path to the dd-agent user. func ChownDDAgent(ctx context.Context, path string) error { - return executeCommand(ctx, `{"command":"chown dd-agent","path":"`+path+`"}`) + return executeHelperCommand(ctx, `{"command":"chown dd-agent","path":"`+path+`"}`) } // RemoveAll removes all files under a given path under /opt/datadog-packages regardless of their owner. func RemoveAll(ctx context.Context, path string) error { - return executeCommand(ctx, `{"command":"rm","path":"`+path+`"}`) + return executeHelperCommand(ctx, `{"command":"rm","path":"`+path+`"}`) } func createAgentSymlink(ctx context.Context) error { - return executeCommand(ctx, `{"command":"agent-symlink"}`) + return executeHelperCommand(ctx, `{"command":"agent-symlink"}`) } func rmAgentSymlink(ctx context.Context) error { - return executeCommand(ctx, `{"command":"rm-agent-symlink"}`) + return executeHelperCommand(ctx, `{"command":"rm-agent-symlink"}`) } // SetCapHelper sets cap setuid on the newly installed helper func SetCapHelper(ctx context.Context, path string) error { - return executeCommand(ctx, `{"command":"setcap cap_setuid+ep", "path":"`+path+`"}`) + return executeHelperCommand(ctx, `{"command":"setcap cap_setuid+ep", "path":"`+path+`"}`) } -func executeCommand(ctx context.Context, command string) error { +func executeHelperCommand(ctx context.Context, command string) error { var err error var stderr io.ReadCloser span, _ := tracer.StartSpanFromContext(ctx, "execute_command") diff --git a/pkg/installer/service/datadog_agent.go b/pkg/installer/service/datadog_agent.go index a3cccb5facd22c..92823d5f9bf275 100644 --- a/pkg/installer/service/datadog_agent.go +++ b/pkg/installer/service/datadog_agent.go @@ -156,5 +156,5 @@ func setInstallerAgentGroup(ctx context.Context) error { if strings.Contains(string(out), "dd-agent") { return nil } - return executeCommand(ctx, string(addInstallerToAgentGroup)) + return executeHelperCommand(ctx, string(addInstallerToAgentGroup)) } diff --git a/pkg/installer/service/datadog_installer.go b/pkg/installer/service/datadog_installer.go index 0d744fac7df9ba..4aec47b3b31fdd 100644 --- a/pkg/installer/service/datadog_installer.go +++ b/pkg/installer/service/datadog_installer.go @@ -20,8 +20,8 @@ const ( var installerUnits = []string{installerUnit, installerUnitExp} -// SetupInstallerUnit installs and starts the installer systemd units -func SetupInstallerUnit(ctx context.Context) (err error) { +// SetupInstallerUnits installs and starts the installer systemd units +func SetupInstallerUnits(ctx context.Context) (err error) { defer func() { if err != nil { log.Errorf("Failed to setup installer units: %s, reverting", err) @@ -41,15 +41,16 @@ func SetupInstallerUnit(ctx context.Context) (err error) { if err = enableUnit(ctx, installerUnit); err != nil { return err } - - if err = startUnit(ctx, installerUnit); err != nil { - return err - } return nil } -// RemoveInstallerUnit removes the installer systemd units -func RemoveInstallerUnit(ctx context.Context) { +// StartInstallerStable starts the stable systemd units for the installer +func StartInstallerStable(ctx context.Context) (err error) { + return startUnit(ctx, installerUnit) +} + +// RemoveInstallerUnits removes the installer systemd units +func RemoveInstallerUnits(ctx context.Context) { var err error for _, unit := range installerUnits { if err = disableUnit(ctx, unit); err != nil { @@ -66,7 +67,7 @@ func StartInstallerExperiment(ctx context.Context) error { return startUnit(ctx, installerUnitExp) } -// StopInstallerExperiment installs the stable systemd units for the installer +// StopInstallerExperiment starts the stable systemd units for the installer func StopInstallerExperiment(ctx context.Context) error { return startUnit(ctx, installerUnit) } diff --git a/pkg/installer/service/datadog_installer_windows.go b/pkg/installer/service/datadog_installer_windows.go index 793a2b5dec97e5..751642c4941e1e 100644 --- a/pkg/installer/service/datadog_installer_windows.go +++ b/pkg/installer/service/datadog_installer_windows.go @@ -9,13 +9,13 @@ package service import "context" -// SetupInstallerUnit noop -func SetupInstallerUnit(_ context.Context) (err error) { +// SetupInstallerUnits noop +func SetupInstallerUnits(_ context.Context) (err error) { return nil } -// RemoveInstallerUnit noop -func RemoveInstallerUnit(_ context.Context) { +// RemoveInstallerUnits noop +func RemoveInstallerUnits(_ context.Context) { } // StartInstallerExperiment noop @@ -27,3 +27,8 @@ func StartInstallerExperiment(_ context.Context) error { func StopInstallerExperiment(_ context.Context) error { return nil } + +// StartInstallerStable noop +func StartInstallerStable(_ context.Context) error { + return nil +} diff --git a/pkg/installer/service/docker.go b/pkg/installer/service/docker.go index 3024cf3bed0633..dba7b1978f0b93 100644 --- a/pkg/installer/service/docker.go +++ b/pkg/installer/service/docker.go @@ -31,7 +31,7 @@ const ( // later func (a *apmInjectorInstaller) setDockerConfig(ctx context.Context) error { // Create docker dir if it doesn't exist - err := executeCommand(ctx, createDockerDirCommand) + err := executeHelperCommand(ctx, createDockerDirCommand) if err != nil { return err } @@ -64,7 +64,7 @@ func (a *apmInjectorInstaller) setDockerConfig(ctx context.Context) error { } // Move the temporary file to the final location - err = executeCommand(ctx, string(replaceDockerCommand)) + err = executeHelperCommand(ctx, string(replaceDockerCommand)) if err != nil { return err } @@ -135,7 +135,7 @@ func (a *apmInjectorInstaller) deleteDockerConfig(ctx context.Context) error { } // Move the temporary file to the final location - err = executeCommand(ctx, string(replaceDockerCommand)) + err = executeHelperCommand(ctx, string(replaceDockerCommand)) if err != nil { return err } @@ -180,7 +180,7 @@ func restartDocker(ctx context.Context) error { log.Info("installer: docker is not installed, skipping reload") return nil } - return executeCommand(ctx, restartDockerCommand) + return executeHelperCommand(ctx, restartDockerCommand) } // isDockerInstalled checks if docker is installed on the system diff --git a/pkg/installer/service/systemd.go b/pkg/installer/service/systemd.go index bdb3bf0a55d2d4..ce75089c5eeb88 100644 --- a/pkg/installer/service/systemd.go +++ b/pkg/installer/service/systemd.go @@ -65,31 +65,31 @@ func restartUnit(ctx context.Context, unit string) error { } func stopUnit(ctx context.Context, unit string) error { - return executeCommand(ctx, wrapUnitCommand(stopCommand, unit)) + return executeHelperCommand(ctx, wrapUnitCommand(stopCommand, unit)) } func startUnit(ctx context.Context, unit string) error { - return executeCommand(ctx, wrapUnitCommand(startCommand, unit)) + return executeHelperCommand(ctx, wrapUnitCommand(startCommand, unit)) } func enableUnit(ctx context.Context, unit string) error { - return executeCommand(ctx, wrapUnitCommand(enableCommand, unit)) + return executeHelperCommand(ctx, wrapUnitCommand(enableCommand, unit)) } func disableUnit(ctx context.Context, unit string) error { - return executeCommand(ctx, wrapUnitCommand(disableCommand, unit)) + return executeHelperCommand(ctx, wrapUnitCommand(disableCommand, unit)) } func loadUnit(ctx context.Context, unit string) error { - return executeCommand(ctx, wrapUnitCommand(loadCommand, unit)) + return executeHelperCommand(ctx, wrapUnitCommand(loadCommand, unit)) } func removeUnit(ctx context.Context, unit string) error { - return executeCommand(ctx, wrapUnitCommand(removeCommand, unit)) + return executeHelperCommand(ctx, wrapUnitCommand(removeCommand, unit)) } func systemdReload(ctx context.Context) error { - return executeCommand(ctx, systemdReloadCommand) + return executeHelperCommand(ctx, systemdReloadCommand) } func wrapUnitCommand(command unitCommand, unit string) string { @@ -108,5 +108,18 @@ func executeCommandStruct(ctx context.Context, command privilegeCommand) error { return err } privilegeCommandJSON := string(rawJSON) - return executeCommand(ctx, privilegeCommandJSON) + return executeHelperCommand(ctx, privilegeCommandJSON) +} + +// IsSystemdRunning checks if systemd is running using the documented way +// https://www.freedesktop.org/software/systemd/man/latest/sd_booted.html#Notes +func IsSystemdRunning() (running bool, err error) { + _, err = os.Stat("/run/systemd/system") + if os.IsNotExist(err) { + log.Infof("Installer: systemd is not running, skip unit setup") + return false, nil + } else if err != nil { + return false, err + } + return true, nil } diff --git a/pkg/installer/service/systemd_test.go b/pkg/installer/service/systemd_test.go index 9a5200031ca86b..7b703c314a567a 100644 --- a/pkg/installer/service/systemd_test.go +++ b/pkg/installer/service/systemd_test.go @@ -37,7 +37,7 @@ func TestInvalidCommands(t *testing.T) { `{"command":"chown dd-agent", "path":"/"}`: "error: invalid path\n", `{"command":"chown dd-agent", "path":"/opt/datadog-packages/../.."}`: "error: invalid path\n", } { - assert.Equal(t, expected, executeCommand(testCtx, input).Error()) + assert.Equal(t, expected, executeHelperCommand(testCtx, input).Error()) } } diff --git a/pkg/installer/service/systemd_windows.go b/pkg/installer/service/systemd_windows.go new file mode 100644 index 00000000000000..8233b83a18e075 --- /dev/null +++ b/pkg/installer/service/systemd_windows.go @@ -0,0 +1,14 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build windows + +// Package service provides a way to interact with os services +package service + +// IsSystemdRunning noop +func IsSystemdRunning() (running bool, err error) { + return false, nil +} diff --git a/test/new-e2e/tests/installer/linux_test.go b/test/new-e2e/tests/installer/linux_test.go index 8d536c570397f0..49d87b6f6d882c 100644 --- a/test/new-e2e/tests/installer/linux_test.go +++ b/test/new-e2e/tests/installer/linux_test.go @@ -10,6 +10,7 @@ import ( "fmt" "path/filepath" "regexp" + "strconv" "strings" "testing" "time" @@ -28,24 +29,25 @@ import ( ) const ( - confDir = "/etc/datadog-agent" - logDir = "/var/log/datadog" - locksDir = "/var/run/datadog-packages" - packagesDir = "/opt/datadog-packages" - bootUpdaterDir = "/opt/datadog-installer" + confDir = "/etc/datadog-agent" + logDir = "/var/log/datadog" + locksDir = "/var/run/datadog-packages" + packagesDir = "/opt/datadog-packages" + bootInstallerDir = "/opt/datadog-installer" ) type vmUpdaterSuite struct { e2e.BaseSuite[environments.Host] - packageManager string - distro os.Descriptor - arch os.Architecture + packageManager string + distro os.Descriptor + arch os.Architecture + remoteUpdatesEnabled bool } -func runTest(t *testing.T, pkgManager string, arch os.Architecture, distro os.Descriptor) { +func runTest(t *testing.T, pkgManager string, arch os.Architecture, distro os.Descriptor, remoteUpdatesEnabled bool) { reg := regexp.MustCompile(`[^a-zA-Z0-9_\-.]`) - testName := reg.ReplaceAllString(distro.String()+"-"+string(arch), "_") - e2e.Run(t, &vmUpdaterSuite{packageManager: pkgManager, distro: distro, arch: arch}, e2e.WithProvisioner(awshost.ProvisionerNoFakeIntake( + testName := reg.ReplaceAllString(distro.String()+"-"+string(arch)+"-remote_updates_"+strconv.FormatBool(remoteUpdatesEnabled), "_") + e2e.Run(t, &vmUpdaterSuite{packageManager: pkgManager, distro: distro, arch: arch, remoteUpdatesEnabled: remoteUpdatesEnabled}, e2e.WithProvisioner(awshost.ProvisionerNoFakeIntake( awshost.WithUpdater(), awshost.WithEC2InstanceOptions(ec2.WithOSArch(distro, arch)), )), @@ -55,23 +57,23 @@ func runTest(t *testing.T, pkgManager string, arch os.Architecture, distro os.De func TestCentOSARM(t *testing.T) { t.Parallel() - runTest(t, "rpm", os.AMD64Arch, os.CentOSDefault) + runTest(t, "rpm", os.AMD64Arch, os.CentOSDefault, false) } func TestRedHatARM(t *testing.T) { t.Skip("Support for SELinux has not been added yet") t.Parallel() - runTest(t, "rpm", os.ARM64Arch, os.RedHatDefault) + runTest(t, "rpm", os.ARM64Arch, os.RedHatDefault, false) } func TestUbuntuARM(t *testing.T) { t.Parallel() - runTest(t, "dpkg", os.ARM64Arch, os.UbuntuDefault) + runTest(t, "dpkg", os.ARM64Arch, os.UbuntuDefault, true) } func TestDebianX86(t *testing.T) { t.Parallel() - runTest(t, "dpkg", os.AMD64Arch, os.DebianDefault) + runTest(t, "dpkg", os.AMD64Arch, os.DebianDefault, true) } func (v *vmUpdaterSuite) TestUserGroupsCreation() { @@ -92,7 +94,7 @@ func (v *vmUpdaterSuite) TestSharedAgentDirs() { } func (v *vmUpdaterSuite) TestUpdaterDirs() { - for _, dir := range []string{locksDir, packagesDir, bootUpdaterDir} { + for _, dir := range []string{locksDir, packagesDir, bootInstallerDir} { require.Equal(v.T(), "dd-installer\n", v.Env().RemoteHost.MustExecute(`stat -c "%U" `+dir)) require.Equal(v.T(), "dd-installer\n", v.Env().RemoteHost.MustExecute(`stat -c "%G" `+dir)) } @@ -101,10 +103,27 @@ func (v *vmUpdaterSuite) TestUpdaterDirs() { } func (v *vmUpdaterSuite) TestInstallerUnitLoaded() { + t := v.T() + host := v.Env().RemoteHost if v.packageManager == "rpm" { - v.T().Skip("FIXME(Paul): installer unit files disappear after bootstrap") + t.Skip("FIXME(Paul): installer unit files disappear after bootstrap") } - require.Equal(v.T(), "enabled\n", v.Env().RemoteHost.MustExecute(`systemctl is-enabled datadog-installer.service`)) + + // temporary hack, remote update enabled by hand and disabled to assert the behavior and pass tests + // until agent param passing to the test install script is implemnted + _, err := host.Execute(`systemctl is-enabled datadog-installer.service`) + require.ErrorContains(t, err, "Failed to get unit file state for datadog-installer.service: No such file or directory") + + if v.remoteUpdatesEnabled { + host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootInstallerDir)) + host.MustExecute(fmt.Sprintf(`DD_UPDATER_REMOTE_UPDATES=true sudo -E %v/bin/installer/installer bootstrap`, bootInstallerDir)) + require.Equal(v.T(), "enabled\n", v.Env().RemoteHost.MustExecute(`systemctl is-enabled datadog-installer.service`)) + host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootInstallerDir)) + host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://public.ecr.aws/datadog/installer-package:latest"`, bootInstallerDir)) + } + _, err = host.Execute(`systemctl is-enabled datadog-installer.service`) + require.ErrorContains(t, err, "Failed to get unit file state for datadog-installer.service: No such file or directory") + } func (v *vmUpdaterSuite) TestAgentUnitsLoaded() { @@ -117,7 +136,7 @@ func (v *vmUpdaterSuite) TestAgentUnitsLoaded() { "datadog-agent-security.service", } addEcrConfig(v.Env().RemoteHost) - v.Env().RemoteHost.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev@sha256:d86138d88b407cf5ef75bccb3e0bc492ce6e3e3dfa9d3a64d2387d3b350fe5c4"`, bootUpdaterDir)) + v.Env().RemoteHost.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev@sha256:d86138d88b407cf5ef75bccb3e0bc492ce6e3e3dfa9d3a64d2387d3b350fe5c4"`, bootInstallerDir)) for _, unit := range stableUnits { require.Equal(t, "enabled\n", v.Env().RemoteHost.MustExecute(fmt.Sprintf(`systemctl is-enabled %s`, unit))) } @@ -128,7 +147,7 @@ func (v *vmUpdaterSuite) TestExperimentCrash() { host := v.Env().RemoteHost addEcrConfig(host) startTime := getMonotonicTimestamp(t, host) - host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev@sha256:d86138d88b407cf5ef75bccb3e0bc492ce6e3e3dfa9d3a64d2387d3b350fe5c4"`, bootUpdaterDir)) + host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev@sha256:d86138d88b407cf5ef75bccb3e0bc492ce6e3e3dfa9d3a64d2387d3b350fe5c4"`, bootInstallerDir)) v.Env().RemoteHost.MustExecute(`sudo systemctl start datadog-agent-exp --no-block`) res := getJournalDOnCondition(t, host, startTime, stopCondition([]JournaldLog{ {Unit: "datadog-agent.service", Message: "Started"}, @@ -150,7 +169,7 @@ func (v *vmUpdaterSuite) TestPurgeAndInstallAgent() { } addEcrConfig(host) - host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootUpdaterDir)) + host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootInstallerDir)) stableUnits := []string{ "datadog-agent.service", "datadog-agent-trace.service", @@ -184,7 +203,7 @@ func (v *vmUpdaterSuite) TestPurgeAndInstallAgent() { } // bootstrap - host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev@sha256:d86138d88b407cf5ef75bccb3e0bc492ce6e3e3dfa9d3a64d2387d3b350fe5c4"`, bootUpdaterDir)) + host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev@sha256:d86138d88b407cf5ef75bccb3e0bc492ce6e3e3dfa9d3a64d2387d3b350fe5c4"`, bootInstallerDir)) // assert agent symlink _ = host.MustExecute(`test -L /usr/bin/datadog-agent`) @@ -229,7 +248,7 @@ func (v *vmUpdaterSuite) TestPurgeAndInstallAPMInjector() { // Setup machine // /////////////////// addEcrConfig(host) - host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootUpdaterDir)) + host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootInstallerDir)) // Install docker installDocker(v.distro, v.arch, v.T(), host) defer func() { @@ -262,9 +281,9 @@ func (v *vmUpdaterSuite) TestPurgeAndInstallAPMInjector() { // Bootstrap packages // //////////////////////// - host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev:7.54.0-devel.git.247.f92fbc1.pipeline.31778392-1"`, bootUpdaterDir)) - host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/apm-library-java-package-dev:1.32.0-SNAPSHOT-8708864e8e-pipeline.30373268.beta.8708864e-1"`, bootUpdaterDir)) - host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/apm-inject-package-dev:0.12.3-dev.bddec85.glci481808135.g8acdc698-1"`, bootUpdaterDir)) + host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/agent-package-dev:7.54.0-devel.git.247.f92fbc1.pipeline.31778392-1"`, bootInstallerDir)) + host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/apm-library-java-package-dev:1.32.0-SNAPSHOT-8708864e8e-pipeline.30373268.beta.8708864e-1"`, bootInstallerDir)) + host.MustExecute(fmt.Sprintf(`sudo %v/bin/installer/installer bootstrap --url "oci://669783387624.dkr.ecr.us-east-1.amazonaws.com/dockerhub/datadog/apm-inject-package-dev:0.12.3-dev.bddec85.glci481808135.g8acdc698-1"`, bootInstallerDir)) //////////////////////////////// // Check post-bootstrap state // @@ -333,7 +352,7 @@ func (v *vmUpdaterSuite) TestPurgeAndInstallAPMInjector() { // Check purge state // /////////////////////// - host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootUpdaterDir)) + host.MustExecute(fmt.Sprintf("sudo %v/bin/installer/installer purge", bootInstallerDir)) _, err = host.Execute(`test -d /opt/datadog-packages/datadog-apm-inject`) require.NotNil(v.T(), err)