[teleport-update] update --now (#49807)

* update --now

* testdata
This commit is contained in:
Stephen Levine
2024-12-05 20:00:09 +00:00
committed by GitHub
parent 8e723cc7ff
commit f7bf7eb086
4 changed files with 58 additions and 8 deletions
@@ -0,0 +1,13 @@
version: v1
kind: update_config
spec:
proxy: localhost
group: group
url_template: https://example.com
enabled: true
pinned: false
status:
active:
version: 16.3.0
backup:
version: old-version
+14 -6
View File
@@ -501,7 +501,7 @@ func (u *Updater) Unpin(ctx context.Context) error {
// Otherwise, the auto-updates configuration is not changed.
// Unlike Enable, Update will not validate or repair the current version.
// This function is idempotent.
func (u *Updater) Update(ctx context.Context) error {
func (u *Updater) Update(ctx context.Context, now bool) error {
// Read configuration from update.yaml and override any new values passed as flags.
cfg, err := readConfig(u.ConfigPath)
if err != nil {
@@ -536,7 +536,7 @@ func (u *Updater) Update(ctx context.Context) error {
// If a version fails and is marked skip, we ignore any edition changes as well.
// If a cluster is broadcasting a version that failed to start, changing ent/fips is unlikely to fix the issue.
if !resp.InWindow {
if !resp.InWindow && !now {
switch {
case target.Version == "":
u.Log.WarnContext(ctx, "Cannot determine target agent version. Waiting for both version and update window.")
@@ -552,18 +552,26 @@ func (u *Updater) Update(ctx context.Context) error {
switch {
case target.Version == "":
u.Log.ErrorContext(ctx, "Update window is active, but target version is not available.", activeKey, active)
if resp.InWindow {
u.Log.ErrorContext(ctx, "Update window is active, but target version is not available.", activeKey, active)
}
return trace.Errorf("target version missing")
case target == active:
u.Log.InfoContext(ctx, "Teleport is up-to-date. Update window is active, but no action is needed.", activeKey, active)
if resp.InWindow {
u.Log.InfoContext(ctx, "Teleport is up-to-date. Update window is active, but no action is needed.", activeKey, active)
} else {
u.Log.InfoContext(ctx, "Teleport is up-to-date. No action is needed.", activeKey, active)
}
return nil
case target.Version == skip.Version:
u.Log.InfoContext(ctx, "Update available, but the new version is marked as broken. Skipping update during the update window.", targetKey, target, activeKey, active)
u.Log.InfoContext(ctx, "Update available, but the new version is marked as broken. Skipping update.", targetKey, target, activeKey, active)
return nil
default:
u.Log.InfoContext(ctx, "Update available. Initiating update.", targetKey, target, activeKey, active)
}
time.Sleep(resp.Jitter)
if !now {
time.Sleep(resp.Jitter)
}
updateErr := u.update(ctx, cfg, target)
writeErr := writeConfig(u.ConfigPath, cfg)
+26 -1
View File
@@ -223,6 +223,7 @@ func TestUpdater_Update(t *testing.T) {
cfg *UpdateConfig // nil -> file not present
flags InstallFlags
inWindow bool
now bool
installErr error
setupErr error
reloadErr error
@@ -261,6 +262,30 @@ func TestUpdater_Update(t *testing.T) {
reloadCalls: 1,
setupCalls: 1,
},
{
name: "updates enabled now",
cfg: &UpdateConfig{
Version: updateConfigVersion,
Kind: updateConfigKind,
Spec: UpdateSpec{
Group: "group",
URLTemplate: "https://example.com",
Enabled: true,
},
Status: UpdateStatus{
Active: NewRevision("old-version", 0),
},
},
now: true,
removedRevisions: []Revision{NewRevision("unknown-version", 0)},
installedRevision: NewRevision("16.3.0", 0),
installedTemplate: "https://example.com",
linkedRevision: NewRevision("16.3.0", 0),
requestGroup: "group",
reloadCalls: 1,
setupCalls: 1,
},
{
name: "updates disabled during window",
cfg: &UpdateConfig{
@@ -627,7 +652,7 @@ func TestUpdater_Update(t *testing.T) {
}
ctx := context.Background()
err = updater.Update(ctx)
err = updater.Update(ctx, tt.now)
if tt.errMatch != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.errMatch)
+5 -1
View File
@@ -80,6 +80,8 @@ type cliConfig struct {
InstallSuffix string
// SelfSetup mode for using the current version of the teleport-update to setup the update service.
SelfSetup bool
// UpdateNow forces an immediate update.
UpdateNow bool
}
func Run(args []string) int {
@@ -136,6 +138,8 @@ func Run(args []string) int {
unpinCmd := app.Command("unpin", "Unpin the current version, allowing it to be updated.")
updateCmd := app.Command("update", "Update the agent to the latest version, if a new version is available.")
updateCmd.Flag("now", "Force immediate update even if update window is not active.").
Short('n').BoolVar(&ccfg.UpdateNow)
updateCmd.Flag("self-setup", "Use the current teleport-update binary to create systemd service config for auto-updates.").
Short('s').Hidden().BoolVar(&ccfg.SelfSetup)
@@ -345,7 +349,7 @@ func cmdUpdate(ctx context.Context, ccfg *cliConfig) error {
}
}()
if err := updater.Update(ctx); err != nil {
if err := updater.Update(ctx, ccfg.UpdateNow); err != nil {
return trace.Wrap(err)
}
return nil