Skip to content

fix: [UIE-9487] VPC UI not displaying DBaaS resources#13504

Draft
smans-akamai wants to merge 5 commits intolinode:developfrom
smans-akamai:UIE-9487-display-vpc-ui-display-dbaas-resources
Draft

fix: [UIE-9487] VPC UI not displaying DBaaS resources#13504
smans-akamai wants to merge 5 commits intolinode:developfrom
smans-akamai:UIE-9487-display-vpc-ui-display-dbaas-resources

Conversation

@smans-akamai
Copy link
Copy Markdown
Contributor

@smans-akamai smans-akamai commented Mar 17, 2026

Description 📝

This pull request fixes an issue in the VPC UI where DBaaS resources aren't being counted or displayed.

This issue consists of the following:

  • The Resource counts shown in the VPC Landing page, VPC Details Summary, and VPC Details Subnets tables aren't including the number of databases in the count
  • In the VPC Details Subnets table, the resource tables shown under each expanded Subnet don't include a databases table in addition to the pre-existing Linode and Nodebalancer tables.

Changes 🔄

List any change(s) relevant to the reviewer.

  • Updating any Resource counts shown in the VPC Landing page, table, VPC Details Summary, and Subnets table to include the number of databases in the count.
  • In the VPC Details Subnets table, under an expanded Subnet, display a databases table in addition to the pre-existing Linode and Nodebalancer tables.
  • Introducing and integrating the new vpcDbaasResources feature flag

Scope 🚢

Upon production release, changes in this PR will be visible to:

  • All customers
  • Some customers (e.g. in Beta or Limited Availability)
  • No customers / Not applicable

Target release date 🗓️

TBD

Preview 📷

Note: The screenshots below are using mock data, so the data shown may not be accurate. The resource counts behavior will need to be checked using the verification steps that follow.

Databases Resource Tables Not displaying under expanded Subnet in VPC Details View

Before After
subnet-resource-tables-before subnet-resource-tables-after

Resource Count Locations in VPC:
VPC Landing Table
vpc-landing-resource-count

VPC Detail Summary and Subnets Table
*Note: The count in the summary is inaccurate. Use the verification steps to test this behavior.
vpc-details-resource-counts

How to test 🧪

Prerequisites

(How to setup test environment)

  • Have the vpcDbaasResources feature flag enabled in your local environment via VPC DBaaS Resources
  • Have access to the Staging environment and have a VPC and Subnet created.

Reproduction steps

Test the VPC workflow

  • In the staging environment, access the VPC tab, select the Create VPC and create a new VPC and Subnet in a region. Preferably one that doesn't currently have one. For example, US, Chicago, IL. Keep track of the region for this new VPC/Subnet.
  • Once created, it should navigate you back to the VPC landing page and you should see your new VPC in the table.
  • Observe that the resource count for that VPC in the table is currently 0, which is accurate.
  • Open the Dev tools Networking tab and keep it open
  • Click the VPC label in the table to navigate to the VPC details view.
  • In the Dev Tools networking tab, search for the subnets call (*/vpcs/{vpcID}/subnets) and inspect the response to see that databases property is currently an empty array
  • Observe that the VPC Summary and Subnets table below show a resource count of 0, which is accurate
  • Expand the Subnets table and see that the linodes table is displayed in an empty state.

Create a new database and assign the VPC/Subnet you created and retest the steps above

  • Access the databases tab and select Create Database Cluster
  • Create a database cluster in the same region, select 3 nodes for the cluster, and make sure to select the VPC and Subnet you just created. This will assign it as the resource for that VPC/Subnet.
  • Access the VPC tab and follow the Test the VPC workflow steps above.
  • See that the subnets call returns the databases property with a single database in the array, but the resource counts on all pages are still 0.
  • See that, when the subnet you created is expanded, it still only displays an empty linodes table and no databases table is shown.

Verification steps

