Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add managed field in Cluster resources #2366

Merged
merged 31 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8b767ac
Add managed field for cluster resource
rtorrero Feb 23, 2024
79f23d6
prepare resources for table rendering
EMaksy Feb 23, 2024
64e90d2
Refactor and fix es lint complains
EMaksy Feb 23, 2024
581c75b
Refactor resourcesTableConfig to be more explicit and add managed column
EMaksy Feb 26, 2024
53c8e64
Adjust tests to include managed resource field
rtorrero Feb 26, 2024
9f6f0cc
Adjust factory to include the managed field in resources
rtorrero Feb 26, 2024
7ef51a5
Add tooltip with count of unmanaged resources
EMaksy Feb 26, 2024
9df9d4e
Add unmanaged resource count in tooltip
EMaksy Feb 27, 2024
5313616
Change resource table config
EMaksy Feb 27, 2024
02972f3
Refactor ClusterNodeName component
EMaksy Feb 27, 2024
8a4459b
use lodash capitalize instead of tenery operator
EMaksy Feb 27, 2024
e8733aa
Use switch case for node status icons
EMaksy Feb 27, 2024
74db2db
Use cluster resource factory instead of literal
rtorrero Feb 28, 2024
a08292a
Refactor ClusterNodeName
EMaksy Feb 28, 2024
8bc19ff
Update test for ClusterNodeName
EMaksy Feb 28, 2024
eda7e2b
Adapt resources managed
rtorrero Feb 28, 2024
fada62e
Make managed a required field
rtorrero Feb 29, 2024
0ddec8e
Add formatting
rtorrero Feb 29, 2024
7b01a23
Address mix credo
rtorrero Feb 29, 2024
e33c22e
Refactor existing test for displaying node details
EMaksy Feb 29, 2024
a0e2c5a
Add unmanaged resource node story
EMaksy Mar 1, 2024
c18196c
Add managed key value to fixtures
EMaksy Mar 1, 2024
efff0bb
Add e2e test to check tooltip icon message
EMaksy Mar 1, 2024
bced77c
Use cluster_resource factory for cluster_details
rtorrero Mar 4, 2024
399b82c
Apply suggestions for parsing resources and nodes
rtorrero Mar 4, 2024
a97eb3c
Address further code readability suggestions
rtorrero Mar 4, 2024
5abe3c4
Remove e2e test for tooltip message
EMaksy Mar 4, 2024
293fe3f
Use factory for resources
EMaksy Mar 4, 2024
2071af7
Add new AttributeDetails test
EMaksy Mar 4, 2024
313791b
Refactor AttributeDetails.test.jsx
EMaksy Mar 4, 2024
e8626fa
Refactor the AttributesDetails test
EMaksy Mar 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions assets/js/lib/test-utils/data/clusters.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ export default [
role: 'Started',
status: 'Active',
type: 'stonith:external/sbd',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHanaTopology_HDD_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::suse:SAPHanaTopology',
managed: true,
},
],
site: 'NBG',
Expand Down Expand Up @@ -111,27 +113,31 @@ export default [
role: 'Master',
status: 'Active',
type: 'ocf::suse:SAPHana',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHanaTopology_HDD_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::suse:SAPHanaTopology',
managed: true,
},
{
fail_count: 0,
id: 'rsc_ip_HDD_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::heartbeat:IPaddr2',
managed: true,
},
{
fail_count: 0,
id: 'rsc_socat_HDD_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::heartbeat:azure-lb',
managed: true,
},
],
site: 'WDF',
Expand Down Expand Up @@ -200,34 +206,39 @@ export default [
role: 'Started',
status: 'Active',
type: 'stonith:external/sbd',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHana_HDQ_HDB10',
role: 'Master',
status: 'Active',
type: 'ocf::suse:SAPHana',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHanaTopology_HDQ_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::suse:SAPHanaTopology',
managed: true,
},
{
fail_count: 0,
id: 'rsc_ip_HDQ_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::heartbeat:IPaddr2',
managed: true,
},
{
fail_count: 0,
id: 'rsc_socat_HDQ_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::heartbeat:azure-lb',
managed: true,
},
],
site: 'NBG',
Expand Down Expand Up @@ -256,13 +267,15 @@ export default [
role: 'Slave',
status: 'Active',
type: 'ocf::suse:SAPHana',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHanaTopology_HDQ_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::suse:SAPHanaTopology',
managed: true,
},
],
site: 'WDF',
Expand Down Expand Up @@ -322,34 +335,39 @@ export default [
role: 'Started',
status: 'Active',
type: 'stonith:external/sbd',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHana_HDP_HDB10',
role: 'Master',
status: 'Active',
type: 'ocf::suse:SAPHana',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHanaTopology_HDP_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::suse:SAPHanaTopology',
managed: true,
},
{
fail_count: 0,
id: 'rsc_ip_HDP_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::heartbeat:IPaddr2',
managed: true,
},
{
fail_count: 0,
id: 'rsc_socat_HDP_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::heartbeat:azure-lb',
managed: true,
},
],
site: 'NBG',
Expand Down Expand Up @@ -378,13 +396,15 @@ export default [
role: 'Slave',
status: 'Active',
type: 'ocf::suse:SAPHana',
managed: true,
},
{
fail_count: 0,
id: 'rsc_SAPHanaTopology_HDP_HDB10',
role: 'Started',
status: 'Active',
type: 'ocf::suse:SAPHanaTopology',
managed: true,
},
],
site: 'WDF',
Expand Down
7 changes: 4 additions & 3 deletions assets/js/lib/test-utils/factories/clusters.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export const sbdDevicesFactory = Factory.define(() => ({

export const clusterResourceFactory = Factory.define(() => ({
id: faker.string.uuid(),
role: faker.animal.bear(),
status: faker.animal.bird(),
type: faker.animal.cat(),
role: faker.location.country(),
status: faker.vehicle.bicycle(),
type: faker.color.human(),
managed: faker.datatype.boolean(),
fail_count: faker.number.int(),
}));

Expand Down
4 changes: 2 additions & 2 deletions assets/js/pages/ClusterDetails/AscsErsClusterDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ const nodeDetailsConfig = {
{
title: 'Hostname',
key: '',
render: (_, { id, name, status }) => (
<ClusterNodeName hostId={id} status={status}>
render: (_, { id, name, status, resources }) => (
<ClusterNodeName hostId={id} status={status} resources={resources}>
{name}
</ClusterNodeName>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ describe('ClusterDetails AscsErsClusterDetails component', () => {
const sapSystems = buildSapSystemsFromAscsErsClusterDetails(details);

const {
nodes: [{ attributes, resources }],
nodes: [{ attributes }],
} = details.sap_systems[0];

renderWithRouter(
Expand All @@ -269,13 +269,6 @@ describe('ClusterDetails AscsErsClusterDetails component', () => {
expect(screen.getByText('Attributes')).toBeInTheDocument();
expect(screen.getByText('Resources')).toBeInTheDocument();

Object.keys(resources[0]).forEach((key) => {
expect(screen.getByText(key)).toBeInTheDocument();
screen.getAllByText(resources[0][key]).forEach((element) => {
expect(element).toBeInTheDocument();
});
});

Object.keys(attributes).forEach((key) => {
screen.getAllByText(key).forEach((element) => {
expect(element).toBeInTheDocument();
Expand Down
39 changes: 33 additions & 6 deletions assets/js/pages/ClusterDetails/AttributesDetails.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useState } from 'react';

import { capitalize } from 'lodash';

import Button from '@common/Button';
import Modal from '@common/Modal';
import Table from '@common/Table';

function AttributesDetails({ attributes, resources, title }) {
const [modalOpen, setModalOpen] = useState(false);

const attributesTableConfig = {
usePadding: false,
columns: [
Expand All @@ -19,12 +20,38 @@ function AttributesDetails({ attributes, resources, title }) {
resources.length > 0
? {
usePadding: false,
columns: Object.keys(resources[0]).map((key) => ({
title: key,
key,
})),
columns: [
{
title: 'fail count',
key: 'fail_count',
},
{
title: 'id',
key: 'id',
},
{
title: 'role',
key: 'role',
},
{
title: 'status',
key: 'status',
},
{
title: 'managed',
key: 'managed',
render: (content) => capitalize(`${content}`),
},
{
title: 'type',
key: 'type',
},
],
}
: { usePadding: false, columns: [] };
: {
usePadding: false,
columns: [],
};

return (
<>
Expand Down
120 changes: 120 additions & 0 deletions assets/js/pages/ClusterDetails/AttributesDetails.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from 'react';

import { screen, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { faker } from '@faker-js/faker';
import { capitalize } from 'lodash';

import { clusterResourceFactory } from '@lib/test-utils/factories';

import AttributesDetails from './AttributesDetails';

describe('AttributesDetails', () => {
it('should show empty attributes table', async () => {
const resources = clusterResourceFactory.buildList(1);
const attributes = [];
const pageTitle = faker.person.firstName();

render(
<AttributesDetails
attributes={attributes}
resources={resources}
title={pageTitle}
/>
);

const detailsButton = screen.getByText('Details');
await userEvent.click(detailsButton);

expect(screen.getByText(pageTitle)).toBeInTheDocument();
expect(screen.getByText('No data available')).toBeInTheDocument();
});

it('should show empty resources table', async () => {
const resources = [];
const attributes = { key1: 'value1', key2: 'value2' };
const pageTitle = faker.person.firstName();

render(
<AttributesDetails
attributes={attributes}
resources={resources}
title={pageTitle}
/>
);

const detailsButton = screen.getByText('Details');
await userEvent.click(detailsButton);

expect(screen.getByText(pageTitle)).toBeInTheDocument();

expect(screen.getByText('No data available')).toBeInTheDocument();
expect(screen.queryByText('fail count')).not.toBeInTheDocument();
});

it('should show attributes', async () => {
const resources = [];
const attributes = { key1: 'value1', key2: 'value2' };
const pageTitle = faker.person.firstName();

render(
<AttributesDetails
attributes={attributes}
resources={resources}
title={pageTitle}
/>
);

const detailsButton = screen.getByText('Details');
await userEvent.click(detailsButton);

expect(screen.getByText(pageTitle)).toBeInTheDocument();
const attributesTable = screen.getAllByRole('table')[0];
expect(
attributesTable.querySelectorAll('tbody > tr > td').item(0)
).toHaveTextContent('key1');
expect(
attributesTable.querySelectorAll('tbody > tr > td').item(1)
).toHaveTextContent('value1');
});

it('should show resources', async () => {
const resources = clusterResourceFactory.buildList(1);
const { id, role, status, type, managed, fail_count } = resources[0];
const attributes = {};
const pageTitle = faker.person.firstName();

render(
<AttributesDetails
attributes={attributes}
resources={resources}
title={pageTitle}
/>
);

const detailsButton = screen.getByText('Details');
await userEvent.click(detailsButton);

expect(screen.getByText(pageTitle)).toBeInTheDocument();
const resourceTable = screen.getAllByRole('table')[1];
expect(
resourceTable.querySelectorAll('tbody > tr > td').item(0)
).toHaveTextContent(fail_count);
expect(
resourceTable.querySelectorAll('tbody > tr > td').item(1)
).toHaveTextContent(id);
expect(
resourceTable.querySelectorAll('tbody > tr > td').item(2)
).toHaveTextContent(role);
expect(
resourceTable.querySelectorAll('tbody > tr > td').item(3)
).toHaveTextContent(status);
expect(
resourceTable.querySelectorAll('tbody > tr > td').item(4)
).toHaveTextContent(capitalize(`${managed}`));
expect(
resourceTable.querySelectorAll('tbody > tr > td').item(5)
).toHaveTextContent(type);
});
});
Loading
Loading