1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 08:19:40 +02:00

feat(license): remove untrusted devices from node count [EE-5357] (#8817)

This commit is contained in:
Chaim Lev-Ari 2023-05-05 09:02:31 +07:00 committed by GitHub
parent 5f6ddc2fad
commit cfed481d6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 102 additions and 35 deletions

View file

@ -6,12 +6,12 @@ import { useDeleteEnvironmentsMutation } from '@/react/portainer/environments/qu
import { Datatable as GenericDatatable } from '@@/datatables';
import { Button } from '@@/buttons';
import { TextTip } from '@@/Tip/TextTip';
import { createPersistedStore } from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
import { confirm } from '@@/modals/confirm';
import { buildConfirmButton } from '@@/modals/utils';
import { ModalType } from '@@/modals';
import { TooltipWithChildren } from '@@/Tip/TooltipWithChildren';
import { useAssociateDeviceMutation, useLicenseOverused } from '../queries';
@ -26,7 +26,7 @@ const settingsStore = createPersistedStore(storageKey, 'Name');
export function Datatable() {
const associateMutation = useAssociateDeviceMutation();
const removeMutation = useDeleteEnvironmentsMutation();
const licenseOverused = useLicenseOverused();
const { willExceed } = useLicenseOverused();
const tableState = useTableState(settingsStore, storageKey);
const { data: environments, totalCount, isLoading } = useEnvironments();
@ -41,28 +41,34 @@ export function Datatable() {
<>
<Button
onClick={() => handleRemoveDevice(selectedRows)}
disabled={selectedRows.length === 0 || licenseOverused}
disabled={selectedRows.length === 0}
color="dangerlight"
icon={Trash2}
>
Remove Device
</Button>
<Button
onClick={() => handleAssociateDevice(selectedRows)}
disabled={selectedRows.length === 0 || licenseOverused}
<TooltipWithChildren
message={
willExceed(selectedRows.length) && (
<>
Associating devices is disabled as your node count exceeds
your license limit
</>
)
}
>
Associate Device
</Button>
{licenseOverused ? (
<div className="ml-2 mt-2">
<TextTip color="orange">
Associating devices is disabled as your node count exceeds your
license limit
</TextTip>
</div>
) : null}
<span>
<Button
onClick={() => handleAssociateDevice(selectedRows)}
disabled={
selectedRows.length === 0 || willExceed(selectedRows.length)
}
>
Associate Device
</Button>
</span>
</TooltipWithChildren>
</>
)}
isLoading={isLoading}

View file

@ -3,12 +3,17 @@ import { withLimitToBE } from '@/react/hooks/useLimitToBE';
import { InformationPanel } from '@@/InformationPanel';
import { TextTip } from '@@/Tip/TextTip';
import { PageHeader } from '@@/PageHeader';
import { Link } from '@@/Link';
import { Alert } from '@@/Alert';
import { Datatable } from './Datatable';
import { useLicenseOverused, useUntrustedCount } from './queries';
export default withLimitToBE(WaitingRoomView);
function WaitingRoomView() {
const untrustedCount = useUntrustedCount();
const { willExceed } = useLicenseOverused();
return (
<>
<PageHeader
@ -27,6 +32,19 @@ function WaitingRoomView() {
</TextTip>
</InformationPanel>
{willExceed(untrustedCount) && (
<div className="row">
<div className="col-sm-12">
<Alert color="warn">
Associating all nodes in waiting room will exceed the node limit
of your current license. Go to{' '}
<Link to="portainer.licenses">Licenses</Link> page to view the
current usage.
</Alert>
</div>
</div>
)}
<Datatable />
</>
);

View file

@ -1,9 +1,10 @@
import { useMutation, useQueryClient } from 'react-query';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { EdgeTypes, EnvironmentId } from '@/react/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { promiseSequence } from '@/portainer/helpers/promise-utils';
import { useIntegratedLicenseInfo } from '@/react/portainer/licenses/use-license.service';
import { useEnvironmentList } from '@/react/portainer/environments/queries';
export function useAssociateDeviceMutation() {
const queryClient = useQueryClient();
@ -35,8 +36,23 @@ async function associateDevice(environmentId: EnvironmentId) {
export function useLicenseOverused() {
const integratedInfo = useIntegratedLicenseInfo();
if (integratedInfo && integratedInfo.licenseInfo.enforcedAt > 0) {
return true;
return {
willExceed,
isOverused: willExceed(0),
};
function willExceed(moreNodes: number) {
return (
!!integratedInfo &&
integratedInfo.usedNodes + moreNodes >= integratedInfo.licenseInfo.nodes
);
}
return false;
}
export function useUntrustedCount() {
const query = useEnvironmentList({
edgeDeviceUntrusted: true,
types: EdgeTypes,
});
return query.totalCount;
}