(How to verify changes)
Testing the Resource Counts

  • In your local environment on the branch for this pull request, point it to staging.
  • Access the VPC tab and see that the resources count for the VPC you created in the verification steps now shows an accurate count (1 for the database that was assigned)
  • Click the VPC label to access the details view and see that the resource counts in the summary and subnets table is also updated to include this count.

Testing the database resources table under the expanded Subnet

  • Enable mock data in the local environment
  • In the ServerHandler.ts file, uncomment the newly added mock data under the */v4beta/vpcs/:vpcId/subnets listener.
  • Access the VPC tab and open the networking tab in Dev tools.
  • Click on one of the VPC labels to access the VPC details
  • In the dev tools Networking tab, search for networking tab for the subnets call (*/vpcs/{vpcID}/subnets) and inspect the response to see that databases property has 5 items listed.
  • In this view, expand the single Subnet from the mock data and see that the databases table now appears in addition the Linodes and Nodebalancers table.
Author Checklists

As an Author, to speed up the review process, I considered 🤔

👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support


  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All tests and CI checks are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

@smans-akamai smans-akamai added DBaaS Relates to Database as a Service VPC Relating to VPC project labels Mar 17, 2026
@smans-akamai smans-akamai self-assigned this Mar 17, 2026
@smans-akamai smans-akamai force-pushed the UIE-9487-display-vpc-ui-display-dbaas-resources branch from 5eb6f67 to 80d3e4c Compare March 24, 2026 20:43
borderTop: `1px solid ${theme.tokens.component.Table.Row.Border}`,
}}
/>
</>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added pagination since the databases table will be using the database list GET request which is paginated. The other tables (Linodes and Nodebalancers) loop through the IDs from the subnets response and make their instance calls, so they don't have to be paginated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using the default page size options (25, 50, 75, 100) and is set to default to 25 as that's the minimum size for the Get database list request.

Copy link
Copy Markdown
Contributor Author

@smans-akamai smans-akamai Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a screenshot of the pagination appearing below the table. This can only be seen with mock data is you make the database list response at least 26 databases in the serverHandler.ts file.

paginator-screenshot

const theme = useTheme();

const [pageSize, setPageSize] = React.useState(25);
const [page, setPage] = React.useState(1);
Copy link
Copy Markdown
Contributor Author

@smans-akamai smans-akamai Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose to store the page and pageSize property in state instead of using the usePaginationV2 hook that's used in the DatabaseLanding since there can be many of these and it might not make sense to store this information in preferences as the VPCs and Subnets can also be deleted.

Does this approach make sense for this unique case?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this

const numResources = isNodebalancerVPCEnabled
? getUniqueResourcesFromSubnets(
vpc.subnets,
flags.vpcDbaasResources ?? false
Copy link
Copy Markdown
Contributor Author

@smans-akamai smans-akamai Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the new vpcDbaasResources feature flag, in addition to hiding the databases table, the resource count fix is also behind this flag. I assumed we want the table to appear along with the updated count, so I've chosen to keep both changes behind the new feature flag for this reason.

id: 5,
label: 'database-instance-5',
});
const ids = Array.from({ length: 5 }, (_, i) => i + 1); // Update length to change the number of databases
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to make it a bit easier to control the length of the mock data. You can see something similar in the */v4beta/vpcs/:vpcId/subnets listener below that was also updated in this pull request.

databasesFilter,
isDefaultEnabled // TODO (UIE-8634): Determine if check if still necessary
isDefaultEnabled, // TODO (UIE-8634): Determine if check if still necessary
20000
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For more info, refer to my previous comment on the databases query.

}

return [primaryIPv4, ...failoverIPv4s].join(', ');
};
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic uses the members property to get the content for the IPv4 field that can be seen in the wireframes.

Comment on lines +43 to +50
// Retrieve failover IPv4 addresses as there can be multiple
const failoverIPv4s = memberKeys.filter(
(key) => database.members[key] === 'failover'
);

