Skip to content

Commit faa6873

Browse files
authored
upcoming: [UIE-10179] - Use new hostname endpoints in Service URIs (#13439)
## Description 📝 Use new hosts endpoints field to populate General and PgBouncer Service URIs. If a VPC is public, display both public and private Service URIs ## How to test 🧪 ### Prerequisites (How to setup test environment) - Use the legacy MSW and ensure you have the pgbouncer and hostnamesEndpoint feature flag on ### Verification steps (How to verify changes) - [ ] In the makeMockDatabase function in serverHandlers.ts, comment/uncomment out some of the values to simulate No VPC (public only), VPC with no public access (private only), VPC with public access (private and public) - [ ] Go to a postgres Database cluster's details page - [ ] If there is no VPC, you should see a general and pgbouncer service URI with _public_ addresses - [ ] If there is a VPC with no public access, you should see a general and pgbouncer service URI with _private_ addresses - [ ] If there is a VPC with public access, you should see 2 general and pgbouncer service URIs with _public_ and _private_ addresses along with an info tooltip for the private address - [ ] Test different screen sizes, test mysql database (there should be no pgbouncer service URIs, only general)
1 parent 10b0552 commit faa6873

10 files changed

Lines changed: 454 additions & 90 deletions

File tree

packages/api-v4/src/databases/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,6 @@ type MemberType = 'failover' | 'primary';
120120
export interface DatabaseInstance {
121121
allow_list: string[];
122122
cluster_size: ClusterSize;
123-
/** @Deprecated replaced by `endpoints` property */
124-
connection_pool_port: null | number;
125123
connection_strings: ConnectionStrings[];
126124
created: string;
127125
/** @Deprecated used by rdbms-legacy only, rdbms-default always encrypts */
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+
Use new hostname endpoints in Service URIs and display public/private URIs for public VPCs ([#13439](https://github.com/linode/manager/pull/13439))

packages/manager/src/factories/databases.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ export const databaseInstanceFactory =
161161
? ([1, 3][i % 2] as ClusterSize)
162162
: ([1, 2, 3][i % 3] as ClusterSize)
163163
),
164-
connection_pool_port:
165-
null /** @Deprecated replaced by `endpoints` property */,
166164
connection_strings: [],
167165
created: '2021-12-09T17:15:12',
168166
encrypted: false,
@@ -203,9 +201,7 @@ export const databaseInstanceFactory =
203201
members: {
204202
'2.2.2.2': 'primary',
205203
},
206-
platform: Factory.each((i) =>
207-
adb10(i) ? 'rdbms-legacy' : 'rdbms-default'
208-
),
204+
platform: 'rdbms-default',
209205
region: Factory.each((i) => possibleRegions[i % possibleRegions.length]),
210206
status: Factory.each((i) => possibleStatuses[i % possibleStatuses.length]),
211207
type: Factory.each((i) => possibleTypes[i % possibleTypes.length]),
@@ -230,8 +226,6 @@ export const databaseInstanceFactory =
230226
export const databaseFactory = Factory.Sync.makeFactory<Database>({
231227
allow_list: [...IPv4List],
232228
cluster_size: Factory.each(() => pickRandom([1, 3])),
233-
connection_pool_port:
234-
null /** @Deprecated replaced by `endpoints` property */,
235229
connection_strings: [
236230
{
237231
driver: 'python',
@@ -277,7 +271,7 @@ export const databaseFactory = Factory.Sync.makeFactory<Database>({
277271
'2.2.2.2': 'primary',
278272
},
279273
oldest_restore_time: '2024-09-15T17:15:12',
280-
platform: Factory.each((i) => (adb10(i) ? 'rdbms-legacy' : 'rdbms-default')),
274+
platform: 'rdbms-default',
281275
private_network: null,
282276
port: 3306,
283277
region: 'us-east',

packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.test.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@ import { DatabaseConnectionPools } from './DatabaseConnectionPools';
1414
const mockDatabase = databaseFactory.build({
1515
platform: 'rdbms-default',
1616
private_network: null,
17+
hosts: {
18+
primary: 'db-mysql-primary-0.b.linodeb.net',
19+
endpoints: [
20+
{
21+
role: 'primary',
22+
address: 'db-mysql-primary-0.b.linodeb.net',
23+
port: 15847,
24+
public_access: true,
25+
},
26+
{
27+
role: 'primary-connection-pool',
28+
address: 'public-db-mysql-primary-0.b.linodeb.net',
29+
port: 15848,
30+
public_access: true,
31+
},
32+
],
33+
},
1734
engine: 'postgresql',
1835
id: 1,
1936
});
@@ -109,13 +126,15 @@ describe('DatabaseConnectionPools Component', () => {
109126
expect(errorStateText).toBeInTheDocument();
110127
});
111128

112-
it('should render service URI component if there are connection pools', () => {
129+
it('should render service URI component if there are connection pools and hostnameEndpoints flag is true', () => {
113130
queryMocks.useDatabaseConnectionPoolsQuery.mockReturnValue({
114131
data: makeResourcePage([mockConnectionPool]),
115132
isLoading: false,
116133
});
117134

118-
renderWithTheme(<DatabaseConnectionPools database={mockDatabase} />);
135+
renderWithTheme(<DatabaseConnectionPools database={mockDatabase} />, {
136+
flags: { hostnameEndpoints: true },
137+
});
119138
const serviceURIText = screen.getByText('Service URI');
120139
expect(serviceURIText).toBeInTheDocument();
121140
});

packages/manager/src/features/Databases/DatabaseDetail/DatabaseNetworking/DatabaseConnectionPools.tsx

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Stack,
88
Typography,
99
} from '@linode/ui';
10+
import Grid from '@mui/material/Grid';
1011
import { useTheme } from '@mui/material/styles';
1112
import { Pagination } from 'akamai-cds-react-components/Pagination';
1213
import {
@@ -28,6 +29,12 @@ import {
2829
CONNECTION_POOL_LABEL_CELL_STYLES,
2930
MANAGE_CONNECTION_POOLS_LEARN_MORE_LINK,
3031
} from 'src/features/Databases/constants';
32+
import {
33+
StyledGridContainer,
34+
StyledLabelTypography,
35+
StyledValueGrid,
36+
} from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style';
37+
import { useFlags } from 'src/hooks/useFlags';
3138
import { usePaginationV2 } from 'src/hooks/usePaginationV2';
3239

3340
import { makeSettingsItemStyles } from '../../shared.styles';
@@ -47,6 +54,7 @@ interface Props {
4754
export const DatabaseConnectionPools = ({ database }: Props) => {
4855
const { classes } = makeSettingsItemStyles();
4956
const theme = useTheme();
57+
const flags = useFlags();
5058
const isDatabaseInactive = database.status !== 'active';
5159

5260
const [deletePoolLabelSelection, setDeletePoolLabelSelection] =
@@ -80,6 +88,9 @@ export const DatabaseConnectionPools = ({ database }: Props) => {
8088
);
8189
}
8290

91+
const hasVPC = Boolean(database?.private_network?.vpc_id);
92+
const hasPublicVPC = hasVPC && database.private_network?.public_access;
93+
8394
return (
8495
<>
8596
<div className={classes.topSection}>
@@ -110,9 +121,42 @@ export const DatabaseConnectionPools = ({ database }: Props) => {
110121
Add Pool
111122
</Button>
112123
</div>
113-
{connectionPools && connectionPools.data.length > 0 && (
114-
<ServiceURI database={database} />
115-
)}
124+
{flags?.hostnameEndpoints &&
125+
connectionPools &&
126+
connectionPools.data.length > 0 && (
127+
<StyledGridContainer container size={12} spacing={0}>
128+
<Grid
129+
size={{
130+
md: 2,
131+
xs: 3,
132+
}}
133+
>
134+
<StyledLabelTypography>
135+
{hasPublicVPC ? 'Public Service URI' : 'Service URI'}
136+
</StyledLabelTypography>
137+
</Grid>
138+
<StyledValueGrid size={{ md: 10, xs: 9 }}>
139+
<ServiceURI database={database} />
140+
</StyledValueGrid>
141+
{hasPublicVPC && (
142+
<>
143+
<Grid
144+
size={{
145+
md: 2,
146+
xs: 3,
147+
}}
148+
>
149+
<StyledLabelTypography>
150+
Private Service URI
151+
</StyledLabelTypography>
152+
</Grid>
153+
<StyledValueGrid size={{ md: 10, xs: 9 }}>
154+
<ServiceURI database={database} showPrivateVPC />
155+
</StyledValueGrid>
156+
</>
157+
)}
158+
</StyledGridContainer>
159+
)}
116160
<div style={{ overflowX: 'auto', width: '100%' }}>
117161
<Table
118162
aria-label={'List of Connection pools'}

packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummary.tsx

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { styled } from '@mui/material/styles';
55
import * as React from 'react';
66

77
import ClusterConfiguration from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration';
8+
import {
9+
StyledGridContainer,
10+
StyledLabelTypography,
11+
StyledValueGrid,
12+
} from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style';
813
import ConnectionDetails from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails';
914
import { useFlags } from 'src/hooks/useFlags';
1015

@@ -28,6 +33,9 @@ export const DatabaseSummary = () => {
2833
connectionPools &&
2934
connectionPools.data.length > 0;
3035

36+
const hasVPC = Boolean(database?.private_network?.vpc_id);
37+
const hasPublicVPC = hasVPC && database.private_network?.public_access;
38+
3139
return (
3240
<Paper>
3341
<Grid container spacing={2}>
@@ -47,7 +55,7 @@ export const DatabaseSummary = () => {
4755
>
4856
<ConnectionDetails database={database} />
4957
</Grid>
50-
{showPgBouncerConnectionDetails && (
58+
{flags.hostnameEndpoints && showPgBouncerConnectionDetails && (
5159
<Grid
5260
size={{
5361
md: 12,
@@ -57,7 +65,38 @@ export const DatabaseSummary = () => {
5765
<Typography mb={2} variant="h3">
5866
PgBouncer Connection Details
5967
</Typography>
60-
<ServiceURI database={database} />
68+
<StyledGridContainer container size={12} spacing={0}>
69+
<Grid
70+
size={{
71+
md: 2,
72+
xs: 3,
73+
}}
74+
>
75+
<StyledLabelTypography>
76+
{hasPublicVPC ? 'Public Service URI' : 'Service URI'}
77+
</StyledLabelTypography>
78+
</Grid>
79+
<StyledValueGrid size={{ md: 10, xs: 9 }}>
80+
<ServiceURI database={database} />
81+
</StyledValueGrid>
82+
{hasPublicVPC && (
83+
<>
84+
<Grid
85+
size={{
86+
md: 2,
87+
xs: 3,
88+
}}
89+
>
90+
<StyledLabelTypography>
91+
Private Service URI
92+
</StyledLabelTypography>
93+
</Grid>
94+
<StyledValueGrid size={{ md: 10, xs: 9 }}>
95+
<ServiceURI database={database} showPrivateVPC />
96+
</StyledValueGrid>
97+
</>
98+
)}
99+
</StyledGridContainer>
61100
</Grid>
62101
)}
63102
</Grid>

packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,32 @@ export const DatabaseSummaryConnectionDetails = (props: Props) => {
117117
</>
118118
);
119119

120+
const hasPublicVPC = hasVPC && database.private_network?.public_access;
121+
const showServiceURIs = flags.hostnameEndpoints && flags.databasePgBouncer;
122+
120123
return (
121124
<>
122125
<Typography className={classes.header} variant="h3">
123126
Connection Details
124127
</Typography>
125128
<StyledGridContainer container size={{ lg: 10, md: 10 }} spacing={0}>
126-
{flags.databasePgBouncer && (
127-
<ConnectionDetailsRow isSummaryTab label="Service URI">
129+
{showServiceURIs && (
130+
<ConnectionDetailsRow
131+
isSummaryTab
132+
label={`${hasPublicVPC ? 'Public Service URI' : 'Service URI'} `}
133+
>
128134
<ServiceURI database={database} isGeneralServiceURI />
129135
</ConnectionDetailsRow>
130136
)}
137+
{showServiceURIs && hasPublicVPC && (
138+
<ConnectionDetailsRow isSummaryTab label="Private Service URI">
139+
<ServiceURI
140+
database={database}
141+
isGeneralServiceURI
142+
showPrivateVPC={true}
143+
/>
144+
</ConnectionDetailsRow>
145+
)}
131146
<ConnectionDetailsRow isSummaryTab label="Username">
132147
{username}
133148
</ConnectionDetailsRow>

0 commit comments

Comments
 (0)