@@ -265,7 +197,7 @@ export const DatabaseSummaryConnectionDetails = (props: Props) => {
showCredentials && credentials ? 'Hide' : 'Show'
)
)}
- {disableShowBtn ? (
+ {disableShowBtn && (
{
status="help"
sxTooltipIcon={sxTooltipIcon}
/>
- ) : null}
- {showCredentials && credentials ? (
+ )}
+ {showCredentials && credentials && (
- ) : null}
-
-
- {!isMongoReplicaSet ? (
-
- {database.hosts?.primary ? (
- <>
-
- host ={' '}
-
- {database.hosts?.primary}
- {' '}
-
-
- {database.engine === 'mongodb' ? (
-
- ) : null}
- >
- ) : (
-
- host ={' '}
-
- Your hostname will appear here once it is available.
-
-
- )}
-
- ) : (
- <>
-
- hosts ={' '}
- {!database.peers || database.peers.length === 0 ? (
-
- Your hostnames will appear here once they are available.
-
- ) : null}
-
- {database.peers && database.peers.length > 0
- ? database.peers.map((hostname, i) => (
-
-
-
- {hostname}
-
-
-
- {/* Display the helper text on the first hostname */}
- {i === 0 ? (
-
- ) : null}
-
- ))
- : null}
- >
)}
-
- {readOnlyHost ? (
-
-
- {database.platform === 'rdbms-default' ? (
- read-only host
- ) : (
- private network host
- )}
- = {readOnlyHost}
-
-
-
-
- ) : null}
-
- port = {database.port}
-
- {isMongoReplicaSet ? (
- database.replica_set ? (
-
-
- replica set ={' '}
-
- {database.replica_set}
-
-
+
+
+ Host
+
+
+ {database.hosts?.primary ? (
+ <>
+ {database.hosts?.primary}
-
+ >
) : (
- replica set ={' '}
- Your replica set will appear here once it is available.
+ Your hostname will appear here once it is available.
- )
- ) : null}
-
- ssl = {database.ssl_connection ? 'ENABLED' : 'DISABLED'}
-
-
+ )}
+
+
+
+ {isLegacy ? 'Private Network Host' : 'Read-only Host'}
+
+
+
+ {readOnlyHost()}
+
+
+ Port
+
+
+ {database.port}
+
+
+ SSL
+
+
+ {database.ssl_connection ? 'ENABLED' : 'DISABLED'}
+
+
{database.ssl_connection ? caCertificateJSX : null}
diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryClusterConfigurationLegacy.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryClusterConfigurationLegacy.tsx
new file mode 100644
index 00000000000..5bc03953c51
--- /dev/null
+++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryClusterConfigurationLegacy.tsx
@@ -0,0 +1,146 @@
+import * as React from 'react';
+import { makeStyles } from 'tss-react/mui';
+
+import { Box } from 'src/components/Box';
+import { TooltipIcon } from 'src/components/TooltipIcon';
+import { Typography } from 'src/components/Typography';
+import { DatabaseStatusDisplay } from 'src/features/Databases/DatabaseDetail/DatabaseStatusDisplay';
+import { databaseEngineMap } from 'src/features/Databases/DatabaseLanding/DatabaseRow';
+import { useDatabaseTypesQuery } from 'src/queries/databases/databases';
+import { useInProgressEvents } from 'src/queries/events/events';
+import { useRegionsQuery } from 'src/queries/regions/regions';
+import { formatStorageUnits } from 'src/utilities/formatStorageUnits';
+import { convertMegabytesTo } from 'src/utilities/unitConversions';
+
+import type { Region } from '@linode/api-v4';
+import type {
+ Database,
+ DatabaseType,
+} from '@linode/api-v4/lib/databases/types';
+import type { Theme } from '@mui/material/styles';
+
+const useStyles = makeStyles()((theme: Theme) => ({
+ configs: {
+ fontSize: '0.875rem',
+ lineHeight: '22px',
+ },
+ header: {
+ marginBottom: theme.spacing(2),
+ },
+ label: {
+ fontFamily: theme.font.bold,
+ lineHeight: '22px',
+ width: theme.spacing(13),
+ },
+ status: {
+ alignItems: 'center',
+ display: 'flex',
+ textTransform: 'capitalize',
+ },
+}));
+
+interface Props {
+ database: Database;
+}
+
+/**
+ * Deprecated @since DBaaS V2 GA. Will be removed remove post GA release ~ Dec 2024
+ * TODO (UIE-8214) remove POST GA
+ */
+export const DatabaseSummaryClusterConfigurationLegacy = (props: Props) => {
+ const { classes } = useStyles();
+ const { database } = props;
+
+ const { data: types } = useDatabaseTypesQuery({
+ platform: database.platform,
+ });
+
+ const type = types?.find((type: DatabaseType) => type.id === database?.type);
+
+ const { data: regions } = useRegionsQuery();
+
+ const region = regions?.find((r: Region) => r.id === database.region);
+
+ const { data: events } = useInProgressEvents();
+
+ if (!database || !type) {
+ return null;
+ }
+
+ const configuration =
+ database.cluster_size === 1
+ ? 'Primary'
+ : `Primary +${database.cluster_size - 1} replicas`;
+
+ const sxTooltipIcon = {
+ marginLeft: '4px',
+ padding: '0px',
+ };
+
+ const STORAGE_COPY =
+ 'The total disk size is smaller than the selected plan capacity due to overhead from the OS.';
+
+ return (
+ <>
+
+ Cluster Configuration
+
+
+
+ Status
+
+
+
+
+
+ Version
+ {databaseEngineMap[database.engine]} v{database.version}
+
+
+ Nodes
+ {configuration}
+
+
+ Region
+ {region?.label ?? database.region}
+
+
+ Plan
+ {formatStorageUnits(type.label)}
+
+
+ RAM
+ {type.memory / 1024} GB
+
+
+ CPUs
+ {type.vcpus}
+
+ {database.total_disk_size_gb ? (
+ <>
+
+ Total Disk Size
+ {database.total_disk_size_gb} GB
+
+
+
+ Used
+ {database.used_disk_size_gb} GB
+
+ >
+ ) : (
+
+ Storage
+ {convertMegabytesTo(type.disk, true)}
+
+ )}
+
+ >
+ );
+};
+
+export default DatabaseSummaryClusterConfigurationLegacy;
diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryConnectionDetailsLegacy.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryConnectionDetailsLegacy.tsx
new file mode 100644
index 00000000000..8fbdb195452
--- /dev/null
+++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryConnectionDetailsLegacy.tsx
@@ -0,0 +1,370 @@
+import { getSSLFields } from '@linode/api-v4/lib/databases/databases';
+import { useTheme } from '@mui/material';
+import { useSnackbar } from 'notistack';
+import * as React from 'react';
+import { makeStyles } from 'tss-react/mui';
+
+import DownloadIcon from 'src/assets/icons/lke-download.svg';
+import { Box } from 'src/components/Box';
+import { Button } from 'src/components/Button/Button';
+import { CircleProgress } from 'src/components/CircleProgress';
+import { CopyTooltip } from 'src/components/CopyTooltip/CopyTooltip';
+import { TooltipIcon } from 'src/components/TooltipIcon';
+import { Typography } from 'src/components/Typography';
+import { DB_ROOT_USERNAME } from 'src/constants';
+import { useDatabaseCredentialsQuery } from 'src/queries/databases/databases';
+import { downloadFile } from 'src/utilities/downloadFile';
+import { getErrorStringOrDefault } from 'src/utilities/errorUtils';
+
+import type { Database, SSLFields } from '@linode/api-v4/lib/databases/types';
+import type { Theme } from '@mui/material/styles';
+
+const useStyles = makeStyles()((theme: Theme) => ({
+ actionBtnsCtn: {
+ display: 'flex',
+ justifyContent: 'flex-end',
+ marginTop: '10px',
+ padding: `${theme.spacing(1)} 0`,
+ },
+ caCertBtn: {
+ '& svg': {
+ marginRight: theme.spacing(),
+ },
+ '&:hover': {
+ backgroundColor: 'transparent',
+ opacity: 0.7,
+ },
+ '&[disabled]': {
+ '& g': {
+ stroke: '#cdd0d5',
+ },
+ '&:hover': {
+ backgroundColor: 'inherit',
+ textDecoration: 'none',
+ },
+ // Override disabled background color defined for dark mode
+ backgroundColor: 'transparent',
+ color: '#cdd0d5',
+ cursor: 'default',
+ },
+ color: theme.palette.primary.main,
+ fontFamily: theme.font.bold,
+ fontSize: '0.875rem',
+ lineHeight: '1.125rem',
+ marginLeft: theme.spacing(),
+ minHeight: 'auto',
+ minWidth: 'auto',
+ padding: 0,
+ },
+ connectionDetailsCtn: {
+ '& p': {
+ lineHeight: '1.5rem',
+ },
+ '& span': {
+ fontFamily: theme.font.bold,
+ },
+ background: theme.bg.bgAccessRowTransparentGradient,
+ border: `1px solid ${theme.name === 'light' ? '#ccc' : '#222'}`,
+ padding: '8px 15px',
+ },
+ copyToolTip: {
+ '& svg': {
+ color: theme.palette.primary.main,
+ height: `16px !important`,
+ width: `16px !important`,
+ },
+ marginRight: 12,
+ },
+ error: {
+ color: theme.color.red,
+ marginLeft: theme.spacing(2),
+ },
+ header: {
+ marginBottom: theme.spacing(2),
+ },
+ inlineCopyToolTip: {
+ '& svg': {
+ height: `16px`,
+ width: `16px`,
+ },
+ '&:hover': {
+ backgroundColor: 'transparent',
+ },
+ display: 'inline-flex',
+ marginLeft: 4,
+ },
+ progressCtn: {
+ '& circle': {
+ stroke: theme.palette.primary.main,
+ },
+ alignSelf: 'flex-end',
+ marginBottom: 2,
+ marginLeft: 22,
+ },
+ provisioningText: {
+ fontFamily: theme.font.normal,
+ fontStyle: 'italic',
+ },
+ showBtn: {
+ color: theme.palette.primary.main,
+ fontSize: '0.875rem',
+ marginLeft: theme.spacing(),
+ minHeight: 'auto',
+ minWidth: 'auto',
+ padding: 0,
+ },
+}));
+
+interface Props {
+ database: Database;
+}
+
+const sxTooltipIcon = {
+ marginLeft: '4px',
+ padding: '0px',
+};
+
+const privateHostCopy =
+ 'A private network host and a private IP can only be used to access a Database Cluster from Linodes in the same data center and will not incur transfer costs.';
+
+const mongoHostHelperCopy =
+ 'This is a public hostname. Coming soon: connect to your MongoDB clusters using private IPs';
+
+/**
+ * Deprecated @since DBaaS V2 GA. Will be removed remove post GA release ~ Dec 2024
+ * TODO (UIE-8214) remove POST GA
+ */
+export const DatabaseSummaryConnectionDetailsLegacy = (props: Props) => {
+ const { database } = props;
+ const { classes } = useStyles();
+ const theme = useTheme();
+ const { enqueueSnackbar } = useSnackbar();
+
+ const [showCredentials, setShowPassword] = React.useState(false);
+ const [isCACertDownloading, setIsCACertDownloading] = React.useState(
+ false
+ );
+
+ const {
+ data: credentials,
+ error: credentialsError,
+ isLoading: credentialsLoading,
+ refetch: getDatabaseCredentials,
+ } = useDatabaseCredentialsQuery(database.engine, database.id);
+
+ const username =
+ database.platform === 'rdbms-default'
+ ? 'akmadmin'
+ : database.engine === 'postgresql'
+ ? 'linpostgres'
+ : DB_ROOT_USERNAME;
+
+ const password =
+ showCredentials && credentials ? credentials?.password : '••••••••••';
+
+ const handleShowPasswordClick = () => {
+ setShowPassword((showCredentials) => !showCredentials);
+ };
+
+ React.useEffect(() => {
+ if (showCredentials && !credentials) {
+ getDatabaseCredentials();
+ }
+ }, [credentials, getDatabaseCredentials, showCredentials]);
+
+ const handleDownloadCACertificate = () => {
+ setIsCACertDownloading(true);
+ getSSLFields(database.engine, database.id)
+ .then((response: SSLFields) => {
+ // Convert to utf-8 from base64
+ try {
+ const decodedFile = window.atob(response.ca_certificate);
+ downloadFile(`${database.label}-ca-certificate.crt`, decodedFile);
+ setIsCACertDownloading(false);
+ } catch (e) {
+ enqueueSnackbar('Error parsing your CA Certificate file', {
+ variant: 'error',
+ });
+ setIsCACertDownloading(false);
+ return;
+ }
+ })
+ .catch((errorResponse: any) => {
+ const error = getErrorStringOrDefault(
+ errorResponse,
+ 'Unable to download your CA Certificate'
+ );
+ setIsCACertDownloading(false);
+ enqueueSnackbar(error, { variant: 'error' });
+ });
+ };
+
+ const disableShowBtn = ['failed', 'provisioning'].includes(database.status);
+ const disableDownloadCACertificateBtn = database.status === 'provisioning';
+ const readOnlyHost = database?.hosts?.standby || database?.hosts?.secondary;
+
+ const credentialsBtn = (handleClick: () => void, btnText: string) => {
+ return (
+
+ );
+ };
+
+ const caCertificateJSX = (
+ <>
+
+ {disableDownloadCACertificateBtn && (
+
+
+
+ )}
+ >
+ );
+
+ return (
+ <>
+
+ Connection Details
+
+
+
+ username = {username}
+
+
+
+ password = {password}
+
+ {showCredentials && credentialsLoading ? (
+
+
+
+ ) : credentialsError ? (
+ <>
+
+ Error retrieving credentials.
+
+ {credentialsBtn(() => getDatabaseCredentials(), 'Retry')}
+ >
+ ) : (
+ credentialsBtn(
+ handleShowPasswordClick,
+ showCredentials && credentials ? 'Hide' : 'Show'
+ )
+ )}
+ {disableShowBtn && (
+
+ )}
+ {showCredentials && credentials && (
+
+ )}
+
+
+
+ hosts ={' '}
+ {(!database.peers || database.peers.length === 0) && (
+
+ Your hostnames will appear here once they are available.
+
+ )}
+
+ {database.peers &&
+ database.peers.length > 0 &&
+ database.peers.map((hostname, i) => (
+
+
+
+ {hostname}
+
+
+
+ {/* Display the helper text on the first hostname */}
+ {i === 0 && (
+
+ )}
+
+ ))}
+
+ {readOnlyHost && (
+
+
+ {database.platform === 'rdbms-default' ? (
+ read-only host
+ ) : (
+ private network host
+ )}
+ = {readOnlyHost}
+
+
+ {database.platform === 'rdbms-legacy' && (
+
+ )}
+
+ )}
+
+ port = {database.port}
+
+
+ ssl = {database.ssl_connection ? 'ENABLED' : 'DISABLED'}
+
+
+
+ {database.ssl_connection ? caCertificateJSX : null}
+
+ >
+ );
+};
+
+export default DatabaseSummaryConnectionDetailsLegacy;
diff --git a/packages/manager/src/features/Databases/utilities.ts b/packages/manager/src/features/Databases/utilities.ts
index ce4fe9bc149..2d3179964c0 100644
--- a/packages/manager/src/features/Databases/utilities.ts
+++ b/packages/manager/src/features/Databases/utilities.ts
@@ -1,17 +1,22 @@
-import type { DatabaseInstance } from '@linode/api-v4';
-import { DatabaseFork } from '@linode/api-v4';
import { DateTime } from 'luxon';
+
import { useFlags } from 'src/hooks/useFlags';
import { useAccount } from 'src/queries/account/account';
import { useDatabaseTypesQuery } from 'src/queries/databases/databases';
import { isFeatureEnabledV2 } from 'src/utilities/accountCapabilities';
+
import { databaseEngineMap } from './DatabaseLanding/DatabaseRow';
+import type { DatabaseInstance } from '@linode/api-v4';
+import type { DatabaseFork } from '@linode/api-v4';
+
export interface IsDatabasesEnabled {
isDatabasesEnabled: boolean;
+ isDatabasesMonitorBeta?: boolean;
+ isDatabasesMonitorEnabled?: boolean;
isDatabasesV1Enabled: boolean;
- isDatabasesV2Enabled: boolean;
isDatabasesV2Beta: boolean;
+ isDatabasesV2Enabled: boolean;
isDatabasesV2GA: boolean;
/**
* Temporary variable to be removed post GA release
@@ -21,8 +26,6 @@ export interface IsDatabasesEnabled {
* Temporary variable to be removed post GA release
*/
isUserNewBeta: boolean;
- isDatabasesMonitorEnabled: boolean;
- isDatabasesMonitorBeta: boolean;
}
/**
@@ -75,18 +78,16 @@ export const useIsDatabasesEnabled = (): IsDatabasesEnabled => {
return {
isDatabasesEnabled: isDatabasesV1Enabled || isDatabasesV2Enabled,
+ isDatabasesMonitorBeta: !!flags.dbaasV2MonitorMetrics?.beta,
+ isDatabasesMonitorEnabled: !!flags.dbaasV2MonitorMetrics?.enabled,
isDatabasesV1Enabled,
- isDatabasesV2Enabled,
-
isDatabasesV2Beta,
- isUserExistingBeta: isDatabasesV2Beta && isDatabasesV1Enabled,
- isUserNewBeta: isDatabasesV2Beta && !isDatabasesV1Enabled,
-
+ isDatabasesV2Enabled,
isDatabasesV2GA:
(isDatabasesV1Enabled || isDatabasesV2Enabled) && hasV2GAFlag,
- isDatabasesMonitorEnabled: !!flags.dbaasV2MonitorMetrics?.enabled,
- isDatabasesMonitorBeta: !!flags.dbaasV2MonitorMetrics?.beta,
+ isUserExistingBeta: isDatabasesV2Beta && isDatabasesV1Enabled,
+ isUserNewBeta: isDatabasesV2Beta && !isDatabasesV1Enabled,
};
}
@@ -95,17 +96,14 @@ export const useIsDatabasesEnabled = (): IsDatabasesEnabled => {
return {
isDatabasesEnabled: hasLegacyTypes || hasDefaultTypes,
+ isDatabasesMonitorBeta: !!flags.dbaasV2MonitorMetrics?.beta,
+ isDatabasesMonitorEnabled: !!flags.dbaasV2MonitorMetrics?.enabled,
isDatabasesV1Enabled: hasLegacyTypes,
- isDatabasesV2Enabled: hasDefaultTypes,
-
isDatabasesV2Beta: hasDefaultTypes && hasV2BetaFlag,
+ isDatabasesV2Enabled: hasDefaultTypes,
+ isDatabasesV2GA: (hasLegacyTypes || hasDefaultTypes) && hasV2GAFlag,
isUserExistingBeta: hasLegacyTypes && hasDefaultTypes && hasV2BetaFlag,
isUserNewBeta: !hasLegacyTypes && hasDefaultTypes && hasV2BetaFlag,
-
- isDatabasesV2GA: (hasLegacyTypes || hasDefaultTypes) && hasV2GAFlag,
-
- isDatabasesMonitorEnabled: !!flags.dbaasV2MonitorMetrics?.enabled,
- isDatabasesMonitorBeta: !!flags.dbaasV2MonitorMetrics?.beta,
};
};
@@ -169,8 +167,7 @@ export const toSelectedDateTime = (
const isoTime = DateTime.now()
.set({ hour: time, minute: 0 })
?.toISOTime({ includeOffset: false });
- const selectedDateTime = DateTime.fromISO(`${isoDate}T${isoTime}`);
- return selectedDateTime;
+ return DateTime.fromISO(`${isoDate}T${isoTime}`);
};
/**