if (failoverIPv4s.length === 0) {
return primaryIPv4;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this early return above primaryIPv4?

Copy link
Copy Markdown
Contributor Author

@smans-akamai smans-akamai Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior for this is, if there aren't any failover IPV4s in the members property, it should display just the primaryIPv4 as IPv4AddressesContent. Otherwise it will display the primary IPv4 followed by the failoverIPv4s. I don't think we can return this early as it would need primaryIPv4 defined before it can be returned.

Copy link
Copy Markdown
Contributor Author

@smans-akamai smans-akamai Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to update this to include an early return for when there's only 1 item in the members object. It should be safe to assume that it's the primary IP and return it as the content in the row.

if (memberKeys.length === 1) {
  return memberKeys[0];
}

This way we'll only perform the additional logic to find the primary and failover IPV4s if there's more than 1 key in the members object.

const theme = useTheme();

const [pageSize, setPageSize] = React.useState(25);
const [page, setPage] = React.useState(1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this

Comment on lines +32 to +49
const assignedDatabasesMap = React.useMemo(() => {
const databaseMap: Record<number, SubnetAssignedDatabaseData> = {};
databasesData.forEach((assignedDatabase) => {
databaseMap[assignedDatabase.id] = assignedDatabase;
});
return databaseMap;
}, [databasesData]);

// Create filter using unique database IDs from the assigned databases
const makeDatabaseIDsFilter = React.useMemo(() => {
const uniqueIds = Object.values(assignedDatabasesMap).map((db) => {
return { id: db.id };
});

return {
'+or': uniqueIds,
};
}, [assignedDatabasesMap]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can simplify this to something like

Suggested change
const assignedDatabasesMap = React.useMemo(() => {
const databaseMap: Record<number, SubnetAssignedDatabaseData> = {};
databasesData.forEach((assignedDatabase) => {
databaseMap[assignedDatabase.id] = assignedDatabase;
});
return databaseMap;
}, [databasesData]);
// Create filter using unique database IDs from the assigned databases
const makeDatabaseIDsFilter = React.useMemo(() => {
const uniqueIds = Object.values(assignedDatabasesMap).map((db) => {
return { id: db.id };
});
return {
'+or': uniqueIds,
};
}, [assignedDatabasesMap]);
const databaseIDsToFilter = databasesData.map((database) => ({
id: database.id,
}));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hana-akamai We could use this instead of the makeDatabaseIDsFilter function, but this wouldn't work for the assignedDatabasesMap since that is meant to store the assigned databases data that we get back from the /subnets response. The map gets used in the SubnetDatabaseRow below that displays data from those assigned databases

Copy link
Copy Markdown
Contributor Author

@smans-akamai smans-akamai Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about simplifying it to something like this so we still have access to the assigned database data for the rows?

const assignedDatabasesMap: Record<number, SubnetAssignedDatabaseData> = {};

const databaseIDsToFilter = databasesData.map((database) => {
    // Store database data in map for easy lookup for rendering subnet database rows
    assignedDatabasesMap[database.id] = database;
    return {
      id: database.id,
    };
  });

Then access it in the SubnetDatabaseRow like this:

<SubnetDatabaseRow
  assignedDatabase={assignedDatabasesMap[database.id]}
  ...
/>

@smans-akamai smans-akamai force-pushed the UIE-9487-display-vpc-ui-display-dbaas-resources branch from 80d3e4c to b308124 Compare March 30, 2026 15:17
@linode-gh-bot
Copy link
Copy Markdown
Collaborator

Cloud Manager UI test results

🔺 1 failing test on test run #5 ↗︎

❌ Failing✅ Passing↪️ Skipped🕐 Duration
1 Failing887 Passing11 Skipped45m 44s

Details

Failing Tests
SpecTest
object-storage.e2e.spec.tsCloud Manager Cypress Tests→object storage end-to-end tests » can update bucket access

Troubleshooting

Use this command to re-run the failing tests:

pnpm cy:run -s "cypress/e2e/core/objectStorage/object-storage.e2e.spec.ts"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DBaaS Relates to Database as a Service VPC Relating to VPC project

Projects

Status: Review

Development

Successfully merging this pull request may close these issues.

3 participants