4646import org .apache .kafka .common .TopicCollection ;
4747import org .apache .kafka .common .TopicPartition ;
4848import org .apache .kafka .common .Uuid ;
49+ import org .apache .kafka .common .config .ConfigResource ;
4950import org .apache .kafka .common .errors .GroupIdNotFoundException ;
5051import org .apache .kafka .common .errors .GroupNotEmptyException ;
5152import org .apache .kafka .common .errors .UnknownMemberIdException ;
@@ -101,17 +102,20 @@ public class GroupService {
101102 @ Inject
102103 PermissionService permissionService ;
103104
105+ @ Inject
106+ ConfigService configService ;
107+
104108 @ Inject
105109 TopicDescribeService topicService ;
106110
107111 @ Inject
108112 ValidationProxy validationService ;
109113
110- public CompletionStage <List <Group >> listGroups (List <String > includes , ListRequestContext <Group > listSupport ) {
111- return listGroups (Collections .emptyList (), includes , listSupport );
114+ public CompletionStage <List <Group >> listGroups (List <String > fields , ListRequestContext <Group > listSupport ) {
115+ return listGroups (Collections .emptyList (), fields , listSupport );
112116 }
113117
114- public CompletionStage <List <Group >> listGroups (String topicId , List <String > includes ,
118+ public CompletionStage <List <Group >> listGroups (String topicId , List <String > fields ,
115119 ListRequestContext <Group > listSupport ) {
116120
117121 Admin adminClient = kafkaContext .admin ();
@@ -131,14 +135,14 @@ public CompletionStage<List<Group>> listGroups(String topicId, List<String> incl
131135 }, asyncExec )
132136 .thenComposeAsync (topicGroups -> {
133137 if (topicGroups .containsKey (topicId )) {
134- return listGroups (topicGroups .get (topicId ), includes , listSupport );
138+ return listGroups (topicGroups .get (topicId ), fields , listSupport );
135139 }
136140 return CompletableFuture .completedStage (Collections .emptyList ());
137141 }, asyncExec );
138142 }
139143
140144 private CompletionStage <List <Group >> listGroups (List <String > groupIds ,
141- List <String > includes , ListRequestContext <Group > listSupport ) {
145+ List <String > fields , ListRequestContext <Group > listSupport ) {
142146
143147 Admin adminClient = kafkaContext .admin ();
144148 Set <GroupType > types = extractFilter (listSupport , "filter[type]" , GroupType ::parse );
@@ -168,7 +172,7 @@ private CompletionStage<List<Group>> listGroups(List<String> groupIds,
168172 .toList (),
169173 threadContext .currentContextExecutor ())
170174 .thenComposeAsync (
171- groups -> augmentList (adminClient , groups , includes ),
175+ groups -> augmentList (adminClient , groups , fields ),
172176 threadContext .currentContextExecutor ());
173177 }
174178
@@ -506,11 +510,11 @@ public CompletionStage<Void> deleteGroup(String requestGroupId) {
506510 .toCompletionStage ();
507511 }
508512
509- private CompletionStage <List <Group >> augmentList (Admin adminClient , List <Group > list , List <String > includes ) {
513+ private CompletionStage <List <Group >> augmentList (Admin adminClient , List <Group > list , List <String > fields ) {
510514 CompletableFuture <Void > describePromise ;
511515
512- if (REQUIRE_DESCRIBE .stream ().anyMatch (includes ::contains )) {
513- describePromise = describeGroups (adminClient , list , includes )
516+ if (REQUIRE_DESCRIBE .stream ().anyMatch (fields ::contains )) {
517+ describePromise = describeGroups (adminClient , list , fields )
514518 .thenAccept (descriptions -> {
515519 Map <String , Group > groups = list .stream ().collect (Collectors .toMap (Group ::groupId , Function .identity ()));
516520 descriptions .forEach ((name , either ) -> mergeDescriptions (groups .get (name ), either ));
@@ -546,7 +550,7 @@ private void mergeDescriptions(Group group, Either<Group, Throwable> description
546550 private CompletionStage <Map <String , Either <Group , Throwable >>> describeGroups (
547551 Admin adminClient ,
548552 Collection <Group > groups ,
549- List <String > includes ) {
553+ List <String > fields ) {
550554
551555 Map <String , Either <Group , Throwable >> result = LinkedHashMap .newLinkedHashMap (groups .size ());
552556
@@ -558,7 +562,7 @@ private CompletionStage<Map<String, Either<Group, Throwable>>> describeGroups(
558562 .<Map .Entry <String , KafkaFuture <?>>>mapMulti ((group , next ) -> describeGroups (adminClient ,
559563 group .getKey (),
560564 group .getValue (),
561- includes .contains (Group .Fields .AUTHORIZED_OPERATIONS ),
565+ fields .contains (Group .Fields .AUTHORIZED_OPERATIONS ),
562566 next ))
563567 .map (entry ->
564568 entry .getValue ()
@@ -587,14 +591,10 @@ private CompletionStage<Map<String, Either<Group, Throwable>>> describeGroups(
587591
588592 return CompletableFuture .allOf (pendingDescribes )
589593 .thenCompose (nothing -> pendingTopicsIds )
590- .thenCompose (topicIds -> {
591- if (includes .contains (Group .Fields .OFFSETS )) {
592- return fetchOffsets (adminClient , availableGroups .get (), topicIds )
593- .thenApply (nothing -> result );
594- }
595-
596- return CompletableFuture .completedFuture (result );
597- });
594+ .thenCompose (topicIds -> CompletableFuture .allOf (
595+ maybeFetchOffsets (adminClient , availableGroups .get (), topicIds , fields ),
596+ maybeDescribeConfigs (adminClient , availableGroups .get (), fields )))
597+ .thenApply (nothing -> result );
598598 }
599599
600600 private CompletableFuture <Map <String , String >> fetchTopicIdMap () {
@@ -661,7 +661,15 @@ private static String groupId(Object description) {
661661 }
662662 }
663663
664- private CompletableFuture <Void > fetchOffsets (Admin adminClient , Map <String , Group > groups , Map <String , String > topicIds ) {
664+ private CompletableFuture <Void > maybeFetchOffsets (
665+ Admin adminClient ,
666+ Map <String , Group > groups , Map <String , String > topicIds ,
667+ List <String > fields ) {
668+
669+ if (!fields .contains (Group .Fields .OFFSETS )) {
670+ return CompletableFuture .completedFuture (null );
671+ }
672+
665673 Map <String , Either <Map <PartitionId , OffsetAndMetadata >, Throwable >> groupOffsets = new LinkedHashMap <>();
666674 Map <TopicPartition , Either <ListOffsetsResultInfo , Throwable >> topicOffsets = new LinkedHashMap <>();
667675
@@ -905,4 +913,29 @@ private void addOffsets(Group group,
905913 group .offsets (offsets );
906914 }
907915 }
916+
917+ CompletableFuture <Void > maybeDescribeConfigs (Admin adminClient , Map <String , Group > groups , List <String > fields ) {
918+ if (!fields .contains (Group .Fields .CONFIGS )) {
919+ return CompletableFuture .completedFuture (null );
920+ }
921+
922+ List <ConfigResource > keys = groups .values ()
923+ .stream ()
924+ .map (Group ::groupId )
925+ .filter (groupId -> {
926+ if (permissionService .permitted (ResourceTypes .Kafka .GROUP_CONFIGS , Privilege .GET , groupId )) {
927+ return true ;
928+ }
929+ var error = permissionService .forbidden (ResourceTypes .Kafka .GROUP_CONFIGS , Privilege .GET , groupId );
930+ groups .get (groupId ).addConfigs (Either .ofAlternate (error ));
931+ return false ;
932+ })
933+ .map (groupId -> new ConfigResource (ConfigResource .Type .GROUP , groupId ))
934+ .toList ();
935+
936+ return configService .describeConfigs (adminClient , keys )
937+ .thenAccept (configs ->
938+ configs .forEach ((groupId , either ) -> groups .get (groupId ).addConfigs (either )))
939+ .toCompletableFuture ();
940+ }
908941}
0 commit comments