diff --git a/commands/apt.go b/commands/apt.go index 70c14a4..e9c6845 100644 --- a/commands/apt.go +++ b/commands/apt.go @@ -39,7 +39,7 @@ const ( // Environment variable for disabling interactive prompts in frontends of // commands like apt-get - frontendNoninteractive = "DEBIAN_FRONTEND=noninteractive" + EnvFrontendNoninteractive = "DEBIAN_FRONTEND=noninteractive" // the basic format for specifying a proxy option for apt: aptProxySettingFormat = "Acquire::%s::Proxy %q;" @@ -50,12 +50,12 @@ const ( // aptCmder is the packageCommander instantiation for apt-based systems. var aptCmder = packageCommander{ - prereq: buildCommand(frontendNoninteractive, aptget, "install python-software-properties"), - update: buildCommand(frontendNoninteractive, aptget, "update"), - upgrade: buildCommand(frontendNoninteractive, aptget, "upgrade"), - install: buildCommand(frontendNoninteractive, aptget, "install"), - remove: buildCommand(frontendNoninteractive, aptget, "remove"), - purge: buildCommand(frontendNoninteractive, aptget, "purge"), + prereq: buildCommand(aptget, "install python-software-properties"), + update: buildCommand(aptget, "update"), + upgrade: buildCommand(aptget, "upgrade"), + install: buildCommand(aptget, "install"), + remove: buildCommand(aptget, "remove"), + purge: buildCommand(aptget, "purge"), search: buildCommand(aptcache, "search --names-only ^%s$"), isInstalled: buildCommand(dpkgquery, "-s %s"), listAvailable: buildCommand(aptcache, "pkgnames"), @@ -63,7 +63,7 @@ var aptCmder = packageCommander{ addRepository: buildCommand(addaptrepo, "%q"), listRepositories: buildCommand(`sed -r -n "s|^deb(-src)? (.*)|\2|p"`, "/etc/apt/sources.list"), removeRepository: buildCommand(addaptrepo, "--remove ppa:%s"), - cleanup: buildCommand(frontendNoninteractive, aptget, "autoremove"), + cleanup: buildCommand(aptget, "autoremove"), getProxy: buildCommand(aptconfig, "Acquire::http::Proxy Acquire::https::Proxy Acquire::ftp::Proxy"), proxySettingsFormat: aptProxySettingFormat, setProxy: buildCommand("echo %s >> ", AptConfFilePath), diff --git a/manager/apt.go b/manager/apt.go index 12a3387..0725f19 100644 --- a/manager/apt.go +++ b/manager/apt.go @@ -48,7 +48,7 @@ func NewAptPackageManager() PackageManager { // Search is defined on the PackageManager interface. func (apt *apt) Search(pack string) (bool, error) { - out, _, err := RunCommandWithRetry(apt.cmder.SearchCmd(pack), apt, apt.retryPolicy) + out, _, err := RunCommandWithRetry(apt.cmder.SearchCmd(pack), apt, apt.retryPolicy, nil) if err != nil { return false, err } @@ -63,7 +63,7 @@ func (apt *apt) Search(pack string) (bool, error) { // Install is defined on the PackageManager interface. func (apt *apt) Install(packs ...string) error { - _, _, err := RunCommandWithRetry(apt.cmder.InstallCmd(packs...), apt.installRetryable, apt.retryPolicy) + _, _, err := RunCommandWithRetry(apt.cmder.InstallCmd(packs...), apt.installRetryable, apt.retryPolicy, []string{commands.EnvFrontendNoninteractive}) return err } diff --git a/manager/manager.go b/manager/manager.go index 3cfec59..139913d 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -23,37 +23,37 @@ type basePackageManager struct { // InstallPrerequisite is defined on the PackageManager interface. func (pm *basePackageManager) InstallPrerequisite() error { - _, _, err := RunCommandWithRetry(pm.cmder.InstallPrerequisiteCmd(), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.InstallPrerequisiteCmd(), pm, pm.retryPolicy, nil) return err } // Update is defined on the PackageManager interface. func (pm *basePackageManager) Update() error { - _, _, err := RunCommandWithRetry(pm.cmder.UpdateCmd(), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.UpdateCmd(), pm, pm.retryPolicy, nil) return err } // Upgrade is defined on the PackageManager interface. func (pm *basePackageManager) Upgrade() error { - _, _, err := RunCommandWithRetry(pm.cmder.UpgradeCmd(), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.UpgradeCmd(), pm, pm.retryPolicy, nil) return err } // Install is defined on the PackageManager interface. func (pm *basePackageManager) Install(packs ...string) error { - _, _, err := RunCommandWithRetry(pm.cmder.InstallCmd(packs...), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.InstallCmd(packs...), pm, pm.retryPolicy, nil) return err } // Remove is defined on the PackageManager interface. func (pm *basePackageManager) Remove(packs ...string) error { - _, _, err := RunCommandWithRetry(pm.cmder.RemoveCmd(packs...), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.RemoveCmd(packs...), pm, pm.retryPolicy, nil) return err } // Purge is defined on the PackageManager interface. func (pm *basePackageManager) Purge(packs ...string) error { - _, _, err := RunCommandWithRetry(pm.cmder.PurgeCmd(packs...), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.PurgeCmd(packs...), pm, pm.retryPolicy, nil) return err } @@ -67,19 +67,19 @@ func (pm *basePackageManager) IsInstalled(pack string) bool { // AddRepository is defined on the PackageManager interface. func (pm *basePackageManager) AddRepository(repo string) error { - _, _, err := RunCommandWithRetry(pm.cmder.AddRepositoryCmd(repo), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.AddRepositoryCmd(repo), pm, pm.retryPolicy, nil) return err } // RemoveRepository is defined on the PackageManager interface. func (pm *basePackageManager) RemoveRepository(repo string) error { - _, _, err := RunCommandWithRetry(pm.cmder.RemoveRepositoryCmd(repo), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.RemoveRepositoryCmd(repo), pm, pm.retryPolicy, nil) return err } // Cleanup is defined on the PackageManager interface. func (pm *basePackageManager) Cleanup() error { - _, _, err := RunCommandWithRetry(pm.cmder.CleanupCmd(), pm, pm.retryPolicy) + _, _, err := RunCommandWithRetry(pm.cmder.CleanupCmd(), pm, pm.retryPolicy, nil) return err } diff --git a/manager/manager_test.go b/manager/manager_test.go index 513b822..36dbcbd 100644 --- a/manager/manager_test.go +++ b/manager/manager_test.go @@ -82,8 +82,8 @@ var ( // getMockRunCommandWithRetry returns a function with the same signature as // RunCommandWithRetry which saves the command it receives in the provided // string whilst always returning no output, 0 error code and nil error. -func getMockRunCommandWithRetry(stor *string) func(string, manager.Retryable, manager.RetryPolicy) (string, int, error) { - return func(cmd string, _ manager.Retryable, _ manager.RetryPolicy) (string, int, error) { +func getMockRunCommandWithRetry(stor *string) func(string, manager.Retryable, manager.RetryPolicy, []string) (string, int, error) { + return func(cmd string, _ manager.Retryable, _ manager.RetryPolicy, _ []string) (string, int, error) { *stor = cmd return "", 0, nil } diff --git a/manager/run.go b/manager/run.go index 2123edb..a5bd2eb 100644 --- a/manager/run.go +++ b/manager/run.go @@ -78,7 +78,7 @@ func DefaultRetryPolicy() RetryPolicy { // It returns the output of the command, the exit code, and an error, if one occurs, // logging along the way. // It was aliased for testing purposes. -var RunCommandWithRetry = func(cmd string, retryable Retryable, policy RetryPolicy) (output string, code int, _ error) { +var RunCommandWithRetry = func(cmd string, retryable Retryable, policy RetryPolicy, envVariables []string) (output string, code int, _ error) { // split the command for use with exec args := strings.Fields(cmd) if len(args) <= 1 { @@ -105,6 +105,7 @@ var RunCommandWithRetry = func(cmd string, retryable Retryable, policy RetryPoli // Create the command for each attempt, because we need to // call cmd.CombinedOutput only once. See http://pad.lv/1394524. command := exec.Command(args[0], args[1:]...) + command.Env = append(os.Environ(), envVariables...) var err error out, err = CommandOutput(command) diff --git a/manager/snap.go b/manager/snap.go index b63a1cc..f4e1c00 100644 --- a/manager/snap.go +++ b/manager/snap.go @@ -65,7 +65,7 @@ func NewSnapPackageManager() *Snap { // Search is defined on the PackageManager interface. func (snap *Snap) Search(pack string) (bool, error) { - out, _, err := RunCommandWithRetry(snap.cmder.SearchCmd(pack), snap, snap.retryPolicy) + out, _, err := RunCommandWithRetry(snap.cmder.SearchCmd(pack), snap, snap.retryPolicy, nil) if strings.Contains(combinedOutput(out, err), "error: no snap found") { return false, nil } else if err != nil { @@ -77,7 +77,7 @@ func (snap *Snap) Search(pack string) (bool, error) { // IsInstalled is defined on the PackageManager interface. func (snap *Snap) IsInstalled(pack string) bool { - out, _, err := RunCommandWithRetry(snap.cmder.IsInstalledCmd(pack), snap, snap.retryPolicy) + out, _, err := RunCommandWithRetry(snap.cmder.IsInstalledCmd(pack), snap, snap.retryPolicy, nil) if strings.Contains(combinedOutput(out, err), "error: no matching snaps installed") || err != nil { return false } @@ -86,7 +86,7 @@ func (snap *Snap) IsInstalled(pack string) bool { // InstalledChannel returns the snap channel for an installed package. func (snap *Snap) InstalledChannel(pack string) string { - out, _, err := RunCommandWithRetry(fmt.Sprintf("snap info %s", pack), snap, snap.retryPolicy) + out, _, err := RunCommandWithRetry(fmt.Sprintf("snap info %s", pack), snap, snap.retryPolicy, nil) combined := combinedOutput(out, err) matches := trackingRE.FindAllStringSubmatch(combined, 1) if len(matches) == 0 { @@ -99,7 +99,7 @@ func (snap *Snap) InstalledChannel(pack string) string { // ChangeChannel updates the tracked channel for an installed snap. func (snap *Snap) ChangeChannel(pack, channel string) error { cmd := fmt.Sprintf("snap refresh --channel %s %s", channel, pack) - out, _, err := RunCommandWithRetry(cmd, snap, snap.retryPolicy) + out, _, err := RunCommandWithRetry(cmd, snap, snap.retryPolicy, nil) if err != nil { return err } else if strings.Contains(combinedOutput(out, err), "not installed") { @@ -111,7 +111,7 @@ func (snap *Snap) ChangeChannel(pack, channel string) error { // Install is defined on the PackageManager interface. func (snap *Snap) Install(packs ...string) error { - out, _, err := RunCommandWithRetry(snap.cmder.InstallCmd(packs...), snap.installRetryable, snap.retryPolicy) + out, _, err := RunCommandWithRetry(snap.cmder.InstallCmd(packs...), snap.installRetryable, snap.retryPolicy, nil) if snapNotFoundRE.MatchString(combinedOutput(out, err)) { return errors.New("unable to locate package") } @@ -122,7 +122,7 @@ func (snap *Snap) Install(packs ...string) error { func (snap *Snap) GetProxySettings() (proxy.Settings, error) { var res proxy.Settings - out, _, err := RunCommandWithRetry(snap.cmder.GetProxyCmd(), snap, snap.retryPolicy) + out, _, err := RunCommandWithRetry(snap.cmder.GetProxyCmd(), snap, snap.retryPolicy, nil) if strings.Contains(combinedOutput(out, err), `no "proxy" configuration option`) { return res, nil } else if err != nil { @@ -170,12 +170,12 @@ func (snap *Snap) ConfigureStoreProxy(assertions, storeID string) error { _ = assertFile.Close() ackCmd := fmt.Sprintf("snap ack %s", assertFile.Name()) - if _, _, err = RunCommandWithRetry(ackCmd, snap, snap.retryPolicy); err != nil { + if _, _, err = RunCommandWithRetry(ackCmd, snap, snap.retryPolicy, nil); err != nil { return errors.Annotate(err, "failed to execute 'snap ack'") } setCmd := fmt.Sprintf("snap set system proxy.store=%s", storeID) - if _, _, err = RunCommandWithRetry(setCmd, snap, snap.retryPolicy); err != nil { + if _, _, err = RunCommandWithRetry(setCmd, snap, snap.retryPolicy, nil); err != nil { return errors.Annotatef(err, "failed to configure snap to use store ID %q", storeID) } @@ -189,7 +189,7 @@ func (snap *Snap) ConfigureStoreProxy(assertions, storeID string) error { // call to SetProxy. func (snap *Snap) DisableStoreProxy() error { setCmd := "snap set system proxy.store=" - if _, _, err := RunCommandWithRetry(setCmd, snap, snap.retryPolicy); err != nil { + if _, _, err := RunCommandWithRetry(setCmd, snap, snap.retryPolicy, nil); err != nil { return errors.Annotate(err, "failed to configure snap to not use a store proxy") } diff --git a/manager/yum.go b/manager/yum.go index d60eab8..0981005 100644 --- a/manager/yum.go +++ b/manager/yum.go @@ -37,7 +37,7 @@ func NewYumPackageManager() PackageManager { // Search is defined on the PackageManager interface. func (yum *yum) Search(pack string) (bool, error) { - _, code, err := RunCommandWithRetry(yum.cmder.SearchCmd(pack), yum, yum.retryPolicy) + _, code, err := RunCommandWithRetry(yum.cmder.SearchCmd(pack), yum, yum.retryPolicy, nil) // yum list package returns 1 when it cannot find the package. if code == 1 { diff --git a/manager/zypper.go b/manager/zypper.go index 4053ec0..43a69c2 100644 --- a/manager/zypper.go +++ b/manager/zypper.go @@ -36,7 +36,7 @@ func NewZypperPackageManager() PackageManager { // Search is defined on the PackageManager interface. func (zypper *zypper) Search(pack string) (bool, error) { - _, code, err := RunCommandWithRetry(zypper.cmder.SearchCmd(pack), zypper, zypper.retryPolicy) + _, code, err := RunCommandWithRetry(zypper.cmder.SearchCmd(pack), zypper, zypper.retryPolicy, nil) // zypper search returns 104 when it cannot find the package. if code == 104 {