Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 11 additions & 1 deletion lib/autoupdate/agent/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ type Process interface {
// If validated, these overrides may be persisted to disk.
type OverrideConfig struct {
UpdateSpec

// The fields below override the behavior of
// Updater.Install for a single run.

// ForceVersion to the specified version.
ForceVersion string
// ForceFlags in installed Teleport.
Expand Down Expand Up @@ -444,7 +448,7 @@ func sameProxies(a, b string) bool {
// Remove removes everything created by the updater for the given namespace.
// Before attempting this, Remove attempts to gracefully recover the system-packaged version of Teleport (if present).
// This function is idempotent.
func (u *Updater) Remove(ctx context.Context) error {
func (u *Updater) Remove(ctx context.Context, force bool) error {
cfg, err := readConfig(u.UpdateConfigPath)
if err != nil {
return trace.Wrap(err, "failed to read %s", updateConfigName)
Expand All @@ -465,6 +469,12 @@ func (u *Updater) Remove(ctx context.Context) error {
revert, err := u.Installer.LinkSystem(ctx)
if errors.Is(err, ErrNoBinaries) ||
errors.Is(err, ErrInvalid) {
if !force {
u.Log.ErrorContext(ctx, "No packaged installation of Teleport was found, and --force was not passed. Refusing to remove Teleport from this system.")
return trace.Errorf("unable to remove Teleport completely without --force")
} else {
u.Log.WarnContext(ctx, "No packaged installation of Teleport was found, and --force was passed. Teleport will be removed from this system.")
}
u.Log.InfoContext(ctx, "Updater-managed installation of Teleport detected. Attempting to unlink and remove.")
ok, err := isActiveOrEnabled(ctx, u.Process)
if err != nil && !errors.Is(err, ErrNotSupported) {
Expand Down
25 changes: 21 additions & 4 deletions lib/autoupdate/agent/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ func TestUpdater_Remove(t *testing.T) {
syncErr error
reloadErr error
processEnabled bool
force bool

unlinkedVersion string
teardownCalls int
Expand All @@ -939,7 +940,7 @@ func TestUpdater_Remove(t *testing.T) {
teardownCalls: 1,
},
{
name: "no system links, process enabled",
name: "no system links, process enabled, force",
cfg: &UpdateConfig{
Version: updateConfigVersion,
Kind: updateConfigKind,
Expand All @@ -950,10 +951,11 @@ func TestUpdater_Remove(t *testing.T) {
linkSystemErr: ErrNoBinaries,
linkSystemCalls: 1,
processEnabled: true,
force: true,
errMatch: "refusing to remove",
},
{
name: "no system links, process disabled",
name: "no system links, process disabled, force",
cfg: &UpdateConfig{
Version: updateConfigVersion,
Kind: updateConfigKind,
Expand All @@ -965,9 +967,23 @@ func TestUpdater_Remove(t *testing.T) {
linkSystemCalls: 1,
unlinkedVersion: version,
teardownCalls: 1,
force: true,
},
{
name: "no system links, process disabled, no systemd",
name: "no system links, process disabled, no force",
cfg: &UpdateConfig{
Version: updateConfigVersion,
Kind: updateConfigKind,
Status: UpdateStatus{
Active: NewRevision(version, 0),
},
},
linkSystemErr: ErrNoBinaries,
linkSystemCalls: 1,
errMatch: "unable to remove",
},
{
name: "no system links, process disabled, no systemd, force",
cfg: &UpdateConfig{
Version: updateConfigVersion,
Kind: updateConfigKind,
Expand All @@ -980,6 +996,7 @@ func TestUpdater_Remove(t *testing.T) {
isEnabledErr: ErrNotSupported,
unlinkedVersion: version,
teardownCalls: 1,
force: true,
},
{
name: "active version",
Expand Down Expand Up @@ -1123,7 +1140,7 @@ func TestUpdater_Remove(t *testing.T) {
}

ctx := context.Background()
err = updater.Remove(ctx)
err = updater.Remove(ctx, tt.force)
if tt.errMatch != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.errMatch)
Expand Down
6 changes: 5 additions & 1 deletion tool/teleport-update/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ type cliConfig struct {
UpdateNow bool
// Reload reloads Teleport.
Reload bool
// ForceUninstall allows Teleport to be completely removed.
ForceUninstall bool
}

func Run(args []string) int {
Expand Down Expand Up @@ -157,6 +159,8 @@ func Run(args []string) int {
statusCmd := app.Command("status", "Show Teleport agent auto-update status.")

uninstallCmd := app.Command("uninstall", "Uninstall the updater-managed installation of Teleport. If the Teleport package is installed, it is restored as the primary installation.")
uninstallCmd.Flag("force", "Force complete uninstallation of Teleport, even if there is no packaged version of Teleport to revert to.").
Short('f').BoolVar(&ccfg.ForceUninstall)

libutils.UpdateAppUsageTemplate(app, args)
command, err := app.Parse(args)
Expand Down Expand Up @@ -470,7 +474,7 @@ func cmdUninstall(ctx context.Context, ccfg *cliConfig) error {
}
}()

if err := updater.Remove(ctx); err != nil {
if err := updater.Remove(ctx, ccfg.ForceUninstall); err != nil {
return trace.Wrap(err)
}
return nil
Expand Down