mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
console: support for mssql read replicas
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3630 Co-authored-by: Varun Choudhary <68095256+Varun-Choudhary@users.noreply.github.com> GitOrigin-RevId: 9660a5d9cdec8aff17cf20fcad3f309bdb3d182e
This commit is contained in:
parent
d50aae87a5
commit
9144d979d4
@ -96,12 +96,13 @@ const ConnectDatabase: React.FC<ConnectDatabaseProps> = props => {
|
||||
const existingReadReplicas: ExtendedConnectDBState[] | [] = (
|
||||
currentSourceInfo.configuration?.read_replicas ?? []
|
||||
).map(replica => {
|
||||
const replicaDBUrlInfo = getReadReplicaDBUrlInfo(replica);
|
||||
const dbType = currentSourceInfo.kind ?? 'postgres';
|
||||
const replicaDBUrlInfo = getReadReplicaDBUrlInfo(replica, dbType);
|
||||
return {
|
||||
chosenConnectionType:
|
||||
replicaDBUrlInfo?.connectionType || connectionTypes.DATABASE_URL,
|
||||
displayName: '',
|
||||
dbType: currentSourceInfo.kind ?? 'postgres',
|
||||
dbType,
|
||||
connectionParamState: {
|
||||
host: '',
|
||||
port: '',
|
||||
@ -347,6 +348,10 @@ const ConnectDatabase: React.FC<ConnectDatabaseProps> = props => {
|
||||
type: 'UPDATE_DISPLAY_NAME',
|
||||
data: `read-replica-${indexForName}`,
|
||||
});
|
||||
connectDBReadReplicaDispatch({
|
||||
type: 'UPDATE_DB_DRIVER',
|
||||
data: connectDBInputState.dbType,
|
||||
});
|
||||
};
|
||||
|
||||
const onClickCancelOnReadReplicaForm = () =>
|
||||
@ -382,7 +387,7 @@ const ConnectDatabase: React.FC<ConnectDatabaseProps> = props => {
|
||||
title="Edit Data Source"
|
||||
>
|
||||
{/* Should be rendered only on Pro and Cloud Console */}
|
||||
{getSupportedDrivers('connectDbForm.read_replicas').includes(
|
||||
{getSupportedDrivers('connectDbForm.read_replicas.edit').includes(
|
||||
connectDBInputState.dbType
|
||||
) &&
|
||||
(window.__env.consoleId || window.__env.userRole) && (
|
||||
@ -416,7 +421,7 @@ const ConnectDatabase: React.FC<ConnectDatabaseProps> = props => {
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{/* Should be rendered only on Pro and Cloud Console */}
|
||||
{getSupportedDrivers('connectDbForm.read_replicas').includes(
|
||||
{getSupportedDrivers('connectDbForm.read_replicas.create').includes(
|
||||
connectDBInputState.dbType
|
||||
) &&
|
||||
(window.__env.consoleId || window.__env.userRole) && (
|
||||
|
@ -154,18 +154,15 @@ const ReadReplicaListItem: React.FC<ReadReplicaListItemProps> = ({
|
||||
<p>{isFromEnvVar ? currentState.envVarState.envVar : host}</p>
|
||||
{/* The connection string is redundant if it's provided via ENV VAR */}
|
||||
{!isFromEnvVar && (
|
||||
<span className={`${styles.db_large_string_break_words}`}>
|
||||
<span className="px-sm py-xs max-w-xs align-top break-all">
|
||||
{showUrl ? (
|
||||
connectionString
|
||||
) : (
|
||||
<span
|
||||
className={styles.show_connection_string}
|
||||
className="text-secondary flex items-center cursor-pointer"
|
||||
onClick={() => setShowUrl(true)}
|
||||
>
|
||||
<i
|
||||
className={`${styles.showAdminSecret} fa fa-eye`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<i className="fa fa-eye" aria-hidden="true" />
|
||||
<p style={{ marginLeft: 6 }}>Show Connection String</p>
|
||||
</span>
|
||||
)}
|
||||
|
@ -89,6 +89,13 @@ describe('dataSourceIsEqual works', () => {
|
||||
'DRIVER={ODBC Driver 17 for SQL Server};SERVER=172.17.0.1;DATABASE=master;Uid=SA;Pwd=reallyStrongPwd123',
|
||||
pool_settings: {},
|
||||
},
|
||||
read_replicas: [
|
||||
{
|
||||
connection_string:
|
||||
'DRIVER={ODBC Driver 17 for SQL Server};SERVER=172.16.238.1,1502;Database=agtestdb;Uid=sa;Pwd=Password1;ApplicationIntent=ReadOnly',
|
||||
pool_settings: { idle_timeout: 5, max_connections: 50 },
|
||||
},
|
||||
],
|
||||
},
|
||||
replace_configuration: false,
|
||||
};
|
||||
@ -112,15 +119,18 @@ describe('dataSourceIsEqual works', () => {
|
||||
});
|
||||
|
||||
describe('getReadReplicaDBUrlInfo gives the correct result', () => {
|
||||
it('for read replicas with db urls', () => {
|
||||
const res = getReadReplicaDBUrlInfo({
|
||||
use_prepared_statements: false,
|
||||
database_url: 'postgres://postgres:test@172.17.0.1:6001/chinook',
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
it('for postgres read replicas with db urls', () => {
|
||||
const res = getReadReplicaDBUrlInfo(
|
||||
{
|
||||
use_prepared_statements: false,
|
||||
database_url: 'postgres://postgres:test@172.17.0.1:6001/chinook',
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
},
|
||||
},
|
||||
});
|
||||
'postgres'
|
||||
);
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"connectionType": "DATABASE_URL",
|
||||
@ -134,17 +144,68 @@ describe('getReadReplicaDBUrlInfo gives the correct result', () => {
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('for read replicas with env vars', () => {
|
||||
const res = getReadReplicaDBUrlInfo({
|
||||
use_prepared_statements: false,
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
it('for mssql read replicas with db urls', () => {
|
||||
const res = getReadReplicaDBUrlInfo(
|
||||
{
|
||||
use_prepared_statements: false,
|
||||
connection_string: 'postgres://postgres:test@172.17.0.1:6001/chinook',
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
},
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
'mssql'
|
||||
);
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"connectionType": "DATABASE_URL",
|
||||
"databaseURLState": Object {
|
||||
"datasets": "",
|
||||
"dbURL": "postgres://postgres:test@172.17.0.1:6001/chinook",
|
||||
"global_select_limit": 1000,
|
||||
"projectId": "",
|
||||
"serviceAccount": "",
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('for postgres read replicas with env vars', () => {
|
||||
const res = getReadReplicaDBUrlInfo(
|
||||
{
|
||||
use_prepared_statements: false,
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
},
|
||||
},
|
||||
});
|
||||
'postgres'
|
||||
);
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"connectionType": "ENVIRONMENT_VARIABLES",
|
||||
"envVarState": Object {
|
||||
"envVar": "HASURA_GRAPHQL_DATABASE_URL",
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('for mssql read replicas with env vars', () => {
|
||||
const res = getReadReplicaDBUrlInfo(
|
||||
{
|
||||
use_prepared_statements: false,
|
||||
connection_string: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
},
|
||||
},
|
||||
'mssql'
|
||||
);
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"connectionType": "ENVIRONMENT_VARIABLES",
|
||||
|
@ -120,23 +120,66 @@ export const dataSourceIsEqual = (
|
||||
return isEqual(filterFields(sourceFromMetaData), filterFields(data));
|
||||
};
|
||||
|
||||
export const getReadReplicaDBUrlInfo = (replica: SourceConnectionInfo) => {
|
||||
if (!replica.database_url) return null;
|
||||
if (typeof replica.database_url === 'string')
|
||||
return {
|
||||
connectionType: connectionTypes.DATABASE_URL,
|
||||
databaseURLState: {
|
||||
dbURL: replica.database_url,
|
||||
serviceAccount: '',
|
||||
global_select_limit: 1000,
|
||||
projectId: '',
|
||||
datasets: '',
|
||||
},
|
||||
};
|
||||
return {
|
||||
connectionType: connectionTypes.ENV_VAR,
|
||||
envVarState: {
|
||||
envVar: replica.database_url.from_env,
|
||||
},
|
||||
type TGetReadReplicaDBUrlInfoResponse = {
|
||||
connectionType: string;
|
||||
envVarState?: {
|
||||
envVar: string;
|
||||
};
|
||||
databaseURLState?: {
|
||||
dbURL: string;
|
||||
serviceAccount: string;
|
||||
global_select_limit: number;
|
||||
projectId: string;
|
||||
datasets: string;
|
||||
};
|
||||
};
|
||||
|
||||
export const getReadReplicaDBUrlInfo = (
|
||||
replica: SourceConnectionInfo,
|
||||
dbType: MetadataDataSource['kind']
|
||||
): TGetReadReplicaDBUrlInfoResponse | null => {
|
||||
const dbUrlConfig = {
|
||||
dbURL: '',
|
||||
serviceAccount: '',
|
||||
global_select_limit: 1000,
|
||||
projectId: '',
|
||||
datasets: '',
|
||||
};
|
||||
|
||||
if (!replica?.database_url && !replica?.connection_string) return null;
|
||||
if (dbType === 'postgres') {
|
||||
if (typeof replica?.database_url === 'string') {
|
||||
return {
|
||||
connectionType: connectionTypes.DATABASE_URL,
|
||||
databaseURLState: {
|
||||
...dbUrlConfig,
|
||||
dbURL: replica?.database_url,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
connectionType: connectionTypes.ENV_VAR,
|
||||
envVarState: {
|
||||
envVar: replica?.database_url?.from_env ?? '',
|
||||
},
|
||||
};
|
||||
}
|
||||
if (dbType === 'mssql') {
|
||||
if (typeof replica?.connection_string === 'string') {
|
||||
return {
|
||||
connectionType: connectionTypes.DATABASE_URL,
|
||||
databaseURLState: {
|
||||
...dbUrlConfig,
|
||||
dbURL: replica?.connection_string,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
connectionType: connectionTypes.ENV_VAR,
|
||||
envVarState: {
|
||||
envVar: replica?.connection_string?.from_env ?? '',
|
||||
},
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -202,7 +202,10 @@ export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
|
||||
connectionParameters: true,
|
||||
databaseURL: false,
|
||||
environmentVariable: true,
|
||||
read_replicas: false,
|
||||
read_replicas: {
|
||||
create: true,
|
||||
edit: true,
|
||||
},
|
||||
prepared_statements: false,
|
||||
isolation_level: false,
|
||||
connectionSettings: false,
|
||||
|
@ -221,7 +221,10 @@ export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
|
||||
connectionParameters: false,
|
||||
databaseURL: true,
|
||||
environmentVariable: true,
|
||||
read_replicas: false,
|
||||
read_replicas: {
|
||||
create: true,
|
||||
edit: true,
|
||||
},
|
||||
prepared_statements: false,
|
||||
isolation_level: false,
|
||||
connectionSettings: true,
|
||||
|
@ -682,7 +682,10 @@ export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
|
||||
connectionParameters: true,
|
||||
databaseURL: true,
|
||||
environmentVariable: true,
|
||||
read_replicas: true,
|
||||
read_replicas: {
|
||||
create: true,
|
||||
edit: true,
|
||||
},
|
||||
prepared_statements: true,
|
||||
isolation_level: true,
|
||||
connectionSettings: true,
|
||||
|
@ -389,7 +389,10 @@ export type SupportedFeaturesType = {
|
||||
connectionParameters: boolean;
|
||||
databaseURL: boolean;
|
||||
environmentVariable: boolean;
|
||||
read_replicas: boolean;
|
||||
read_replicas: {
|
||||
create: boolean;
|
||||
edit: boolean;
|
||||
};
|
||||
prepared_statements: boolean;
|
||||
isolation_level: boolean;
|
||||
connectionSettings: boolean;
|
||||
|
@ -42,6 +42,7 @@ export const addSource = (
|
||||
connection_string: payload.dbUrl,
|
||||
pool_settings: payload.connection_pool_settings,
|
||||
},
|
||||
read_replicas: replicas?.length ? replicas : null,
|
||||
},
|
||||
replace_configuration,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user