[8.6] [Fleet] fix for rolling upgrade for <=2h (#148502)

## Summary

Fix for rolling upgrade in 8.6 branch. 
Related:
https://github.com/elastic/ingest-dev/issues/1278#issuecomment-1372100383
Related:
https://github.com/elastic/kibana/pull/148240#discussion_r1060630064

When Maintenance window was set to 1h or 2h, all agents started to
upgrade immediately.
This is because Fleet Server calculated the rollout period from `start :
expiration - minDur (2h)`.
For 1 and 2h, expiration was set to `start + dur`, so the period was set
to 0. As a fix, added a longer expiration for these cases (`2 * dur`).

Only adding this fix for 8.6, as the feature changes in 8.7.

When choosing 1 or 2h, 1 agent starts to upgrade immediately, and the
rest will be scheduled later.
Aborting works for the remaining agents.

<img width="1041" alt="image"
src="https://user-images.githubusercontent.com/90178898/211026957-4abc6120-defd-4bfd-8b2d-b9ade9cd5b57.png">


### Checklist

- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Julia Bardi 2023-01-09 12:19:59 +01:00 committed by GitHub
parent 0eed9f3db5
commit 631a12ba3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 6 deletions

View file

@ -13,6 +13,7 @@ import { createAppContextStartContractMock } from '../../mocks';
import { sendUpgradeAgentsActions } from './upgrade';
import { createClientMock } from './action.mock';
import { getRollingUpgradeOptions } from './upgrade_action_runner';
describe('sendUpgradeAgentsActions (plural)', () => {
beforeEach(async () => {
@ -102,3 +103,45 @@ describe('sendUpgradeAgentsActions (plural)', () => {
}
});
});
describe('getRollingUpgradeOptions', () => {
it('should set longer expiration for 1h duration', () => {
const options = getRollingUpgradeOptions('2023-01-06T00:00:00Z', 3600);
expect(options).toEqual({
expiration: '2023-01-06T02:00:00.000Z',
minimum_execution_duration: 3600,
start_time: '2023-01-06T00:00:00Z',
});
});
it('should set longer expiration for 2h duration', () => {
const options = getRollingUpgradeOptions('2023-01-06T00:00:00Z', 7200);
expect(options).toEqual({
expiration: '2023-01-06T04:00:00.000Z',
minimum_execution_duration: 7200,
start_time: '2023-01-06T00:00:00Z',
});
});
it('should set normal expiration for longer duration', () => {
const options = getRollingUpgradeOptions('2023-01-06T00:00:00Z', 36000);
expect(options).toEqual({
expiration: '2023-01-06T10:00:00.000Z',
minimum_execution_duration: 7200,
start_time: '2023-01-06T00:00:00Z',
});
});
it('should set min expiration for no duration', () => {
const options = getRollingUpgradeOptions('2023-01-06T00:00:00Z');
expect(options).toEqual({
expiration: '2023-01-06T02:00:00.000Z',
minimum_execution_duration: 7200,
start_time: '2023-01-06T00:00:00Z',
});
});
it('should return empty options for no start time, no duration', () => {
const options = getRollingUpgradeOptions();
expect(options).toEqual({});
});
});

View file

@ -148,18 +148,24 @@ export async function upgradeBatch(
const MINIMUM_EXECUTION_DURATION_SECONDS = 60 * 60 * 2; // 2h
const getRollingUpgradeOptions = (startTime?: string, upgradeDurationSeconds?: number) => {
export const getRollingUpgradeOptions = (startTime?: string, upgradeDurationSeconds?: number) => {
const now = new Date().toISOString();
// Perform a rolling upgrade
if (upgradeDurationSeconds) {
const minExecutionDuration = Math.min(
MINIMUM_EXECUTION_DURATION_SECONDS,
upgradeDurationSeconds
);
return {
start_time: startTime ?? now,
minimum_execution_duration: Math.min(
MINIMUM_EXECUTION_DURATION_SECONDS,
upgradeDurationSeconds
),
minimum_execution_duration: minExecutionDuration,
expiration: moment(startTime ?? now)
.add(upgradeDurationSeconds, 'seconds')
.add(
upgradeDurationSeconds <= MINIMUM_EXECUTION_DURATION_SECONDS
? minExecutionDuration * 2
: upgradeDurationSeconds,
'seconds'
)
.toISOString(),
};
}