Skip to content

Commit

Permalink
ISPN-16412 display failed caches
Browse files Browse the repository at this point in the history
  • Loading branch information
karesti committed Sep 13, 2024
1 parent 4dfc295 commit 8fb7275
Show file tree
Hide file tree
Showing 13 changed files with 257 additions and 82 deletions.
10 changes: 5 additions & 5 deletions cypress/e2e/1_rbac_func.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('RBAC Functionality Tests', () => {
checkNotOwnSecuredCache('a-rbac-test-cache');
checkNonSecuredCacheDetailView(true, false);
checkMenu(false);
cy.login(monitorUserName, Cypress.env('password'), '/cache/default');
cy.login(monitorUserName, Cypress.env('password'), '/cache/indexed-cache');
checkNoEntriesTabView(false);
cy.login(monitorUserName, Cypress.env('password'), '/global-stats');
checkGlobalStatsView(false)
Expand All @@ -36,7 +36,7 @@ describe('RBAC Functionality Tests', () => {
//Go to tasks (@TODO at the moment for observer no tasks are shown, add after fix)
checkSchemasPageView(false);
checkCountersPageView();
cy.login(observerUserName, Cypress.env('password'), '/cache/default');
cy.login(observerUserName, Cypress.env('password'), '/cache/not-encoded');
checkNoEntriesTabView(false);
cy.login(observerUserName, Cypress.env('password'), '/global-stats');
checkGlobalStatsView(false)
Expand All @@ -55,7 +55,7 @@ describe('RBAC Functionality Tests', () => {
//Go to tasks (@TODO at the moment for observer no tasks are shown, add after fix)
checkSchemasPageView(false);
checkCountersPageView();
cy.login(applicationUserName, Cypress.env('password'), '/cache/default');
cy.login(applicationUserName, Cypress.env('password'), '/cache/not-encoded');
checkNoEntriesTabView(false);
cy.login(applicationUserName, Cypress.env('password'), '/global-stats');
checkGlobalStatsView(false)
Expand All @@ -74,7 +74,7 @@ describe('RBAC Functionality Tests', () => {
//Go to tasks (@TODO at the moment for observer no tasks are shown, add after fix)
checkSchemasPageView(true);
checkCountersPageView();
cy.login(deployerUserName, Cypress.env('password'), '/cache/default');
cy.login(deployerUserName, Cypress.env('password'), '/cache/not-encoded');
checkNoEntriesTabView(false);
cy.login(deployerUserName, Cypress.env('password'), '/global-stats');
checkGlobalStatsView(false)
Expand All @@ -94,7 +94,7 @@ describe('RBAC Functionality Tests', () => {
checkSchemasPageView(true);
checkCountersPageView();
checkTasksPage();
cy.login(Cypress.env('username'), Cypress.env('password'), '/cache/default');
cy.login(Cypress.env('username'), Cypress.env('password'), '/cache/not-encoded');
checkNoEntriesTabView(true);
});

Expand Down
12 changes: 12 additions & 0 deletions src/app/CacheManagers/CacheTableDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,18 @@ const CacheTableDisplay = (props: { setCachesCount: (count: number) => void; isV
);
};

if (loadingCaches) {
return (
<EmptyState variant={EmptyStateVariant.sm}>
<EmptyStateHeader
titleText={<>{t('cache-managers.loading-caches')}</>}
icon={<EmptyStateIcon icon={Spinner} />}
headingLevel="h4"
/>
</EmptyState>
);
}

return (
<React.Fragment>
{!loadingCaches && !rowsLoading && caches.length == 0 ? (
Expand Down
97 changes: 67 additions & 30 deletions src/app/Caches/CacheMetrics.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';
import {
Button,
ButtonVariant,
Card,
CardBody,
CardTitle,
EmptyState,
EmptyStateActions,
EmptyStateBody,
EmptyStateFooter,
EmptyStateHeader,
EmptyStateIcon,
EmptyStateVariant,
Expand All @@ -20,7 +24,7 @@ import {
TextVariants
} from '@patternfly/react-core';
import displayUtils from '@services/displayUtils';
import { CubesIcon } from '@patternfly/react-icons';
import { CubesIcon, ExclamationCircleIcon } from '@patternfly/react-icons';
import { QueryMetrics } from '@app/Caches/Query/QueryMetrics';
import { DataDistributionChart } from './DataDistributionChart';
import { PopoverHelp } from '@app/Common/PopoverHelp';
Expand All @@ -32,32 +36,24 @@ import { ConsoleServices } from '@services/ConsoleServices';
import { useConnectedUser } from '@app/services/userManagementHook';
import { ConsoleACL } from '@services/securityService';
import { CacheLifecycle } from '@app/Caches/CacheLifecycle';
import { global_danger_color_200 } from '@patternfly/react-tokens';
import { Link } from 'react-router-dom';

const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
const { t } = useTranslation();
const { connectedUser } = useConnectedUser();
const { cache, error, loading } = useCacheDetail();
const [stats, setStats] = useState<CacheStats | undefined>(cache.stats);
const [displayQueryStats, setDisplayQueryStats] = useState<boolean>(false);
const [displayDataDistribution, setDisplayDataDistribution] = useState<boolean>(false);
const [memory, setMemory] = useState<string | undefined>(undefined);
const { t } = useTranslation();
const brandname = t('brandname.brandname');

useEffect(() => {
if (ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
// Data distribution is for admin only
setDisplayDataDistribution(true);
const loadMemory = cache.memory;
if (loadMemory) {
setMemory(loadMemory.storage_type == 'OFF_HEAP' ? StorageType.OFF_HEAP : StorageType.HEAP);
} else {
setMemory(StorageType.HEAP);
}
const [displayQueryStats, setDisplayQueryStats] = useState<boolean>(cache.queryable!);
const [displayDataDistribution, setDisplayDataDistribution] = useState<boolean>(
ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)
);
const memory = () => {
if (cache.memory) {
return cache.memory.storage_type == 'OFF_HEAP' ? StorageType.OFF_HEAP : StorageType.HEAP;
}

setStats(cache.stats);
setDisplayQueryStats(cache.queryable);
}, [cache, error]);
return StorageType.HEAP;
};

const buildOperationsPerformanceCard = () => {
if (!stats) {
Expand Down Expand Up @@ -180,7 +176,7 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
return '';
}
let content;
if (memory === StorageType.OFF_HEAP) {
if (memory() === StorageType.OFF_HEAP) {
content = (
<React.Fragment>
<TextListItem aria-label="view-cache-metrics-off-heap" component={TextListItemVariants.dt}>
Expand Down Expand Up @@ -242,18 +238,59 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
};

if (!props.display) {
return <span />;
return <></>;
}

if (loading && error.length == 0) {
return (
<Card>
<CardBody>
<EmptyState>
<EmptyStateHeader
titleText={t('common.loading')}
headingLevel="h4"
icon={<EmptyStateIcon icon={Spinner} />}
/>
</EmptyState>
</CardBody>
</Card>
);
}

if (!stats || loading) {
return <Spinner size={'xl'} />;
if (error.length > 0) {
return (
<Card>
<CardBody>
<EmptyState variant={EmptyStateVariant.sm}>
<EmptyStateHeader
titleText={<>{`An error occurred while retrieving stats ${props.cacheName}`}</>}
icon={<EmptyStateIcon icon={ExclamationCircleIcon} color={global_danger_color_200.value} />}
headingLevel="h2"
/>
<EmptyStateBody>{error}</EmptyStateBody>
<EmptyStateFooter>
<EmptyStateActions>
<Link
to={{
pathname: '/',
search: location.search
}}
>
<Button variant={ButtonVariant.secondary}>{t('common.actions.back')}</Button>
</Link>
</EmptyStateActions>
</EmptyStateFooter>
</EmptyState>
</CardBody>
</Card>
);
}

if (!stats.enabled) {
if (stats && !stats.enabled) {
return (
<EmptyState variant={EmptyStateVariant.sm}>
<EmptyStateHeader
titleText={<>{t('caches.cache-metrics.metrics-title')}</>}
titleText={t('caches.cache-metrics.metrics-title')}
icon={<EmptyStateIcon icon={CubesIcon} />}
headingLevel="h5"
/>
Expand All @@ -273,8 +310,8 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
<GridItem span={4}>{buildOperationsPerformanceCard()}</GridItem>
{displayDataDistribution && <GridItem span={8}> {buildDataDistribution()}</GridItem>}
<GridItem span={4}>
<CacheLifecycle stats={stats} />
<DataAccess cacheName={props.cacheName} stats={stats} />
<CacheLifecycle stats={stats!} />
<DataAccess cacheName={props.cacheName} stats={stats!} />
</GridItem>
<GridItem span={displayDataDistribution ? 12 : 8}>{buildQueryStats()}</GridItem>
</Grid>
Expand Down
61 changes: 52 additions & 9 deletions src/app/Caches/DetailCache.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { ThemeContext } from '@app/providers/ThemeProvider';
import { useNavigate } from 'react-router';
import { TracingEnabled } from '@app/Common/TracingEnabled';
import { AlertIcon } from '@patternfly/react-core/dist/js/components/Alert/AlertIcon';
import { Health } from '@app/Common/Health';

const DetailCache = (props: { cacheName: string }) => {
const cacheName = props.cacheName;
Expand All @@ -84,7 +85,11 @@ const DetailCache = (props: { cacheName: string }) => {
return;
}

if (cache.editable && ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
if (
cache.started &&
cache.editable &&
ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)
) {
setActiveTabKey1(0);
} else if (ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
setActiveTabKey1(1);
Expand All @@ -94,7 +99,7 @@ const DetailCache = (props: { cacheName: string }) => {
}, [cache]);

const buildEntriesTabContent = () => {
if (!ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
if (cache.started && !ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
return '';
}

Expand Down Expand Up @@ -127,7 +132,7 @@ const DetailCache = (props: { cacheName: string }) => {
};

const entriesTabEnabled = (): boolean => {
return cache.editable && ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser);
return cache.editable! && ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser);
};

const buildDetailContent = () => {
Expand Down Expand Up @@ -177,7 +182,11 @@ const DetailCache = (props: { cacheName: string }) => {
if (activeTabKey1 == 1) {
return (
cache.configuration && (
<CacheConfiguration cacheName={cache.name} editable={cache.editable} config={cache.configuration.config} />
<CacheConfiguration
cacheName={cache.name}
editable={cache?.editable || true}
config={cache.configuration.config}
/>
)
);
}
Expand Down Expand Up @@ -208,11 +217,15 @@ const DetailCache = (props: { cacheName: string }) => {
};

const displayBackupsManagement = () => {
return cache?.features.hasRemoteBackup && ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser);
return (
cache &&
cache?.features?.hasRemoteBackup &&
ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)
);
};

const displayIndexManage = () => {
return cache?.features.indexed;
return cache && cache?.features?.indexed;
};

const buildBackupsManage = () => {
Expand Down Expand Up @@ -266,7 +279,7 @@ const DetailCache = (props: { cacheName: string }) => {
};

const buildTracing = () => {
if (!cacheManager || !cacheManager.tracing_enabled) return;
if (!cacheManager || !cacheManager.tracing_enabled || !cache || !cache.started) return;

return (
<DropdownItem
Expand Down Expand Up @@ -344,7 +357,7 @@ const DetailCache = (props: { cacheName: string }) => {
{cacheManager.tracing_enabled && (
<React.Fragment>
<ToolbarItem>
<TracingEnabled enabled={cache.tracing} />
<TracingEnabled enabled={cache.tracing!} />
</ToolbarItem>
<ToolbarItem variant="separator"></ToolbarItem>
</React.Fragment>
Expand Down Expand Up @@ -464,6 +477,36 @@ const DetailCache = (props: { cacheName: string }) => {
);
}

if (!cache.started) {
// cache is not ok
return (
<React.Fragment>
<Toolbar id="cache-detail-header">
<ToolbarContent>
<ToolbarGroup>
<ToolbarItem>
<Flex>
<FlexItem>
<TextContent>
<Text component={TextVariants.h1}>{cache.name}</Text>
</TextContent>
</FlexItem>
<FlexItem>
<Health health={cache.health} displayIcon={true} cacheName={cache.name} />
</FlexItem>
</Flex>
</ToolbarItem>
</ToolbarGroup>
{displayActions}
</ToolbarContent>
</Toolbar>
<Tabs isBox={false} activeKey={activeTabKey1} isSecondary={true} component={TabsComponent.nav}>
{displayConfiguration()}
</Tabs>
</React.Fragment>
);
}

return (
<React.Fragment>
<Toolbar id="cache-detail-header">
Expand All @@ -475,7 +518,7 @@ const DetailCache = (props: { cacheName: string }) => {
</TextContent>
</ToolbarItem>
<ToolbarItem>
<CacheTypeBadge cacheType={cache.type} small={true} cacheName={cache.name} />
<CacheTypeBadge cacheType={cache.type!} small={true} cacheName={cache.name} />
</ToolbarItem>
{buildFeaturesChip()}
</ToolbarGroup>
Expand Down
Loading

0 comments on commit 8fb7275

Please sign in to comment.