Skip to content

Commit 13a29bb

Browse files
authored
Merge branch 'kafbat:main' into main
2 parents 5b5b14c + 7ef51b5 commit 13a29bb

File tree

46 files changed

+344
-112
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+344
-112
lines changed

api/src/main/java/io/kafbat/ui/service/TopicsService.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import io.kafbat.ui.model.TopicCreationDTO;
2727
import io.kafbat.ui.model.TopicUpdateDTO;
2828
import java.time.Duration;
29+
import java.util.ArrayList;
2930
import java.util.Collection;
3031
import java.util.Collections;
3132
import java.util.Comparator;
@@ -288,6 +289,18 @@ private Map<TopicPartition, Optional<NewPartitionReassignment>> getPartitionsRea
288289
Map<Integer, Integer> brokersUsage = getBrokersMap(cluster, currentAssignment);
289290
int currentReplicationFactor = topic.getReplicationFactor();
290291

292+
// Get online nodes
293+
List<Integer> onlineNodes = statisticsCache.get(cluster).getClusterDescription().getNodes()
294+
.stream().map(Node::id).toList();
295+
296+
// keep only online nodes
297+
for (Map.Entry<Integer, List<Integer>> parition : currentAssignment.entrySet()) {
298+
parition.getValue().retainAll(onlineNodes);
299+
}
300+
301+
brokersUsage.keySet().retainAll(onlineNodes);
302+
303+
291304
// If we should to increase Replication factor
292305
if (replicationFactorChange.getTotalReplicationFactor() > currentReplicationFactor) {
293306
// For each partition
@@ -320,28 +333,35 @@ private Map<TopicPartition, Optional<NewPartitionReassignment>> getPartitionsRea
320333
var partition = assignmentEntry.getKey();
321334
var brokers = assignmentEntry.getValue();
322335

336+
// Copy from online nodes if all nodes are offline
337+
if (brokers.isEmpty()) {
338+
brokers = new ArrayList<>(onlineNodes);
339+
}
340+
323341
// Get brokers list sorted by usage in reverse order
324342
var brokersUsageList = brokersUsage.entrySet().stream()
325343
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
326344
.map(Map.Entry::getKey)
327345
.toList();
328346

347+
Integer leader = topic.getPartitions().get(partition).getLeader();
348+
329349
// Iterate brokers and try to remove them from assignment
330350
// while partition replicas count != requested replication factor
331351
for (Integer broker : brokersUsageList) {
352+
if (brokers.size() == replicationFactorChange.getTotalReplicationFactor()) {
353+
break;
354+
}
332355
// Check is the broker the leader of partition
333-
if (!topic.getPartitions().get(partition).getLeader()
334-
.equals(broker)) {
356+
if (leader == null || !leader.equals(broker)) {
335357
brokers.remove(broker);
336358
brokersUsage.merge(broker, -1, Integer::sum);
337359
}
338-
if (brokers.size() == replicationFactorChange.getTotalReplicationFactor()) {
339-
break;
340-
}
341360
}
342361
if (brokers.size() != replicationFactorChange.getTotalReplicationFactor()) {
343362
throw new ValidationException("Something went wrong during removing replicas");
344363
}
364+
currentAssignment.put(partition, brokers);
345365
}
346366
} else {
347367
throw new ValidationException("Replication factor already equals requested");
@@ -374,7 +394,7 @@ private Map<Integer, Integer> getBrokersMap(KafkaCluster cluster,
374394
c -> 0
375395
));
376396
currentAssignment.values().forEach(brokers -> brokers
377-
.forEach(broker -> result.put(broker, result.get(broker) + 1)));
397+
.forEach(broker -> result.put(broker, result.getOrDefault(broker, 0) + 1)));
378398

379399
return result;
380400
}

contract/src/main/resources/swagger/kafbat-ui-api.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4101,7 +4101,6 @@ components:
41014101
KafkaAclNamePatternType:
41024102
type: string
41034103
enum:
4104-
- MATCH
41054104
- LITERAL
41064105
- PREFIXED
41074106

frontend/src/components/ACLPage/Form/CustomACL/lib.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { KafkaAcl, KafkaAclNamePatternType } from 'generated-sources';
2-
import isRegex from 'lib/isRegex';
32
import { MatchType } from 'components/ACLPage/Form/types';
43

