Skip to content

Commit 814c11e

Browse files
jaalah-akamaijaalahdmcintyr-akamai
authored
upcoming: [M3-10708] - Display maintenance type and config in linode_migrate event messages (#13084)
* upcoming: [M3-10708] - Enhance Linode Migration Event Messages with Maintenance Type and Config Information * Add two changesets * Use the field for upcoming tables start date * add max reason constant --------- Co-authored-by: Jaalah Ramos <[email protected]> Co-authored-by: dmcintyr-akamai <[email protected]>
1 parent a28d980 commit 814c11e

File tree

9 files changed

+250
-32
lines changed

9 files changed

+250
-32
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/api-v4": Changed
3+
---
4+
5+
Use v4beta endpoints for /events and /events/<eventId> ([#13084](https://github.com/linode/manager/pull/13084))

packages/api-v4/src/account/events.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { API_ROOT } from '../constants';
1+
import { API_ROOT, BETA_API_ROOT } from '../constants';
22
import Request, { setMethod, setParams, setURL, setXFilter } from '../request';
33

44
import type { Filter, Params, ResourcePage } from '../types';
@@ -12,7 +12,7 @@ import type { Event, Notification } from './types';
1212
*/
1313
export const getEvents = (params: Params = {}, filter: Filter = {}) =>
1414
Request<ResourcePage<Event>>(
15-
setURL(`${API_ROOT}/account/events`),
15+
setURL(`${BETA_API_ROOT}/account/events`),
1616
setMethod('GET'),
1717
setXFilter(filter),
1818
setParams(params),
@@ -26,7 +26,7 @@ export const getEvents = (params: Params = {}, filter: Filter = {}) =>
2626
*/
2727
export const getEvent = (eventId: number) =>
2828
Request<Event>(
29-
setURL(`${API_ROOT}/account/events/${encodeURIComponent(eventId)}`),
29+
setURL(`${BETA_API_ROOT}/account/events/${encodeURIComponent(eventId)}`),
3030
setMethod('GET'),
3131
);
3232

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
Display maintenance type (emergency/scheduled) and config information in linode_migrate event messages ([#13084](https://github.com/linode/manager/pull/13084))

packages/manager/src/dev-tools/components/ExtraPresetEvents.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,65 @@ const eventTemplates = {
287287
status: 'finished',
288288
}),
289289

290+
'Linode Migration In Progress': () =>
291+
eventFactory.build({
292+
action: 'linode_migrate',
293+
entity: {
294+
id: 1,
295+
label: 'linode-1',
296+
type: 'linode',
297+
url: '/v4/linode/instances/1',
298+
},
299+
message: 'Linode migration in progress.',
300+
percent_complete: 45,
301+
status: 'started',
302+
}),
303+
304+
'Linode Migration - Emergency': () =>
305+
eventFactory.build({
306+
action: 'linode_migrate',
307+
description: 'emergency',
308+
entity: {
309+
id: 1,
310+
label: 'linode-1',
311+
type: 'linode',
312+
url: '/v4/linode/instances/1',
313+
},
314+
message: 'Emergency linode migration in progress.',
315+
percent_complete: 30,
316+
status: 'started',
317+
}),
318+
319+
'Linode Migration - Scheduled Started': () =>
320+
eventFactory.build({
321+
action: 'linode_migrate',
322+
description: 'scheduled',
323+
entity: {
324+
id: 1,
325+
label: 'linode-1',
326+
type: 'linode',
327+
url: '/v4/linode/instances/1',
328+
},
329+
message: 'Scheduled linode migration in progress.',
330+
percent_complete: 10,
331+
status: 'started',
332+
}),
333+
334+
'Linode Migration - Scheduled': () =>
335+
eventFactory.build({
336+
action: 'linode_migrate',
337+
description: 'scheduled',
338+
entity: {
339+
id: 1,
340+
label: 'linode-1',
341+
type: 'linode',
342+
url: '/v4/linode/instances/1',
343+
},
344+
message: 'Scheduled linode migration in progress.',
345+
percent_complete: 0,
346+
status: 'scheduled',
347+
}),
348+
290349
'Completed Event': () =>
291350
eventFactory.build({
292351
action: 'account_update',

packages/manager/src/dev-tools/components/ExtraPresetMaintenance.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,42 @@ const maintenanceTemplates = {
210210
Canceled: () => accountMaintenanceFactory.build({ status: 'canceled' }),
211211
Completed: () => accountMaintenanceFactory.build({ status: 'completed' }),
212212
'In Progress': () =>
213-
accountMaintenanceFactory.build({ status: 'in_progress' }),
213+
accountMaintenanceFactory.build({
214+
status: 'in_progress',
215+
entity: {
216+
type: 'linode',
217+
id: 1,
218+
label: 'linode-1',
219+
url: '/v4/linode/instances/1',
220+
},
221+
type: 'migrate',
222+
}),
223+
'In Progress - Emergency Migration': () =>
224+
accountMaintenanceFactory.build({
225+
status: 'in_progress',
226+
entity: {
227+
type: 'linode',
228+
id: 1,
229+
label: 'linode-1',
230+
url: '/v4/linode/instances/1',
231+
},
232+
type: 'migrate',
233+
description: 'emergency',
234+
reason: 'Emergency maintenance migration',
235+
}),
236+
'In Progress - Scheduled Migration': () =>
237+
accountMaintenanceFactory.build({
238+
status: 'in_progress',
239+
entity: {
240+
type: 'linode',
241+
id: 1,
242+
label: 'linode-1',
243+
url: '/v4/linode/instances/1',
244+
},
245+
type: 'migrate',
246+
description: 'scheduled',
247+
reason: 'Scheduled maintenance migration',
248+
}),
214249
Pending: () => accountMaintenanceFactory.build({ status: 'pending' }),
215250
Scheduled: () => accountMaintenanceFactory.build({ status: 'scheduled' }),
216251
Started: () => accountMaintenanceFactory.build({ status: 'started' }),

packages/manager/src/dev-tools/components/JsonTextArea.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ export const JsonTextArea = ({
2424
const debouncedUpdate = React.useMemo(
2525
() =>
2626
debounce((text: string) => {
27+
// Handle empty/whitespace text as null
28+
if (!text.trim()) {
29+
const event = {
30+
currentTarget: {
31+
name,
32+
value: null,
33+
},
34+
target: {
35+
name,
36+
value: null,
37+
},
38+
} as unknown as React.ChangeEvent<HTMLTextAreaElement>;
39+
40+
onChange(event);
41+
return;
42+
}
43+
2744
try {
2845
const parsedJson = JSON.parse(text);
2946
const event = {
@@ -35,7 +52,7 @@ export const JsonTextArea = ({
3552
name,
3653
value: parsedJson,
3754
},
38-
} as React.ChangeEvent<HTMLTextAreaElement>;
55+
} as unknown as React.ChangeEvent<HTMLTextAreaElement>;
3956

4057
onChange(event);
4158
} catch (err) {

packages/manager/src/features/Account/Maintenance/MaintenanceTableRow.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ const statusIconMap: Record<AccountMaintenance['status'], Status> = {
4747
scheduled: 'active',
4848
};
4949

50+
const MAX_REASON_DISPLAY_LENGTH = 93;
51+
5052
interface MaintenanceTableRowProps {
5153
maintenance: AccountMaintenance;
5254
tableType: MaintenanceTableType;
@@ -74,9 +76,11 @@ export const MaintenanceTableRow = (props: MaintenanceTableRowProps) => {
7476

7577
const eventProgress = recentEvent && formatProgressEvent(recentEvent);
7678

77-
const truncatedReason = truncate(reason, 93);
79+
const truncatedReason = reason
80+
? truncate(reason, MAX_REASON_DISPLAY_LENGTH)
81+
: '';
7882

79-
const isTruncated = reason !== truncatedReason;
83+
const isTruncated = reason ? reason !== truncatedReason : false;
8084

8185
const dateField = getMaintenanceDateField(tableType);
8286
const dateValue = props.maintenance[dateField];

packages/manager/src/features/Account/Maintenance/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const maintenanceDateColumnMap: Record<
4040
> = {
4141
completed: ['complete_time', 'End Date'],
4242
'in progress': ['start_time', 'Start Date'],
43-
upcoming: ['start_time', 'Start Date'],
43+
upcoming: ['when', 'Start Date'],
4444
pending: ['when', 'Date'],
4545
};
4646

packages/manager/src/features/Events/factories/linode.tsx

Lines changed: 117 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ import { Link } from 'src/components/Link';
55
import { EventLink } from '../EventLink';
66

77
import type { PartialEventMap } from '../types';
8+
import type { AccountMaintenance } from '@linode/api-v4';
9+
10+
/**
11+
* Normalizes the event description to a valid maintenance type.
12+
* Only accepts 'emergency' or 'scheduled' from AccountMaintenance.description,
13+
* defaults to 'maintenance' for any other value or null/undefined.
14+
*/
15+
type MaintenanceDescription = 'maintenance' | AccountMaintenance['description'];
16+
17+
const getMaintenanceDescription = (
18+
description: null | string | undefined
19+
): MaintenanceDescription => {
20+
if (description === 'emergency' || description === 'scheduled') {
21+
return description;
22+
}
23+
return 'maintenance';
24+
};
825

926
export const linode: PartialEventMap<'linode'> = {
1027
linode_addip: {
@@ -241,30 +258,106 @@ export const linode: PartialEventMap<'linode'> = {
241258
),
242259
},
243260
linode_migrate: {
244-
failed: (e) => (
245-
<>
246-
Migration <strong>failed</strong> for Linode{' '}
247-
<EventLink event={e} to="entity" />.
248-
</>
249-
),
250-
finished: (e) => (
251-
<>
252-
Linode <EventLink event={e} to="entity" /> has been{' '}
253-
<strong>migrated</strong>.
254-
</>
255-
),
256-
scheduled: (e) => (
257-
<>
258-
Linode <EventLink event={e} to="entity" /> is scheduled to be{' '}
259-
<strong>migrated</strong>.
260-
</>
261-
),
262-
started: (e) => (
263-
<>
264-
Linode <EventLink event={e} to="entity" /> is being{' '}
265-
<strong>migrated</strong>.
266-
</>
267-
),
261+
failed: (e) => {
262+
const maintenanceType = getMaintenanceDescription(e.description);
263+
return (
264+
<>
265+
Migration <strong>failed</strong> for Linode{' '}
266+
<EventLink event={e} to="entity" /> for{' '}
267+
{maintenanceType === 'maintenance' ? (
268+
<strong>maintenance</strong>
269+
) : (
270+
<>
271+
<strong>{maintenanceType}</strong> maintenance
272+
</>
273+
)}
274+
{e.secondary_entity ? (
275+
<>
276+
{' '}
277+
with config <EventLink event={e} to="secondaryEntity" />
278+
</>
279+
) : (
280+
''
281+
)}
282+
.
283+
</>
284+
);
285+
},
286+
finished: (e) => {
287+
const maintenanceType = getMaintenanceDescription(e.description);
288+
return (
289+
<>
290+
Linode <EventLink event={e} to="entity" /> has been{' '}
291+
<strong>migrated</strong> for{' '}
292+
{maintenanceType === 'maintenance' ? (
293+
<strong>maintenance</strong>
294+
) : (
295+
<>
296+
<strong>{maintenanceType}</strong> maintenance
297+
</>
298+
)}
299+
{e.secondary_entity ? (
300+
<>
301+
{' '}
302+
with config <EventLink event={e} to="secondaryEntity" />
303+
</>
304+
) : (
305+
''
306+
)}
307+
.
308+
</>
309+
);
310+
},
311+
scheduled: (e) => {
312+
const maintenanceType = getMaintenanceDescription(e.description);
313+
return (
314+
<>
315+
Linode <EventLink event={e} to="entity" /> is scheduled to be{' '}
316+
<strong>migrated</strong> for{' '}
317+
{maintenanceType === 'maintenance' ? (
318+
<strong>maintenance</strong>
319+
) : (
320+
<>
321+
<strong>{maintenanceType}</strong> maintenance
322+
</>
323+
)}
324+
{e.secondary_entity ? (
325+
<>
326+
{' '}
327+
with config <EventLink event={e} to="secondaryEntity" />
328+
</>
329+
) : (
330+
''
331+
)}
332+
.
333+
</>
334+
);
335+
},
336+
started: (e) => {
337+
const maintenanceType = getMaintenanceDescription(e.description);
338+
return (
339+
<>
340+
Linode <EventLink event={e} to="entity" /> is being{' '}
341+
<strong>migrated</strong> for{' '}
342+
{maintenanceType === 'maintenance' ? (
343+
<strong>maintenance</strong>
344+
) : (
345+
<>
346+
<strong>{maintenanceType}</strong> maintenance
347+
</>
348+
)}
349+
{e.secondary_entity ? (
350+
<>
351+
{' '}
352+
with config <EventLink event={e} to="secondaryEntity" />
353+
</>
354+
) : (
355+
''
356+
)}
357+
.
358+
</>
359+
);
360+
},
268361
},
269362
linode_migrate_datacenter: {
270363
failed: (e) => (

0 commit comments

Comments
 (0)