Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/api-v4": Changed
---

Use v4beta endpoints for /events and /events/<eventId> ([#13084](https://github.com/linode/manager/pull/13084))
6 changes: 3 additions & 3 deletions packages/api-v4/src/account/events.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { API_ROOT } from '../constants';
import { API_ROOT, BETA_API_ROOT } from '../constants';
import Request, { setMethod, setParams, setURL, setXFilter } from '../request';

import type { Filter, Params, ResourcePage } from '../types';
Expand All @@ -12,7 +12,7 @@ import type { Event, Notification } from './types';
*/
export const getEvents = (params: Params = {}, filter: Filter = {}) =>
Request<ResourcePage<Event>>(
setURL(`${API_ROOT}/account/events`),
setURL(`${BETA_API_ROOT}/account/events`),
setMethod('GET'),
setXFilter(filter),
setParams(params),
Expand All @@ -26,7 +26,7 @@ export const getEvents = (params: Params = {}, filter: Filter = {}) =>
*/
export const getEvent = (eventId: number) =>
Request<Event>(
setURL(`${API_ROOT}/account/events/${encodeURIComponent(eventId)}`),
setURL(`${BETA_API_ROOT}/account/events/${encodeURIComponent(eventId)}`),
setMethod('GET'),
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Display maintenance type (emergency/scheduled) and config information in linode_migrate event messages ([#13084](https://github.com/linode/manager/pull/13084))
59 changes: 59 additions & 0 deletions packages/manager/src/dev-tools/components/ExtraPresetEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,65 @@
status: 'finished',
}),

'Linode Migration In Progress': () =>
eventFactory.build({
action: 'linode_migrate',
entity: {
id: 1,
label: 'linode-1',
type: 'linode',
url: '/v4/linode/instances/1',

Check warning on line 297 in packages/manager/src/dev-tools/components/ExtraPresetEvents.tsx

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Define a constant instead of duplicating this literal 4 times. Raw Output: {"ruleId":"sonarjs/no-duplicate-string","severity":1,"message":"Define a constant instead of duplicating this literal 4 times.","line":297,"column":14,"nodeType":"Literal","endLine":297,"endColumn":38}
},
message: 'Linode migration in progress.',
percent_complete: 45,
status: 'started',
}),

'Linode Migration - Emergency': () =>
eventFactory.build({
action: 'linode_migrate',
description: 'emergency',
entity: {
id: 1,
label: 'linode-1',
type: 'linode',
url: '/v4/linode/instances/1',
},
message: 'Emergency linode migration in progress.',
percent_complete: 30,
status: 'started',
}),

'Linode Migration - Scheduled Started': () =>
eventFactory.build({
action: 'linode_migrate',
description: 'scheduled',
entity: {
id: 1,
label: 'linode-1',
type: 'linode',
url: '/v4/linode/instances/1',
},
message: 'Scheduled linode migration in progress.',
percent_complete: 10,
status: 'started',
}),

'Linode Migration - Scheduled': () =>
eventFactory.build({
action: 'linode_migrate',
description: 'scheduled',
entity: {
id: 1,
label: 'linode-1',
type: 'linode',
url: '/v4/linode/instances/1',
},
message: 'Scheduled linode migration in progress.',
percent_complete: 0,
status: 'scheduled',
}),

'Completed Event': () =>
eventFactory.build({
action: 'account_update',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,42 @@
Canceled: () => accountMaintenanceFactory.build({ status: 'canceled' }),
Completed: () => accountMaintenanceFactory.build({ status: 'completed' }),
'In Progress': () =>
accountMaintenanceFactory.build({ status: 'in_progress' }),
accountMaintenanceFactory.build({
status: 'in_progress',
entity: {
type: 'linode',
id: 1,
label: 'linode-1',
url: '/v4/linode/instances/1',

Check warning on line 219 in packages/manager/src/dev-tools/components/ExtraPresetMaintenance.tsx

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Define a constant instead of duplicating this literal 4 times. Raw Output: {"ruleId":"sonarjs/no-duplicate-string","severity":1,"message":"Define a constant instead of duplicating this literal 4 times.","line":219,"column":14,"nodeType":"Literal","endLine":219,"endColumn":38}
},
type: 'migrate',
}),
'In Progress - Emergency Migration': () =>
accountMaintenanceFactory.build({
status: 'in_progress',
entity: {
type: 'linode',
id: 1,
label: 'linode-1',
url: '/v4/linode/instances/1',
},
type: 'migrate',
description: 'emergency',
reason: 'Emergency maintenance migration',
}),
'In Progress - Scheduled Migration': () =>
accountMaintenanceFactory.build({
status: 'in_progress',
entity: {
type: 'linode',
id: 1,
label: 'linode-1',
url: '/v4/linode/instances/1',
},
type: 'migrate',
description: 'scheduled',
reason: 'Scheduled maintenance migration',
}),
Pending: () => accountMaintenanceFactory.build({ status: 'pending' }),
Scheduled: () => accountMaintenanceFactory.build({ status: 'scheduled' }),
Started: () => accountMaintenanceFactory.build({ status: 'started' }),
Expand Down
19 changes: 18 additions & 1 deletion packages/manager/src/dev-tools/components/JsonTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ export const JsonTextArea = ({
const debouncedUpdate = React.useMemo(
() =>
debounce((text: string) => {
// Handle empty/whitespace text as null
if (!text.trim()) {
const event = {
currentTarget: {
name,
value: null,
},
target: {
name,
value: null,
},
} as unknown as React.ChangeEvent<HTMLTextAreaElement>;

onChange(event);
return;
}

try {
const parsedJson = JSON.parse(text);
const event = {
Expand All @@ -35,7 +52,7 @@ export const JsonTextArea = ({
name,
value: parsedJson,
},
} as React.ChangeEvent<HTMLTextAreaElement>;
} as unknown as React.ChangeEvent<HTMLTextAreaElement>;

onChange(event);
} catch (err) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const statusIconMap: Record<AccountMaintenance['status'], Status> = {
scheduled: 'active',
};

const MAX_REASON_DISPLAY_LENGTH = 93;

interface MaintenanceTableRowProps {
maintenance: AccountMaintenance;
tableType: MaintenanceTableType;
Expand Down Expand Up @@ -74,9 +76,11 @@ export const MaintenanceTableRow = (props: MaintenanceTableRowProps) => {

const eventProgress = recentEvent && formatProgressEvent(recentEvent);

const truncatedReason = truncate(reason, 93);
const truncatedReason = reason
? truncate(reason, MAX_REASON_DISPLAY_LENGTH)
: '';

const isTruncated = reason !== truncatedReason;
const isTruncated = reason ? reason !== truncatedReason : false;

const dateField = getMaintenanceDateField(tableType);
const dateValue = props.maintenance[dateField];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const maintenanceDateColumnMap: Record<
> = {
completed: ['complete_time', 'End Date'],
'in progress': ['start_time', 'Start Date'],
upcoming: ['start_time', 'Start Date'],
upcoming: ['when', 'Start Date'],
pending: ['when', 'Date'],
};

Expand Down
141 changes: 117 additions & 24 deletions packages/manager/src/features/Events/factories/linode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ import { Link } from 'src/components/Link';
import { EventLink } from '../EventLink';

import type { PartialEventMap } from '../types';
import type { AccountMaintenance } from '@linode/api-v4';

/**
* Normalizes the event description to a valid maintenance type.
* Only accepts 'emergency' or 'scheduled' from AccountMaintenance.description,
* defaults to 'maintenance' for any other value or null/undefined.
*/
type MaintenanceDescription = 'maintenance' | AccountMaintenance['description'];

const getMaintenanceDescription = (
description: null | string | undefined
): MaintenanceDescription => {
if (description === 'emergency' || description === 'scheduled') {
return description;
}
return 'maintenance';
};

export const linode: PartialEventMap<'linode'> = {
linode_addip: {
Expand Down Expand Up @@ -241,30 +258,106 @@ export const linode: PartialEventMap<'linode'> = {
),
},
linode_migrate: {
failed: (e) => (
<>
Migration <strong>failed</strong> for Linode{' '}
<EventLink event={e} to="entity" />.
</>
),
finished: (e) => (
<>
Linode <EventLink event={e} to="entity" /> has been{' '}
<strong>migrated</strong>.
</>
),
scheduled: (e) => (
<>
Linode <EventLink event={e} to="entity" /> is scheduled to be{' '}
<strong>migrated</strong>.
</>
),
started: (e) => (
<>
Linode <EventLink event={e} to="entity" /> is being{' '}
<strong>migrated</strong>.
</>
),
failed: (e) => {
const maintenanceType = getMaintenanceDescription(e.description);
return (
<>
Migration <strong>failed</strong> for Linode{' '}
<EventLink event={e} to="entity" /> for{' '}
{maintenanceType === 'maintenance' ? (
<strong>maintenance</strong>
) : (
<>
<strong>{maintenanceType}</strong> maintenance
</>
)}
{e.secondary_entity ? (
<>
{' '}
with config <EventLink event={e} to="secondaryEntity" />
</>
) : (
''
)}
.
</>
);
},
finished: (e) => {
const maintenanceType = getMaintenanceDescription(e.description);
return (
<>
Linode <EventLink event={e} to="entity" /> has been{' '}
<strong>migrated</strong> for{' '}
{maintenanceType === 'maintenance' ? (
<strong>maintenance</strong>
) : (
<>
<strong>{maintenanceType}</strong> maintenance
</>
)}
{e.secondary_entity ? (
<>
{' '}
with config <EventLink event={e} to="secondaryEntity" />
</>
) : (
''
)}
.
</>
);
},
scheduled: (e) => {
const maintenanceType = getMaintenanceDescription(e.description);
return (
<>
Linode <EventLink event={e} to="entity" /> is scheduled to be{' '}
<strong>migrated</strong> for{' '}
{maintenanceType === 'maintenance' ? (
<strong>maintenance</strong>
) : (
<>
<strong>{maintenanceType}</strong> maintenance
</>
)}
{e.secondary_entity ? (
<>
{' '}
with config <EventLink event={e} to="secondaryEntity" />
</>
) : (
''
)}
.
</>
);
},
started: (e) => {
const maintenanceType = getMaintenanceDescription(e.description);
return (
<>
Linode <EventLink event={e} to="entity" /> is being{' '}
<strong>migrated</strong> for{' '}
{maintenanceType === 'maintenance' ? (
<strong>maintenance</strong>
) : (
<>
<strong>{maintenanceType}</strong> maintenance
</>
)}
{e.secondary_entity ? (
<>
{' '}
with config <EventLink event={e} to="secondaryEntity" />
</>
) : (
''
)}
.
</>
);
},
},
linode_migrate_datacenter: {
failed: (e) => (
Expand Down