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
1 change: 1 addition & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ packages:
interfaces:
WatcherHelper: {}
watcherGrappler: {}
availableRollbacksSource: {}
github.com/elastic/elastic-agent/internal/pkg/agent/cmd:
interfaces:
agentWatcher: {}
Expand Down
12 changes: 10 additions & 2 deletions internal/pkg/agent/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func New(
fleetInitTimeout time.Duration,
disableMonitoring bool,
override CfgOverrider,
initialUpgradeDetails *details.Details,
initialUpdateMarker *upgrade.UpdateMarker,
modifiers ...component.PlatformModifier,
) (*coordinator.Coordinator, coordinator.ConfigManager, composable.Controller, error) {

Expand Down Expand Up @@ -129,7 +129,9 @@ func New(

// monitoring is not supported in bootstrap mode https://github.com/elastic/elastic-agent/issues/1761
isMonitoringSupported := !disableMonitoring && cfg.Settings.V1MonitoringEnabled
upgrader, err := upgrade.NewUpgrader(log, cfg.Settings.DownloadConfig, cfg.Settings.Upgrade, agentInfo, new(upgrade.AgentWatcherHelper))

availableRollbacksSource := upgrade.NewTTLMarkerRegistry(log, paths.Top())
upgrader, err := upgrade.NewUpgrader(log, cfg.Settings.DownloadConfig, cfg.Settings.Upgrade, agentInfo, new(upgrade.AgentWatcherHelper), availableRollbacksSource)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to create upgrader: %w", err)
}
Expand All @@ -153,6 +155,12 @@ func New(
return nil, nil, nil, fmt.Errorf("failed to initialize runtime manager: %w", err)
}

// prepare initialUpgradeDetails for injecting it in coordinator later on
var initialUpgradeDetails *details.Details
if initialUpdateMarker != nil && initialUpdateMarker.Details != nil {
initialUpgradeDetails = initialUpdateMarker.Details
}

var configMgr coordinator.ConfigManager
var managed *managedConfigManager
var compModifiers = []coordinator.ComponentsModifier{InjectAPMConfig}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,8 @@ func TestCoordinatorReportsInvalidPolicy(t *testing.T) {
}
}()

upgradeMgr, err := upgrade.NewUpgrader(log, &artifact.Config{}, nil, &info.AgentInfo{}, new(upgrade.AgentWatcherHelper))
tmpDir := t.TempDir()
upgradeMgr, err := upgrade.NewUpgrader(log, &artifact.Config{}, nil, &info.AgentInfo{}, new(upgrade.AgentWatcherHelper), upgrade.NewTTLMarkerRegistry(nil, tmpDir))
require.NoError(t, err, "errored when creating a new upgrader")

// Channels have buffer length 1, so we don't have to run on multiple
Expand Down
133 changes: 133 additions & 0 deletions internal/pkg/agent/application/upgrade/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/pkg/agent/application/upgrade/rollback_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,6 @@ func createUpdateMarker(t *testing.T, log *logger.Logger, topDir, newAgentVersio
time.Now(),
newAgentInstall,
oldAgentInstall,
nil, nil, disableRollbackWindow)
nil, nil, nil)
require.NoError(t, err, "error writing fake update marker")
}
43 changes: 15 additions & 28 deletions internal/pkg/agent/application/upgrade/step_mark.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ import (
const markerFilename = ".update-marker"
const disableRollbackWindow = time.Duration(0)

// RollbackAvailable identifies an elastic-agent install available for rollback
type RollbackAvailable struct {
// TTLMarker marks an elastic-agent install available for rollback
type TTLMarker struct {
Version string `json:"version" yaml:"version"`
Home string `json:"home" yaml:"home"`
ValidUntil time.Time `json:"valid_until" yaml:"valid_until"`
}

Expand Down Expand Up @@ -55,7 +54,7 @@ type UpdateMarker struct {

Details *details.Details `json:"details,omitempty" yaml:"details,omitempty"`

RollbacksAvailable []RollbackAvailable `json:"rollbacks_available,omitempty" yaml:"rollbacks_available,omitempty"`
RollbacksAvailable map[string]TTLMarker `json:"rollbacks_available,omitempty" yaml:"rollbacks_available,omitempty"`
}

// GetActionID returns the Fleet Action ID associated with the
Expand Down Expand Up @@ -112,7 +111,7 @@ type updateMarkerSerializer struct {
Acked bool `yaml:"acked"`
Action *MarkerActionUpgrade `yaml:"action"`
Details *details.Details `yaml:"details"`
RollbacksAvailable []RollbackAvailable `yaml:"rollbacks_available,omitempty"`
RollbacksAvailable map[string]TTLMarker `yaml:"rollbacks_available,omitempty"`
}

func newMarkerSerializer(m *UpdateMarker) *updateMarkerSerializer {
Expand Down Expand Up @@ -142,35 +141,23 @@ type updateActiveCommitFunc func(log *logger.Logger, topDirPath, hash string, wr

// markUpgrade marks update happened so we can handle grace period
func markUpgradeProvider(updateActiveCommit updateActiveCommitFunc, writeFile writeFileFunc) markUpgradeFunc {
return func(log *logger.Logger, dataDirPath string, updatedOn time.Time, agent, previousAgent agentInstall, action *fleetapi.ActionUpgrade, upgradeDetails *details.Details, rollbackWindow time.Duration) error {
return func(log *logger.Logger, dataDirPath string, updatedOn time.Time, agent, previousAgent agentInstall, action *fleetapi.ActionUpgrade, upgradeDetails *details.Details, availableRollbacks map[string]TTLMarker) error {

if len(previousAgent.hash) > hashLen {
previousAgent.hash = previousAgent.hash[:hashLen]
}

marker := &UpdateMarker{
Version: agent.version,
Hash: agent.hash,
VersionedHome: agent.versionedHome,
UpdatedOn: updatedOn,
PrevVersion: previousAgent.version,
PrevHash: previousAgent.hash,
PrevVersionedHome: previousAgent.versionedHome,
Action: action,
Details: upgradeDetails,
}

if rollbackWindow > disableRollbackWindow && agent.parsedVersion != nil && !agent.parsedVersion.Less(*Version_9_2_0_SNAPSHOT) {
// if we have a not empty rollback window, write the prev version in the rollbacks_available field
// we also need to check the destination version because the manual rollback and delayed cleanup will be
// handled by that version of agent, so it needs to be recent enough
marker.RollbacksAvailable = []RollbackAvailable{
{
Version: previousAgent.version,
Home: previousAgent.versionedHome,
ValidUntil: updatedOn.Add(rollbackWindow),
},
}
Version: agent.version,
Hash: agent.hash,
VersionedHome: agent.versionedHome,
UpdatedOn: updatedOn,
PrevVersion: previousAgent.version,
PrevHash: previousAgent.hash,
PrevVersionedHome: previousAgent.versionedHome,
Action: action,
Details: upgradeDetails,
RollbacksAvailable: availableRollbacks,
}

markerBytes, err := yaml.Marshal(newMarkerSerializer(marker))
Expand Down
Loading