1
2 /**
3 * Copyright (C) 2018-present MongoDB, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the Server Side Public License, version 1,
7 * as published by MongoDB, Inc.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * Server Side Public License for more details.
13 *
14 * You should have received a copy of the Server Side Public License
15 * along with this program. If not, see
16 * <http://www.mongodb.com/licensing/server-side-public-license>.
17 *
18 * As a special exception, the copyright holders give permission to link the
19 * code of portions of this program with the OpenSSL library under certain
20 * conditions as described in each individual source file and distribute
21 * linked combinations including the program with the OpenSSL library. You
22 * must comply with the Server Side Public License in all respects for
23 * all of the code used other than as permitted herein. If you modify file(s)
24 * with this exception, you may extend this exception to your version of the
25 * file(s), but you are not obligated to do so. If you do not wish to do so,
26 * delete this exception statement from your version. If you delete this
27 * exception statement from all source files in the program, then also delete
28 * it in the license file.
29 */
30
31 #include "mongo/platform/basic.h"
32
33 #include "mongo/db/s/type_shard_identity.h"
34
35 #include "mongo/bson/bsonobjbuilder.h"
36 #include "mongo/bson/util/bson_extract.h"
37 #include "mongo/util/assert_util.h"
38
39 namespace mongo {
40
41 const std::string ShardIdentityType::IdName("shardIdentity");
42
43 const BSONField<std::string> ShardIdentityType::configsvrConnString("configsvrConnectionString");
44 const BSONField<std::string> ShardIdentityType::shardName("shardName");
45 const BSONField<OID> ShardIdentityType::clusterId("clusterId");
46
fromBSON(const BSONObj & source)47 StatusWith<ShardIdentityType> ShardIdentityType::fromBSON(const BSONObj& source) {
48 if (!source.hasField("_id")) {
49 return {ErrorCodes::NoSuchKey,
50 str::stream() << "missing _id field for shardIdentity document"};
51 }
52
53 ShardIdentityType shardIdentity;
54
55 {
56 std::string docId;
57 Status status = bsonExtractStringField(source, "_id", &docId);
58 if (!status.isOK()) {
59 return status;
60 }
61
62 if (docId != IdName) {
63 return {ErrorCodes::FailedToParse,
64 str::stream() << "got _id: " << docId << " instead of " << IdName};
65 }
66 }
67
68 {
69 std::string connString;
70 Status status = bsonExtractStringField(source, configsvrConnString(), &connString);
71 if (!status.isOK()) {
72 return status;
73 }
74
75 try {
76 // Note: ConnectionString::parse can uassert from HostAndPort constructor.
77 auto parsedConfigConnStrStatus = ConnectionString::parse(connString);
78 if (!parsedConfigConnStrStatus.isOK()) {
79 return parsedConfigConnStrStatus.getStatus();
80 }
81
82 auto configSvrConnStr = parsedConfigConnStrStatus.getValue();
83 if (configSvrConnStr.type() != ConnectionString::SET) {
84 return Status(ErrorCodes::UnsupportedFormat,
85 str::stream()
86 << "config server connection string can only be replica sets: "
87 << configSvrConnStr.toString());
88 }
89
90 shardIdentity.setConfigsvrConnString(std::move(configSvrConnStr));
91 } catch (const AssertionException& parseException) {
92 return parseException.toStatus();
93 }
94 }
95
96 {
97 std::string name;
98 Status status = bsonExtractStringField(source, shardName(), &name);
99 if (!status.isOK()) {
100 return status;
101 }
102
103 shardIdentity.setShardName(name);
104 }
105
106 {
107 OID oid;
108 Status status = bsonExtractOIDField(source, clusterId(), &oid);
109 if (!status.isOK()) {
110 return status;
111 }
112
113 shardIdentity.setClusterId(oid);
114 }
115
116 return shardIdentity;
117 }
118
validate() const119 Status ShardIdentityType::validate() const {
120 if (!_configsvrConnString) {
121 return {ErrorCodes::NoSuchKey,
122 str::stream() << "missing " << configsvrConnString() << " field"};
123 }
124
125 if (_configsvrConnString->type() != ConnectionString::SET) {
126 return {ErrorCodes::UnsupportedFormat,
127 str::stream() << "config connection string can only be replica sets, got "
128 << ConnectionString::typeToString(_configsvrConnString->type())};
129 }
130
131 if (!_shardName || _shardName->empty()) {
132 return {ErrorCodes::NoSuchKey, str::stream() << "missing " << shardName() << " field"};
133 }
134
135 if (!_clusterId || !_clusterId->isSet()) {
136 return {ErrorCodes::NoSuchKey, str::stream() << "missing " << clusterId() << " field"};
137 }
138
139 return Status::OK();
140 }
141
toBSON() const142 BSONObj ShardIdentityType::toBSON() const {
143 BSONObjBuilder builder;
144
145 builder.append("_id", IdName);
146
147 if (_configsvrConnString) {
148 builder << configsvrConnString(_configsvrConnString->toString());
149 }
150
151 if (_shardName) {
152 builder << shardName(_shardName.get());
153 }
154
155 if (_clusterId) {
156 builder << clusterId(_clusterId.get());
157 }
158
159 return builder.obj();
160 }
161
toString() const162 std::string ShardIdentityType::toString() const {
163 return toBSON().toString();
164 }
165
isConfigsvrConnStringSet() const166 bool ShardIdentityType::isConfigsvrConnStringSet() const {
167 return _configsvrConnString.is_initialized();
168 }
169
getConfigsvrConnString() const170 const ConnectionString& ShardIdentityType::getConfigsvrConnString() const {
171 invariant(_configsvrConnString);
172 return _configsvrConnString.get();
173 }
174
setConfigsvrConnString(ConnectionString connString)175 void ShardIdentityType::setConfigsvrConnString(ConnectionString connString) {
176 _configsvrConnString = std::move(connString);
177 }
178
isShardNameSet() const179 bool ShardIdentityType::isShardNameSet() const {
180 return _shardName.is_initialized();
181 }
182
getShardName() const183 const std::string& ShardIdentityType::getShardName() const {
184 invariant(_shardName);
185 return _shardName.get();
186 }
187
setShardName(std::string shardName)188 void ShardIdentityType::setShardName(std::string shardName) {
189 _shardName = std::move(shardName);
190 }
191
isClusterIdSet() const192 bool ShardIdentityType::isClusterIdSet() const {
193 return _clusterId.is_initialized();
194 }
195
getClusterId() const196 const OID& ShardIdentityType::getClusterId() const {
197 invariant(_clusterId);
198 return _clusterId.get();
199 }
200
setClusterId(OID clusterId)201 void ShardIdentityType::setClusterId(OID clusterId) {
202 _clusterId = std::move(clusterId);
203 }
204
createConfigServerUpdateObject(const std::string & newConnString)205 BSONObj ShardIdentityType::createConfigServerUpdateObject(const std::string& newConnString) {
206 BSONObjBuilder builder;
207 BSONObjBuilder setConfigBuilder(builder.subobjStart("$set"));
208 setConfigBuilder.append(configsvrConnString(), newConnString);
209 setConfigBuilder.doneFast();
210 return builder.obj();
211 }
212
213 } // namespace mongo
214