54
import { FormValues } from './types';
@@ -8,8 +7,6 @@ export function toRequest(formValue: FormValues): KafkaAcl {
87
let namePatternType: KafkaAclNamePatternType;
98
if (formValue.namePatternType === MatchType.PREFIXED) {
109
namePatternType = KafkaAclNamePatternType.PREFIXED;
11-
} else if (isRegex(formValue.resourceName)) {
12-
namePatternType = KafkaAclNamePatternType.MATCH;
1310
} else {
1411
namePatternType = KafkaAclNamePatternType.LITERAL;
1512
}

frontend/src/components/ACLPage/List/List.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React from 'react';
22
import { ColumnDef, Row } from '@tanstack/react-table';
3-
import PageHeading from 'components/common/PageHeading/PageHeading';
43
import Table from 'components/common/NewTable';
54
import { useConfirm } from 'lib/hooks/useConfirm';
65
import useAppParams from 'lib/hooks/useAppParams';
@@ -20,6 +19,8 @@ import { useTheme } from 'styled-components';
2019
import ACLFormContext from 'components/ACLPage/Form/AclFormContext';
2120
import PlusIcon from 'components/common/Icons/PlusIcon';
2221
import ActionButton from 'components/common/ActionComponent/ActionButton/ActionButton';
22+
import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading';
23+
import BreakableTextCell from 'components/common/NewTable/BreakableTextCell';
2324

2425
import * as S from './List.styled';
2526

@@ -56,6 +57,7 @@ const ACList: React.FC = () => {
5657
header: 'Principal',
5758
accessorKey: 'principal',
5859
size: 257,
60+
cell: BreakableTextCell,
5961
},
6062
{
6163
header: 'Resource',
@@ -149,7 +151,7 @@ const ACList: React.FC = () => {
149151

150152
return (
151153
<S.Container>
152-
<PageHeading text="Access Control List">
154+
<ResourcePageHeading text="Access Control List">
153155
<ActionButton
154156
buttonType="primary"
155157
buttonSize="M"
@@ -161,7 +163,7 @@ const ACList: React.FC = () => {
161163
>
162164
<PlusIcon /> Create ACL
163165
</ActionButton>
164-
</PageHeading>
166+
</ResourcePageHeading>
165167
<Table
166168
columns={columns}
167169
data={aclList ?? []}

frontend/src/components/Brokers/Broker/Broker.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React, { Suspense } from 'react';
2-
import PageHeading from 'components/common/PageHeading/PageHeading';
32
import * as Metrics from 'components/common/Metrics';
43
import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
54
import useAppParams from 'lib/hooks/useAppParams';
@@ -21,6 +20,7 @@ import Navbar from 'components/common/Navigation/Navbar.styled';
2120
import PageLoader from 'components/common/PageLoader/PageLoader';
2221
import { ActionNavLink } from 'components/common/ActionComponent';
2322
import { Action, ResourceType } from 'generated-sources';
23+
import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading';
2424

2525
import Configs from './Configs/Configs';
2626

@@ -38,7 +38,7 @@ const Broker: React.FC = () => {
3838
);
3939
return (
4040
<>
41-
<PageHeading
41+
<ResourcePageHeading
4242
text={`Broker ${brokerId}`}
4343
backTo={clusterBrokersPath(clusterName)}
4444
backText="Brokers"

frontend/src/components/Brokers/BrokersList/BrokersList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, { useMemo } from 'react';
22
import { ClusterName } from 'lib/interfaces/cluster';
33
import { useNavigate } from 'react-router-dom';
4-
import PageHeading from 'components/common/PageHeading/PageHeading';
54
import useAppParams from 'lib/hooks/useAppParams';
65
import Table from 'components/common/NewTable';
76
import { clusterBrokerPath } from 'lib/paths';
87
import { useBrokers } from 'lib/hooks/api/brokers';
98
import { useClusterStats } from 'lib/hooks/api/clusters';
9+
import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading';
1010

1111
import { BrokersMetrics } from './BrokersMetrics/BrokersMetrics';
1212
import { getBrokersTableColumns, getBrokersTableRows } from './lib';
@@ -45,7 +45,7 @@ const BrokersList: React.FC = () => {
4545

4646
return (
4747
<>
48-
<PageHeading text="Brokers" />
48+
<ResourcePageHeading text="Brokers" />
4949

5050
<BrokersMetrics
5151
brokerCount={brokerCount}

frontend/src/components/Brokers/BrokersList/lib/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as Cell from 'components/Brokers/BrokersList/TableCells/TableCells';
33
import { createColumnHelper } from '@tanstack/react-table';
44
import { keyBy } from 'lib/functions/keyBy';
55
import SkewHeader from 'components/Brokers/BrokersList/SkewHeader/SkewHeader';
6+
import BreakableTextCell from 'components/common/NewTable/BreakableTextCell';
67

78
import { BrokersTableRow } from './types';
89
import { NA_DISK_USAGE } from './constants';
@@ -75,6 +76,6 @@ export const getBrokersTableColumns = () => {
7576
cell: Cell.Skew,
7677
}),
7778
columnHelper.accessor('port', { header: 'Port' }),
78-
columnHelper.accessor('host', { header: 'Host' }),
79+
columnHelper.accessor('host', { header: 'Host', cell: BreakableTextCell }),
7980
];
8081
};

frontend/src/components/Connect/Details/DetailsPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import {
99
RouterParamsClusterConnectConnector,
1010
} from 'lib/paths';
1111
import Navbar from 'components/common/Navigation/Navbar.styled';
12-
import PageHeading from 'components/common/PageHeading/PageHeading';
1312
import PageLoader from 'components/common/PageLoader/PageLoader';
13+
import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading';
1414

1515
import Overview from './Overview/Overview';
1616
import Tasks from './Tasks/Tasks';
@@ -23,13 +23,13 @@ const DetailsPage: React.FC = () => {
2323

2424
return (
2525
<div>
26-
<PageHeading
26+
<ResourcePageHeading
2727
text={connectorName}
2828
backTo={clusterConnectorsPath(clusterName)}
2929
backText="Connectors"
3030
>
3131
<Actions />
32-
</PageHeading>
32+
</ResourcePageHeading>
3333
<Overview />
3434
<Navbar role="navigation">
3535
<NavLink

frontend/src/components/Connect/List/List.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { FullConnectorInfo } from 'generated-sources';
66
import { useConnectors } from 'lib/hooks/api/kafkaConnect';
77
import { ColumnDef } from '@tanstack/react-table';
88
import { useNavigate, useSearchParams } from 'react-router-dom';
9+
import BreakableTextCell from 'components/common/NewTable/BreakableTextCell';
910

1011
import ActionsCell from './ActionsCell';
1112
import TopicsCell from './TopicsCell';
@@ -23,9 +24,13 @@ const List: React.FC = () => {
2324
const columns = React.useMemo<ColumnDef<FullConnectorInfo>[]>(
2425
() => [
2526
{ header: 'Name', accessorKey: 'name' },
26-
{ header: 'Connect', accessorKey: 'connect' },
27+
{ header: 'Connect', accessorKey: 'connect', cell: BreakableTextCell },
2728
{ header: 'Type', accessorKey: 'type' },
28-
{ header: 'Plugin', accessorKey: 'connectorClass' },
29+
{
30+
header: 'Plugin',
31+
accessorKey: 'connectorClass',
32+
cell: BreakableTextCell,
33+
},
2934
{ header: 'Topics', cell: TopicsCell },
3035
{ header: 'Status', accessorKey: 'status.state', cell: TagCell },
3136
{ header: 'Running Tasks', cell: RunningTasksCell },

frontend/src/components/Connect/List/ListPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { ClusterNameRoute, clusterConnectorNewRelativePath } from 'lib/paths';
44
import ClusterContext from 'components/contexts/ClusterContext';
55
import Search from 'components/common/Search/Search';
66
import * as Metrics from 'components/common/Metrics';
7-
import PageHeading from 'components/common/PageHeading/PageHeading';
87
import Tooltip from 'components/common/Tooltip/Tooltip';
98
import { ControlPanelWrapper } from 'components/common/ControlPanel/ControlPanel.styled';
109
import PageLoader from 'components/common/PageLoader/PageLoader';
1110
import { ConnectorState, Action, ResourceType } from 'generated-sources';
1211
import { useConnectors, useConnects } from 'lib/hooks/api/kafkaConnect';
1312
import { ActionButton } from 'components/common/ActionComponent';
13+
import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading';
1414

1515
import List from './List';
1616

@@ -33,7 +33,7 @@ const ListPage: React.FC = () => {
3333

3434
return (
3535
<>
36-
<PageHeading text="Connectors">
36+
<ResourcePageHeading text="Connectors">
3737
{!isReadOnly && (
3838
<Tooltip
3939
value={
@@ -55,7 +55,7 @@ const ListPage: React.FC = () => {
5555
placement="left"
5656
/>
5757
)}
58-
</PageHeading>
58+
</ResourcePageHeading>
5959
<Metrics.Wrapper>
6060
<Metrics.Section>
6161
<Metrics.Indicator

0 commit comments

Comments
 (0)