| 221 | } // namespace validation { |
| 222 | |
| 223 | Option<Error> validate(const QuotaConfig& config) |
| 224 | { |
| 225 | if (!config.has_role()) { |
| 226 | return Error("'QuotaConfig.role' must be set"); |
| 227 | } |
| 228 | |
| 229 | // Check the provided role is valid. |
| 230 | Option<Error> error = roles::validate(config.role()); |
| 231 | if (error.isSome()) { |
| 232 | return Error("Invalid 'QuotaConfig.role': " + error->message); |
| 233 | } |
| 234 | |
| 235 | // Before we validate the scalars, we need to check for |
| 236 | // our maximum supported quota values. Otherwise, they |
| 237 | // will surface as a generic overflow error in the scalar |
| 238 | // validation below. |
| 239 | // |
| 240 | // The underlying fixed precision logic used for |
| 241 | // Value::Scalar overflows between: |
| 242 | // |
| 243 | // 9,223,372,036,854,774 and (ditto) + 1.0 |
| 244 | // |
| 245 | // double d = 9223372036854774; |
| 246 | // d += 1.0; |
| 247 | // Value::scalar s, zero; |
| 248 | // s.set_value(d); |
| 249 | // s < zero == true; // overflow! |
| 250 | // |
| 251 | // This works out to ~9 zettabytes (given we use megabytes |
| 252 | // as the base unit), we set a limit of 1 exabyte, and we |
| 253 | // can increase this later if needed. |
| 254 | // |
| 255 | // We also impose a limit on cpu, ports and other types of |
| 256 | // 1 trillion. |
| 257 | |
| 258 | const int64_t exabyteInMegabytes = 1024ll * 1024ll * 1024ll * 1024ll; |
| 259 | const int64_t otherLimit = 1000ll * 1000ll * 1000ll * 1000ll; |
| 260 | |
| 261 | auto validateTooLarge = [&]( |
| 262 | const Map<string, Value::Scalar>& m) -> Option<Error> { |
| 263 | foreach (auto&& pair, m) { |
| 264 | if (pair.first == "mem" || pair.first == "disk") { |
| 265 | if (pair.second.value() > exabyteInMegabytes) { |
| 266 | return Error( |
| 267 | "{'" + pair.first + "': " + stringify(pair.second) + "}" |
| 268 | " is invalid: values greater than 1 exabyte" |
| 269 | " (" + stringify(exabyteInMegabytes) + ") are not supported"); |
| 270 | } |
| 271 | } else if (pair.second.value() > otherLimit) { |
| 272 | return Error( |
| 273 | "{'" + pair.first + "': " + stringify(pair.second) + "}" |
| 274 | " is invalid: values greater than 1 trillion" |
| 275 | " (" + stringify(otherLimit) + ") are not supported"); |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | return None(); |
| 280 | }; |
no test coverage detected