@@ -2,6 +2,7 @@ package topo
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"strings"
6
7
7
8
"go.mongodb.org/mongo-driver/bson"
@@ -120,6 +121,7 @@ func ClusterMembers(ctx context.Context, m *mongo.Client) ([]Shard, error) {
120
121
return nil , errors .Wrap (err , "define cluster state" )
121
122
}
122
123
124
+ // sharded cluster topo
123
125
var shards []Shard
124
126
if inf .IsMongos () || inf .IsSharded () {
125
127
members , err := getShardMapImpl (ctx , m )
@@ -135,10 +137,15 @@ func ClusterMembers(ctx context.Context, m *mongo.Client) ([]Shard, error) {
135
137
return shards , nil
136
138
}
137
139
140
+ // RS topo
141
+ hosts , err := GetReplsetHosts (ctx , m )
142
+ if err != nil {
143
+ return nil , errors .Wrap (err , "get all hosts for RS" )
144
+ }
138
145
shards = []Shard {{
139
146
ID : inf .SetName ,
140
147
RS : inf .SetName ,
141
- Host : inf . SetName + "/" + strings .Join (inf . Hosts , "," ),
148
+ Host : fmt . Sprintf ( "%s/%s" , inf . SetName , strings .Join (hosts , "," ) ),
142
149
}}
143
150
return shards , nil
144
151
}
@@ -153,18 +160,44 @@ func getShardMapImpl(ctx context.Context, m *mongo.Client) (map[ReplsetName]Shar
153
160
// if shard name is not set, mongodb will provide unique name for it
154
161
// (e.g. the replset name of the shard)
155
162
// for configsvr, key name is "config"
156
- var shardMap struct { Map map [string ]string }
163
+ // hosts field is used to discover hidden members, which are not present in map field
164
+ var shardMap struct {
165
+ Map map [string ]string
166
+ Hosts map [string ]string
167
+ }
157
168
if err := res .Decode (& shardMap ); err != nil {
158
169
return nil , errors .Wrap (err , "decode" )
159
170
}
160
171
172
+ // Example of the hosts field from command output:
173
+ // hosts: {
174
+ // 'rs103:27017': 'rs1',
175
+ // 'rs101:27017': 'rs1',
176
+ // 'cfg02:27017': 'config',
177
+ // ...
178
+ // }
179
+ // hostsByShard will contain even hidden RS members
180
+ hostsByShard := map [string ][]string {}
181
+ for host , shardID := range shardMap .Hosts {
182
+ hostsByShard [shardID ] = append (hostsByShard [shardID ], host )
183
+ }
184
+
185
+ // for PSMDB 6 and below, config srv is not reported within hosts field
186
+ if len (hostsByShard ["config" ]) == 0 {
187
+ cfgHostgs , err := GetReplsetHosts (ctx , m )
188
+ if err != nil {
189
+ return nil , errors .Wrap (err , "get all hosts for config RS" )
190
+ }
191
+ hostsByShard ["config" ] = cfgHostgs
192
+ }
193
+
161
194
shards := make (map [string ]Shard , len (shardMap .Map ))
162
195
for id , host := range shardMap .Map {
163
196
rs , _ , _ := strings .Cut (host , "/" )
164
197
shards [rs ] = Shard {
165
198
ID : id ,
166
199
RS : rs ,
167
- Host : host ,
200
+ Host : fmt . Sprintf ( "%s/%s" , rs , strings . Join ( hostsByShard [ id ], "," )) ,
168
201
}
169
202
}
170
203
0 commit comments