@@ -683,11 +683,19 @@ public static Metadata fromXContent(XContentParser parser) throws IOException {
683683
684684 @ Override
685685 public Iterator <? extends ToXContent > toXContentChunked (ToXContent .Params p ) {
686- XContentContext context = XContentContext .from (p );
686+ final XContentContext context = XContentContext .from (p );
687687 final Iterator <? extends ToXContent > start = context == XContentContext .API
688688 ? ChunkedToXContentHelper .startObject ("metadata" )
689689 : Iterators .single ((builder , params ) -> builder .startObject ("meta-data" ).field ("version" , version ()));
690690
691+ final Iterator <? extends ToXContent > clusterCoordination = Iterators .single ((builder , params ) -> {
692+ builder .field ("cluster_uuid" , clusterUUID );
693+ builder .field ("cluster_uuid_committed" , clusterUUIDCommitted );
694+ builder .startObject ("cluster_coordination" );
695+ coordinationMetadata ().toXContent (builder , params );
696+ return builder .endObject ();
697+ });
698+
691699 final Iterator <? extends ToXContent > persistentSettings = context != XContentContext .API && persistentSettings ().isEmpty () == false
692700 ? Iterators .single ((builder , params ) -> {
693701 builder .startObject ("settings" );
@@ -696,89 +704,98 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params p) {
696704 })
697705 : Collections .emptyIterator ();
698706
699- // use a tree map so the order is deterministic
700- Map <String , ReservedStateMetadata > clusterReservedState = new TreeMap <>(reservedStateMetadata );
701-
702707 @ FixForMultiProject
703708 // Need to revisit whether this should be a param or something else.
704709 final boolean multiProject = p .paramAsBoolean ("multi-project" , false );
705710 if (multiProject ) {
706- return Iterators .concat (start , Iterators .single ((builder , params ) -> {
707- builder .field ("cluster_uuid" , clusterUUID );
708- builder .field ("cluster_uuid_committed" , clusterUUIDCommitted );
709- builder .startObject ("cluster_coordination" );
710- coordinationMetadata ().toXContent (builder , params );
711- return builder .endObject ();
712- }),
713- persistentSettings ,
714- ChunkedToXContentHelper .array (
715- "projects" ,
716- Iterators .flatMap (
717- projectMetadata .entrySet ().iterator (),
718- e -> Iterators .concat (
719- ChunkedToXContentHelper .startObject (),
720- Iterators .single ((builder , params ) -> builder .field ("id" , e .getKey ())),
721- e .getValue ().toXContentChunked (p ),
722- ChunkedToXContentHelper .endObject ()
723- )
724- )
725- ),
726- Iterators .flatMap (
727- customs .entrySet ().iterator (),
728- entry -> entry .getValue ().context ().contains (context )
729- ? ChunkedToXContentHelper .object (entry .getKey (), entry .getValue ().toXContentChunked (p ))
730- : Collections .emptyIterator ()
731- ),
732- ChunkedToXContentHelper .object ("reserved_state" , reservedStateMetadata ().values ().iterator ()),
733- ChunkedToXContentHelper .endObject ()
734- );
711+ return toXContentChunkedWithMultiProjectFormat (p , context , start , clusterCoordination , persistentSettings );
735712 } else {
736- if (projectMetadata .size () != 1 ) {
737- throw new MultiProjectPendingException ("There are multiple projects " + projectMetadata .keySet ());
738- }
739- // Need to rethink what to do here. This might be right, but maybe not...
740- @ FixForMultiProject
741- final ProjectMetadata project = projectMetadata .values ().iterator ().next ();
742-
743- // need to combine reserved state together into a single block so we don't get duplicate keys
744- // and not include it in the project xcontent output (through the lack of multi-project params)
745- clusterReservedState .putAll (project .reservedStateMetadata ());
746-
747- // Similarly, combine cluster and project persistent tasks and report them under a single key
748- Iterator <ToXContent > customs = Iterators .flatMap (customs ().entrySet ().iterator (), entry -> {
749- if (entry .getValue ().context ().contains (context )
750- && ClusterPersistentTasksCustomMetadata .TYPE .equals (entry .getKey ()) == false ) {
751- return ChunkedToXContentHelper .object (entry .getKey (), entry .getValue ().toXContentChunked (p ));
752- } else {
753- return Collections .emptyIterator ();
754- }
755- });
756- final var combinedTasks = PersistentTasksCustomMetadata .combine (
757- ClusterPersistentTasksCustomMetadata .get (this ),
758- PersistentTasksCustomMetadata .get (project )
759- );
760- if (combinedTasks != null ) {
761- customs = Iterators .concat (
762- customs ,
763- ChunkedToXContentHelper .object (PersistentTasksCustomMetadata .TYPE , combinedTasks .toXContentChunked (p ))
764- );
765- }
713+ return toXContentChunkedWithSingleProjectFormat (p , context , start , clusterCoordination , persistentSettings );
714+ }
715+ }
766716
767- final var iterators = Iterators .concat (start , Iterators .single ((builder , params ) -> {
768- builder .field ("cluster_uuid" , clusterUUID );
769- builder .field ("cluster_uuid_committed" , clusterUUIDCommitted );
770- builder .startObject ("cluster_coordination" );
771- coordinationMetadata ().toXContent (builder , params );
772- return builder .endObject ();
773- }),
774- persistentSettings ,
775- project .toXContentChunked (p ),
717+ private Iterator <? extends ToXContent > toXContentChunkedWithMultiProjectFormat (
718+ ToXContent .Params p ,
719+ XContentContext context ,
720+ Iterator <? extends ToXContent > start ,
721+ Iterator <? extends ToXContent > clusterCoordination ,
722+ Iterator <? extends ToXContent > persistentSettings
723+ ) {
724+ return Iterators .concat (
725+ start ,
726+ clusterCoordination ,
727+ persistentSettings ,
728+ ChunkedToXContentHelper .array (
729+ "projects" ,
730+ Iterators .flatMap (
731+ projectMetadata .entrySet ().iterator (),
732+ e -> Iterators .concat (
733+ ChunkedToXContentHelper .startObject (),
734+ Iterators .single ((builder , params ) -> builder .field ("id" , e .getKey ())),
735+ e .getValue ().toXContentChunked (p ),
736+ ChunkedToXContentHelper .endObject ()
737+ )
738+ )
739+ ),
740+ Iterators .flatMap (
741+ customs .entrySet ().iterator (),
742+ entry -> entry .getValue ().context ().contains (context )
743+ ? ChunkedToXContentHelper .object (entry .getKey (), entry .getValue ().toXContentChunked (p ))
744+ : Collections .emptyIterator ()
745+ ),
746+ ChunkedToXContentHelper .object ("reserved_state" , reservedStateMetadata ().values ().iterator ()),
747+ ChunkedToXContentHelper .endObject ()
748+ );
749+ }
750+
751+ private Iterator <? extends ToXContent > toXContentChunkedWithSingleProjectFormat (
752+ ToXContent .Params p ,
753+ XContentContext context ,
754+ Iterator <? extends ToXContent > start ,
755+ Iterator <? extends ToXContent > clusterCoordination ,
756+ Iterator <? extends ToXContent > persistentSettings
757+ ) {
758+ if (projectMetadata .size () != 1 ) {
759+ throw new MultiProjectPendingException ("There are multiple projects " + projectMetadata .keySet ());
760+ }
761+ // Need to rethink what to do here. This might be right, but maybe not...
762+ @ FixForMultiProject
763+ final ProjectMetadata project = projectMetadata .values ().iterator ().next ();
764+
765+ // need to combine reserved state together into a single block so we don't get duplicate keys
766+ // and not include it in the project xcontent output (through the lack of multi-project params)
767+ // use a tree map so the order is deterministic
768+ final Map <String , ReservedStateMetadata > clusterReservedState = new TreeMap <>(reservedStateMetadata );
769+ clusterReservedState .putAll (project .reservedStateMetadata ());
770+
771+ // Similarly, combine cluster and project persistent tasks and report them under a single key
772+ Iterator <ToXContent > customs = Iterators .flatMap (customs ().entrySet ().iterator (), entry -> {
773+ if (entry .getValue ().context ().contains (context ) && ClusterPersistentTasksCustomMetadata .TYPE .equals (entry .getKey ()) == false ) {
774+ return ChunkedToXContentHelper .object (entry .getKey (), entry .getValue ().toXContentChunked (p ));
775+ } else {
776+ return Collections .emptyIterator ();
777+ }
778+ });
779+ final var combinedTasks = PersistentTasksCustomMetadata .combine (
780+ ClusterPersistentTasksCustomMetadata .get (this ),
781+ PersistentTasksCustomMetadata .get (project )
782+ );
783+ if (combinedTasks != null ) {
784+ customs = Iterators .concat (
776785 customs ,
777- ChunkedToXContentHelper .object ("reserved_state" , clusterReservedState .values ().iterator ()),
778- ChunkedToXContentHelper .endObject ()
786+ ChunkedToXContentHelper .object (PersistentTasksCustomMetadata .TYPE , combinedTasks .toXContentChunked (p ))
779787 );
780- return iterators ;
781788 }
789+
790+ return Iterators .concat (
791+ start ,
792+ clusterCoordination ,
793+ persistentSettings ,
794+ project .toXContentChunked (p ),
795+ customs ,
796+ ChunkedToXContentHelper .object ("reserved_state" , clusterReservedState .values ().iterator ()),
797+ ChunkedToXContentHelper .endObject ()
798+ );
782799 }
783800
784801 private static final DiffableUtils .KeySerializer <ProjectId > PROJECT_ID_SERIALIZER = DiffableUtils .getWriteableKeySerializer (
0 commit comments