diff --git a/packages/api-v4/.changeset/pr-10980-changed-1726868220865.md b/packages/api-v4/.changeset/pr-10980-changed-1726868220865.md new file mode 100644 index 00000000000..b3d64c2dd7f --- /dev/null +++ b/packages/api-v4/.changeset/pr-10980-changed-1726868220865.md @@ -0,0 +1,5 @@ +--- +"@linode/api-v4": Changed +--- + +Make `replication_type` and `replication_commit_type` optional in MySQL and Postgres interfaces ([#10980](https://github.com/linode/manager/pull/10980)) diff --git a/packages/api-v4/src/databases/types.ts b/packages/api-v4/src/databases/types.ts index 09ab3b816ef..07bb902cd06 100644 --- a/packages/api-v4/src/databases/types.ts +++ b/packages/api-v4/src/databases/types.ts @@ -156,7 +156,7 @@ export interface BaseDatabase { } export interface MySQLDatabase extends BaseDatabase { - replication_type: MySQLReplicationType; + replication_type?: MySQLReplicationType; } export type PostgresReplicationType = 'none' | 'synch' | 'asynch'; @@ -169,8 +169,8 @@ type ReplicationCommitTypes = | 'off'; export interface PostgresDatabase extends BaseDatabase { - replication_type: PostgresReplicationType; - replication_commit_type: ReplicationCommitTypes; + replication_type?: PostgresReplicationType; + replication_commit_type?: ReplicationCommitTypes; } type MongoStorageEngine = 'wiredtiger' | 'mmapv1'; diff --git a/packages/manager/.changeset/pr-10980-fixed-1726845381695.md b/packages/manager/.changeset/pr-10980-fixed-1726845381695.md new file mode 100644 index 00000000000..b9fb082bfa9 --- /dev/null +++ b/packages/manager/.changeset/pr-10980-fixed-1726845381695.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Incorrect timezone in Database Maintenance Window tooltip, inaccurate Resize status of Database, and unneeded `replication_type` in v2 `createPayload` ([#10980](https://github.com/linode/manager/pull/10980)) diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx index 716a4d46a36..87887c34e03 100644 --- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx +++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx @@ -277,7 +277,9 @@ const DatabaseCreate = () => { ...values, allow_list: _allow_list, }; - + if (isDatabasesV2Beta) { + delete createPayload.replication_type; + } try { const response = await createDatabase(createPayload); history.push(`/databases/${response.engine}/${response.id}`); @@ -459,17 +461,26 @@ const DatabaseCreate = () => { 'cluster_size', values.cluster_size < 1 ? 3 : values.cluster_size ); - setFieldValue( - 'replication_type', - determineReplicationType(values.cluster_size, values.engine) - ); - setFieldValue( - 'replication_commit_type', - determineReplicationCommitType(values.engine) - ); + if (!isDatabasesV2Enabled) { + setFieldValue( + 'replication_type', + determineReplicationType(values.cluster_size, values.engine) + ); + setFieldValue( + 'replication_commit_type', + determineReplicationCommitType(values.engine) + ); + } setFieldValue('storage_engine', determineStorageEngine(values.engine)); setFieldValue('compression_type', determineCompressionType(values.engine)); - }, [dbtypes, setFieldValue, values.cluster_size, values.type, values.engine]); + }, [ + dbtypes, + setFieldValue, + values.cluster_size, + values.type, + values.engine, + isDatabasesV2Enabled, + ]); if (regionsLoading || !regionsData || enginesLoading || typesLoading) { return ; @@ -580,10 +591,11 @@ const DatabaseCreate = () => { ) => { setFieldValue('cluster_size', +e.target.value); - setFieldValue( - 'replication_type', - +e.target.value === 1 ? 'none' : 'semi_synch' - ); + !isDatabasesV2Enabled && + setFieldValue( + 'replication_type', + +e.target.value === 1 ? 'none' : 'semi_synch' + ); }} data-testid="database-nodes" > diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/MaintenanceWindow.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/MaintenanceWindow.tsx index ce32afc346e..753c2959ff5 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/MaintenanceWindow.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/MaintenanceWindow.tsx @@ -430,7 +430,7 @@ const weekSelectionMap = [ ]; const utcOffsetText = (utcOffsetInHours: number) => { - return utcOffsetInHours < 0 + return utcOffsetInHours <= 0 ? `+${Math.abs(utcOffsetInHours)}` : `-${utcOffsetInHours}`; }; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx index feb25df224d..a4858793f31 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.test.tsx @@ -1,35 +1,53 @@ import React from 'react'; -import { DatabaseStatusDisplay } from '../DatabaseDetail/DatabaseStatusDisplay'; -import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; + import { databaseFactory } from 'src/factories'; import { entityFactory, eventFactory } from 'src/factories/events'; +import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers'; + +import { DatabaseStatusDisplay } from '../DatabaseDetail/DatabaseStatusDisplay'; beforeAll(() => mockMatchMedia()); describe('DatabaseStatusDisplay component', () => { - it(`renders status 'resizing' with percentage when recent event status is 'started' or 'scheduled'`, () => { + it(`should render status 'resizing' with percentage when recent event status is 'started'`, () => { const mockEvent = eventFactory.build({ action: 'database_resize', - percent_complete: 50, entity: entityFactory.build({ id: 1, type: 'database' }), + percent_complete: 50, + status: 'started', }); const database = databaseFactory.build({ id: 1, status: 'resizing' }); const { getByText } = renderWithTheme( - + ); expect(getByText('Resizing (50%)')).toBeInTheDocument(); }); - it(`renders status 'active' when recent event status is 'finished' `, () => { + it(`should render status 'resizing' when recent event status is 'scheduled' `, () => { + const mockEvent = eventFactory.build({ + action: 'database_resize', + entity: entityFactory.build({ id: 1, type: 'database' }), + percent_complete: 50, + status: 'scheduled', + }); + const database = databaseFactory.build({ id: 1, status: 'resizing' }); + + const { getByText } = renderWithTheme( + + ); + + expect(getByText('Resizing (50%)')).toBeInTheDocument(); + }); + it(`should render status 'active' when recent event status is 'finished' `, () => { const mockEvent = eventFactory.build({ action: 'database_resize', - status: 'finished', entity: entityFactory.build({ id: 1, type: 'database' }), + status: 'finished', }); const database = databaseFactory.build({ id: 1, status: 'active' }); const { getByText } = renderWithTheme( - + ); expect(getByText('Active')).toBeInTheDocument(); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx index 5ee8c9f33f7..d2907c5360b 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseStatusDisplay.tsx @@ -37,10 +37,11 @@ export const DatabaseStatusDisplay = (props: Props) => { let progress: number | undefined; let displayedStatus; - if ( + const isResizing = recentEvent?.action === 'database_resize' && - (recentEvent?.status === 'started' || recentEvent?.status === 'scheduled') - ) { + (recentEvent?.status === 'started' || recentEvent?.status === 'scheduled'); + + if (isResizing) { progress = recentEvent?.percent_complete ?? 0; displayedStatus = ( <> diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index 494618e55ec..650222ad803 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -100,12 +100,13 @@ import { accountLoginFactory } from 'src/factories/accountLogin'; import { accountUserFactory } from 'src/factories/accountUsers'; import { grantFactory, grantsFactory } from 'src/factories/grants'; import { LinodeKernelFactory } from 'src/factories/linodeKernel'; -import { pickRandom } from 'src/utilities/random'; import { getStorage } from 'src/utilities/storage'; const getRandomWholeNumber = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1) + min); +import { pickRandom } from 'src/utilities/random'; + import type { AccountMaintenance, CreateObjectStorageKeyPayload, diff --git a/packages/validation/.changeset/pr-10980-changed-1726868115893.md b/packages/validation/.changeset/pr-10980-changed-1726868115893.md new file mode 100644 index 00000000000..9ec7d32d0f5 --- /dev/null +++ b/packages/validation/.changeset/pr-10980-changed-1726868115893.md @@ -0,0 +1,5 @@ +--- +"@linode/validation": Changed +--- + +Make `replication_type` and `replication_commit_type` optional in `databases.schema.ts` ([#10980](https://github.com/linode/manager/pull/10980)) diff --git a/packages/validation/src/databases.schema.ts b/packages/validation/src/databases.schema.ts index 61d3009008c..4830427c621 100644 --- a/packages/validation/src/databases.schema.ts +++ b/packages/validation/src/databases.schema.ts @@ -25,14 +25,14 @@ export const createDatabaseSchema = object({ is: (engine: string) => Boolean(engine.match(/postgres/)), then: string().oneOf(['none', 'synch', 'asynch']), }) - .required('Replication Type is required'), + .optional(), otherwise: string().notRequired().nullable(true), }), replication_commit_type: string().when('engine', { is: (engine: string) => Boolean(engine.match(/postgres/)), then: string() .oneOf(['off', 'on', 'local', 'remote_write', 'remote_apply']) - .required(), + .optional(), otherwise: string().notRequired().nullable(true), }), storage_engine: string().when('engine', {