diff --git a/internal/pkg/agent/application/upgrade/upgrade.go b/internal/pkg/agent/application/upgrade/upgrade.go index 8bf7563f7c..e7e14c8784 100644 --- a/internal/pkg/agent/application/upgrade/upgrade.go +++ b/internal/pkg/agent/application/upgrade/upgrade.go @@ -163,6 +163,17 @@ func (av agentVersion) String() string { func (u *Upgrader) Upgrade(ctx context.Context, version string, sourceURI string, action *fleetapi.ActionUpgrade, det *details.Details, skipVerifyOverride bool, skipDefaultPgp bool, pgpBytes ...string) (_ reexec.ShutdownCallbackFn, err error) { u.log.Infow("Upgrading agent", "version", version, "source_uri", sourceURI) + currentVersion := agentVersion{ + version: release.Version(), + snapshot: release.Snapshot(), + hash: release.Commit(), + } + + if isSameReleaseVersion(currentVersion, version) { + u.log.Warnf("Upgrade action skipped because agent is already at version %s", currentVersion) + return nil, ErrUpgradeSameVersion + } + // Inform the Upgrade Marker Watcher that we've started upgrading. Note that this // is only possible to do in-memory since, today, the process that's initiating // the upgrade is the same as the Agent process in which the Upgrade Marker Watcher is @@ -207,12 +218,6 @@ func (u *Upgrader) Upgrade(ctx context.Context, version string, sourceURI string return nil, fmt.Errorf("reading metadata for elastic agent version %s package %q: %w", version, archivePath, err) } - currentVersion := agentVersion{ - version: release.Version(), - snapshot: release.Snapshot(), - hash: release.Commit(), - } - same, newVersion := isSameVersion(u.log, currentVersion, metadata, version) if same { u.log.Warnf("Upgrade action skipped because agent is already at version %s", currentVersion) @@ -628,3 +633,17 @@ func IsInProgress(c client.Client, watcherPIDsFetcher func() ([]int, error)) (bo return state.State == cproto.State_UPGRADING, nil } + +// isSameReleaseVersion will if upgradeVersion and currentVersion are equal using only release numbers. +// They are not equal if either are a SNAPSHOT, or if the semver numbers (including prerelease and build identifiers) differ. +func isSameReleaseVersion(current agentVersion, upgradeVersion string) bool { + if current.snapshot { + return false + } + target, _ := agtversion.ParseVersion(upgradeVersion) + targetVersion, targetSnapshot := target.ExtractSnapshotFromVersionString() + if targetSnapshot { + return false + } + return current.version == targetVersion +} diff --git a/internal/pkg/agent/application/upgrade/upgrade_test.go b/internal/pkg/agent/application/upgrade/upgrade_test.go index eefb8f7fe9..10864d50b9 100644 --- a/internal/pkg/agent/application/upgrade/upgrade_test.go +++ b/internal/pkg/agent/application/upgrade/upgrade_test.go @@ -1000,3 +1000,60 @@ func Test_selectWatcherExecutable(t *testing.T) { }) } } + +func TestIsSameReleaseVersion(t *testing.T) { + tests := []struct { + name string + current agentVersion + target string + expect bool + }{{ + name: "current version is snapshot", + current: agentVersion{ + version: "1.2.3", + snapshot: true, + }, + target: "1.2.3", + expect: false, + }, { + name: "target version is snapshot", + current: agentVersion{ + version: "1.2.3", + }, + target: "1.2.3-SNAPSHOT", + expect: false, + }, { + name: "target version is different version", + current: agentVersion{ + version: "1.2.3", + }, + target: "1.2.4", + expect: false, + }, { + name: "target version is same with pre-release", + current: agentVersion{ + version: "1.2.3", + }, + target: "1.2.3-custom.info", + expect: false, + }, { + name: "target version is same with build", + current: agentVersion{ + version: "1.2.3", + }, + target: "1.2.3+buildID", + expect: false, + }, { + name: "target version is same", + current: agentVersion{ + version: "1.2.3", + }, + target: "1.2.3", + expect: true, + }} + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expect, isSameReleaseVersion(tc.current, tc.target)) + }) + } +}