From c90b7c6f29205782822ed298a9087bc533a98648 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 4 Mar 2025 18:09:02 -0500 Subject: [PATCH 01/11] Usability fixes --- lib/autoupdate/agent/updater.go | 26 +++++++++++++++++--------- tool/teleport-update/main.go | 4 ++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 0c2e354c018bd..00767205d760b 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -85,6 +85,11 @@ func warnUmask(ctx context.Context, log *slog.Logger, old int) { } } +var ( + // ErrNotInstalled is returned when Teleport is not installed. + ErrNotInstalled = trace.Errorf("not installed") +) + // NewLocalUpdater returns a new Updater that auto-updates local // installations of the Teleport agent. // The AutoUpdater uses an HTTP client with sane defaults for downloads, and @@ -448,11 +453,17 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { // Do not link system package installation if the installation we are removing // is not installed into /usr/local/bin. if filepath.Clean(cfg.Spec.Path) != filepath.Clean(defaultPathDir) { - return u.removeWithoutSystem(ctx, cfg, force) + return u.removeWithoutSystem(ctx, cfg) } revert, err := u.Installer.LinkSystem(ctx) if errors.Is(err, ErrNoBinaries) { - return u.removeWithoutSystem(ctx, cfg, force) + 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.") + } + return u.removeWithoutSystem(ctx, cfg) } if err != nil { return trace.Wrap(err, "failed to link") @@ -519,13 +530,7 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { return nil } -func (u *Updater) removeWithoutSystem(ctx context.Context, cfg *UpdateConfig, force bool) error { - 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.") - } +func (u *Updater) removeWithoutSystem(ctx context.Context, cfg *UpdateConfig) error { u.Log.InfoContext(ctx, "Updater-managed installation of Teleport detected. Attempting to unlink and remove.") ok, err := u.Process.IsActive(ctx) if err != nil && !errors.Is(err, ErrNotSupported) { @@ -558,6 +563,9 @@ func (u *Updater) Status(ctx context.Context) (Status, error) { if err := validateConfigSpec(&cfg.Spec, OverrideConfig{}); err != nil { return out, trace.Wrap(err) } + if cfg.Spec.Proxy == "" { + return out, ErrNotInstalled + } out.UpdateSpec = cfg.Spec out.UpdateStatus = cfg.Status diff --git a/tool/teleport-update/main.go b/tool/teleport-update/main.go index 58ccb6bdd0584..eaeeb568e9dd2 100644 --- a/tool/teleport-update/main.go +++ b/tool/teleport-update/main.go @@ -460,6 +460,10 @@ func cmdStatus(ctx context.Context, ccfg *cliConfig) error { if err != nil { return trace.Wrap(err, "failed to get status") } + if errors.Is(err, autoupdate.ErrNotInstalled) { + plog.InfoContext(ctx, "Teleport is not installed.") + return nil + } enc := yaml.NewEncoder(os.Stdout) return trace.Wrap(enc.Encode(status)) } From 1b5921531c57ec8c6b572d7069bff8edb47331e3 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Mon, 10 Mar 2025 20:37:22 -0400 Subject: [PATCH 02/11] cancel jitter --- lib/autoupdate/agent/updater.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 00767205d760b..f8d0423752b14 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -697,7 +697,11 @@ func (u *Updater) Update(ctx context.Context, now bool) error { u.Log.InfoContext(ctx, "Update available. Initiating update.", targetKey, target, activeKey, active) } if !now { - time.Sleep(resp.Jitter) + select { + case <-time.After(resp.Jitter): + case <-ctx.Done(): + return trace.Wrap(ctx.Err()) + } } updateErr := u.update(ctx, cfg, target, false, resp.AGPL) From 196d4ec0a697b02fcd69ab86fa60c6d05ec15eb2 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Mon, 10 Mar 2025 20:53:57 -0400 Subject: [PATCH 03/11] root + fix logs --- lib/autoupdate/agent/updater.go | 27 +++++++++++++++++---------- tool/teleport-update/main.go | 6 +++++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index f8d0423752b14..7ff49d803ae5a 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -23,6 +23,7 @@ import ( "crypto/tls" "crypto/x509" "errors" + "fmt" "log/slog" "net/http" "os" @@ -120,13 +121,14 @@ func NewLocalUpdater(cfg LocalUpdaterConfig, ns *Namespace) (*Updater, error) { validator := Validator{Log: cfg.Log} debugClient := debug.NewClient(filepath.Join(ns.dataDir, debugSocketFileName)) return &Updater{ - Log: cfg.Log, - Pool: certPool, - InsecureSkipVerify: cfg.InsecureSkipVerify, - UpdateConfigFile: filepath.Join(ns.Dir(), updateConfigName), - TeleportConfigFile: ns.configFile, - DefaultProxyAddr: ns.defaultProxyAddr, - DefaultPathDir: ns.defaultPathDir, + Log: cfg.Log, + Pool: certPool, + InsecureSkipVerify: cfg.InsecureSkipVerify, + UpdateConfigFile: filepath.Join(ns.Dir(), updateConfigName), + TeleportConfigFile: ns.configFile, + TeleportServiceName: filepath.Base(ns.serviceFile), + DefaultProxyAddr: ns.defaultProxyAddr, + DefaultPathDir: ns.defaultPathDir, Installer: &LocalInstaller{ InstallDir: filepath.Join(ns.Dir(), versionsDirName), TargetServiceFile: ns.serviceFile, @@ -209,6 +211,8 @@ type Updater struct { UpdateConfigFile string // TeleportConfigFile contains the path to Teleport's configuration. TeleportConfigFile string + // TeleportServiceName contains the full name of the systemd service for Teleport + TeleportServiceName string // DefaultProxyAddr contains Teleport's proxy address. This may differ from the updater's. DefaultProxyAddr string // DefaultPathDir contains the default path that Teleport binaries should be installed into. @@ -953,15 +957,18 @@ func (u *Updater) notices(ctx context.Context) error { } if !enabled && active { u.Log.WarnContext(ctx, "Teleport is installed and started, but not configured to start on boot.") - u.Log.WarnContext(ctx, "After configuring teleport.yaml, you can enable it with: systemctl enable teleport") + u.Log.WarnContext(ctx, "After configuring teleport.yaml, you must enable it.", + "command", fmt.Sprintf("systemctl enable %s", u.TeleportServiceName)) } if !active && enabled { u.Log.WarnContext(ctx, "Teleport is installed and enabled at boot, but not running.") - u.Log.WarnContext(ctx, "After configuring teleport.yaml, you can start it with: systemctl start teleport") + u.Log.WarnContext(ctx, "After configuring teleport.yaml, you must start it.", + "command", fmt.Sprintf("systemctl start %s", u.TeleportServiceName)) } if !active && !enabled { u.Log.WarnContext(ctx, "Teleport is installed, but not running or enabled at boot.") - u.Log.WarnContext(ctx, "After configuring teleport.yaml, you can enable and start it with: systemctl enable teleport --now") + u.Log.WarnContext(ctx, "After configuring teleport.yaml, you must enable and start.", + "command", fmt.Sprintf("systemctl enable %s --now", u.TeleportServiceName)) } return nil diff --git a/tool/teleport-update/main.go b/tool/teleport-update/main.go index eaeeb568e9dd2..958504c472c6a 100644 --- a/tool/teleport-update/main.go +++ b/tool/teleport-update/main.go @@ -184,10 +184,14 @@ func Run(args []string) int { return 1 } - // Set required umask for commands that write files to system directories as root, and warn loudly if it changes. switch command { case statusCmd.FullCommand(), versionCmd.FullCommand(): default: + if os.Geteuid() != 0 { + plog.ErrorContext(ctx, "This command must be run as root. Try running with sudo.") + return 1 + } + // Set required umask for commands that write files to system directories as root, and warn loudly if it changes. autoupdate.SetRequiredUmask(ctx, plog) } From 0fdf2ec949f3100295a26191893534b71d090019 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 11 Mar 2025 01:36:03 -0400 Subject: [PATCH 04/11] check extra case --- lib/autoupdate/agent/updater.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 7ff49d803ae5a..dd62df07726a5 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -455,8 +455,14 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { } // Do not link system package installation if the installation we are removing - // is not installed into /usr/local/bin. + // is not installed into /usr/local/bin. In this case, we also need to make sure + // it is clear we are not going to recover the package's systemd service if it + // was overwritten. if filepath.Clean(cfg.Spec.Path) != filepath.Clean(defaultPathDir) { + if u.TeleportServiceName == serviceName && !force { + u.Log.ErrorContext(ctx, "Default Teleport systemd service would be removed, and --force was not passed. Refusing to remove Teleport from this system.") + return trace.Errorf("unable to remove Teleport completely without --force") + } return u.removeWithoutSystem(ctx, cfg) } revert, err := u.Installer.LinkSystem(ctx) From c2be65d01ca48c180bf045f51b34b35636e97d63 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 11 Mar 2025 01:40:05 -0400 Subject: [PATCH 05/11] cleanup --- lib/autoupdate/agent/updater.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index dd62df07726a5..45b6f25be9cdb 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -86,11 +86,6 @@ func warnUmask(ctx context.Context, log *slog.Logger, old int) { } } -var ( - // ErrNotInstalled is returned when Teleport is not installed. - ErrNotInstalled = trace.Errorf("not installed") -) - // NewLocalUpdater returns a new Updater that auto-updates local // installations of the Teleport agent. // The AutoUpdater uses an HTTP client with sane defaults for downloads, and @@ -283,6 +278,8 @@ var ( ErrNoBinaries = errors.New("no binaries available to link") // ErrFilePresent is returned when a file is present. ErrFilePresent = errors.New("file present") + // ErrNotInstalled is returned when Teleport is not installed. + ErrNotInstalled = trace.Errorf("not installed") ) // Process provides an API for interacting with a running Teleport process. From 65cde299102c899f44e1d9cc377e9553535a18bd Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 11 Mar 2025 01:44:22 -0400 Subject: [PATCH 06/11] extra warning --- lib/autoupdate/agent/updater.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 45b6f25be9cdb..d16ad5251dc01 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -459,6 +459,8 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { if u.TeleportServiceName == serviceName && !force { u.Log.ErrorContext(ctx, "Default Teleport systemd service would be removed, 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, "Default Teleport systemd service would be removed since --force was passed. Teleport will be removed from this system.") } return u.removeWithoutSystem(ctx, cfg) } From cb88c4aec9efc9733bbd654656846897757938cf Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 11 Mar 2025 01:57:09 -0400 Subject: [PATCH 07/11] tests --- lib/autoupdate/agent/updater_test.go | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/lib/autoupdate/agent/updater_test.go b/lib/autoupdate/agent/updater_test.go index cab4e36f20691..dc2878ee1766f 100644 --- a/lib/autoupdate/agent/updater_test.go +++ b/lib/autoupdate/agent/updater_test.go @@ -1058,6 +1058,7 @@ func TestUpdater_Remove(t *testing.T) { reloadErr error processActive bool force bool + serviceName string unlinkedVersion string teardownCalls int @@ -1163,6 +1164,53 @@ func TestUpdater_Remove(t *testing.T) { teardownCalls: 1, force: true, }, + { + name: "no system links, process disabled, custom path, force", + cfg: &UpdateConfig{ + Version: updateConfigVersion, + Kind: updateConfigKind, + Spec: UpdateSpec{ + Path: "custom", + }, + Status: UpdateStatus{ + Active: NewRevision(version, 0), + }, + }, + unlinkedVersion: version, + teardownCalls: 1, + force: true, + }, + { + name: "no system links, process disabled, custom path, no force", + cfg: &UpdateConfig{ + Version: updateConfigVersion, + Kind: updateConfigKind, + Spec: UpdateSpec{ + Path: "custom", + }, + Status: UpdateStatus{ + Active: NewRevision(version, 0), + }, + }, + errMatch: "unable to remove", + }, + { + name: "no system links, process disabled, custom path, no force, custom service", + cfg: &UpdateConfig{ + Version: updateConfigVersion, + Kind: updateConfigKind, + Spec: UpdateSpec{ + Path: "custom", + }, + Status: UpdateStatus{ + Active: NewRevision(version, 0), + }, + }, + serviceName: "custom", + unlinkedVersion: version, + teardownCalls: 1, + force: true, + }, { name: "active version", cfg: &UpdateConfig{ @@ -1268,6 +1316,10 @@ func TestUpdater_Remove(t *testing.T) { InsecureSkipVerify: true, }, ns) require.NoError(t, err) + updater.TeleportServiceName = serviceName + if tt.serviceName != "" { + updater.TeleportServiceName = tt.serviceName + } // Create config file only if provided in test case if tt.cfg != nil { From 04b14d296536e05b09da335aaad2368619e7ad43 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 11 Mar 2025 12:21:00 -0400 Subject: [PATCH 08/11] feedback --- lib/autoupdate/agent/updater.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index d16ad5251dc01..baaf8d907d417 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -23,7 +23,6 @@ import ( "crypto/tls" "crypto/x509" "errors" - "fmt" "log/slog" "net/http" "os" @@ -456,11 +455,13 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { // it is clear we are not going to recover the package's systemd service if it // was overwritten. if filepath.Clean(cfg.Spec.Path) != filepath.Clean(defaultPathDir) { - if u.TeleportServiceName == serviceName && !force { - u.Log.ErrorContext(ctx, "Default Teleport systemd service would be removed, 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, "Default Teleport systemd service would be removed since --force was passed. Teleport will be removed from this system.") + if u.TeleportServiceName == serviceName { + if !force { + u.Log.ErrorContext(ctx, "Default Teleport systemd service would be removed, 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, "Default Teleport systemd service will be removed since --force was passed. Teleport will be removed from this system.") + } } return u.removeWithoutSystem(ctx, cfg) } @@ -963,17 +964,17 @@ func (u *Updater) notices(ctx context.Context) error { if !enabled && active { u.Log.WarnContext(ctx, "Teleport is installed and started, but not configured to start on boot.") u.Log.WarnContext(ctx, "After configuring teleport.yaml, you must enable it.", - "command", fmt.Sprintf("systemctl enable %s", u.TeleportServiceName)) + "command", "systemctl enable "+u.TeleportServiceName) } if !active && enabled { u.Log.WarnContext(ctx, "Teleport is installed and enabled at boot, but not running.") u.Log.WarnContext(ctx, "After configuring teleport.yaml, you must start it.", - "command", fmt.Sprintf("systemctl start %s", u.TeleportServiceName)) + "command", "systemctl start "+u.TeleportServiceName) } if !active && !enabled { u.Log.WarnContext(ctx, "Teleport is installed, but not running or enabled at boot.") u.Log.WarnContext(ctx, "After configuring teleport.yaml, you must enable and start.", - "command", fmt.Sprintf("systemctl enable %s --now", u.TeleportServiceName)) + "command", "systemctl enable --now "+u.TeleportServiceName) } return nil From d77cd2d7192c884a9ab7913ee8107238497c54ec Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Tue, 11 Mar 2025 22:34:13 -0400 Subject: [PATCH 09/11] add newlines --- lib/autoupdate/agent/updater.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index baaf8d907d417..61e4f065e7bfe 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -457,10 +457,12 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { if filepath.Clean(cfg.Spec.Path) != filepath.Clean(defaultPathDir) { if u.TeleportServiceName == serviceName { if !force { - u.Log.ErrorContext(ctx, "Default Teleport systemd service would be removed, and --force was not passed. Refusing to remove Teleport from this system.") + u.Log.ErrorContext(ctx, "Default Teleport systemd service would be removed, and --force was not passed.") + u.Log.ErrorContext(ctx, "Refusing to remove Teleport from this system.") return trace.Errorf("unable to remove Teleport completely without --force") } else { - u.Log.WarnContext(ctx, "Default Teleport systemd service will be removed since --force was passed. Teleport will be removed from this system.") + u.Log.WarnContext(ctx, "Default Teleport systemd service will be removed since --force was passed.") + u.Log.WarnContext(ctx, "Teleport will be removed from this system.") } } return u.removeWithoutSystem(ctx, cfg) @@ -468,10 +470,12 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { revert, err := u.Installer.LinkSystem(ctx) if errors.Is(err, ErrNoBinaries) { 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.") + u.Log.ErrorContext(ctx, "No packaged installation of Teleport was found, and --force was not passed.") + u.Log.ErrorContext(ctx, "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.WarnContext(ctx, "No packaged installation of Teleport was found, and --force was passed.") + u.Log.WarnContext(ctx, "Teleport will be removed from this system.") } return u.removeWithoutSystem(ctx, cfg) } @@ -479,7 +483,8 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { return trace.Wrap(err, "failed to link") } - u.Log.InfoContext(ctx, "Updater-managed installation of Teleport detected. Restoring packaged version of Teleport before removing.") + u.Log.InfoContext(ctx, "Updater-managed installation of Teleport detected.") + u.Log.InfoContext(ctx, "Restoring packaged version of Teleport before removing.") revertConfig := func(ctx context.Context) bool { if ok := revert(ctx); !ok { @@ -525,7 +530,8 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { u.Log.ErrorContext(ctx, "Reverting symlinks due to failed restart.") if ok := revertConfig(ctx); ok { if err := u.Process.Reload(ctx); err != nil && !errors.Is(err, ErrNotNeeded) { - u.Log.ErrorContext(ctx, "Failed to reload Teleport after reverting. Installation likely broken.", errorKey, err) + u.Log.ErrorContext(ctx, "Failed to reload Teleport after reverting.", errorKey, err) + u.Log.ErrorContext(ctx, "Installation likely broken.") } else { u.Log.WarnContext(ctx, "Teleport updater detected an error with the new installation and successfully reverted it.") } @@ -541,7 +547,8 @@ func (u *Updater) Remove(ctx context.Context, force bool) error { } func (u *Updater) removeWithoutSystem(ctx context.Context, cfg *UpdateConfig) error { - u.Log.InfoContext(ctx, "Updater-managed installation of Teleport detected. Attempting to unlink and remove.") + u.Log.InfoContext(ctx, "Updater-managed installation of Teleport detected.") + u.Log.InfoContext(ctx, "Attempting to unlink and remove.") ok, err := u.Process.IsActive(ctx) if err != nil && !errors.Is(err, ErrNotSupported) { return trace.Wrap(err) From d437911c65dee8af0b82918f204784df8317d616 Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Wed, 12 Mar 2025 12:47:36 -0400 Subject: [PATCH 10/11] adjust message --- tool/teleport-update/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/teleport-update/main.go b/tool/teleport-update/main.go index 958504c472c6a..a9120a6523d84 100644 --- a/tool/teleport-update/main.go +++ b/tool/teleport-update/main.go @@ -465,7 +465,7 @@ func cmdStatus(ctx context.Context, ccfg *cliConfig) error { return trace.Wrap(err, "failed to get status") } if errors.Is(err, autoupdate.ErrNotInstalled) { - plog.InfoContext(ctx, "Teleport is not installed.") + plog.InfoContext(ctx, "Teleport is not installed by teleport-update with this suffix.") return nil } enc := yaml.NewEncoder(os.Stdout) From 48065eedcd444195f64e832dc5f6304da4dbe52f Mon Sep 17 00:00:00 2001 From: Stephen Levine Date: Wed, 12 Mar 2025 13:51:57 -0400 Subject: [PATCH 11/11] consistent error type --- lib/autoupdate/agent/updater.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 61e4f065e7bfe..a036b676cba5e 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -278,7 +278,7 @@ var ( // ErrFilePresent is returned when a file is present. ErrFilePresent = errors.New("file present") // ErrNotInstalled is returned when Teleport is not installed. - ErrNotInstalled = trace.Errorf("not installed") + ErrNotInstalled = errors.New("not installed") ) // Process provides an API for interacting with a running Teleport process.