swarm-controller: refuse a percentage with a leading zero in its whole part
systemd ignores `08%` and `085480%` for CPUQuota= and `08%` for MemoryMax=
("Invalid ... ignoring"), which leaves the agent uncapped. `hundredths` now
refuses a whole part that starts with `0` unless it is exactly `0`, for both
fields. `0.5%` and `0.01%` stay accepted.
This commit is contained in:
parent
e14955f20a
commit
05c9075825
2 changed files with 15 additions and 4 deletions
|
|
@ -493,7 +493,8 @@ caps. swarm-controller alone writes it:
|
||||||
|
|
||||||
`PUT` refuses an agent no hive's wanted state declares, unknown fields, and
|
`PUT` refuses an agent no hive's wanted state declares, unknown fields, and
|
||||||
any value systemd would ignore, which would leave the agent uncapped. A
|
any value systemd would ignore, which would leave the agent uncapped. A
|
||||||
percentage has at most two decimals and is above zero, up to `100%` for
|
percentage has at most two decimals, no leading zero in its whole part (it
|
||||||
|
refuses `08%`), and is above zero, up to `100%` for
|
||||||
`memory_max` and `21474836.47%` for `cpu_quota`. A size is digits with an
|
`memory_max` and `21474836.47%` for `cpu_quota`. A size is digits with an
|
||||||
optional fraction and an optional `B`, `K`, `M`, `G` or `T` (upper case), at
|
optional fraction and an optional `B`, `K`, `M`, `G` or `T` (upper case), at
|
||||||
least one byte and below 2^64 - 1 bytes. The controller stores each value as
|
least one byte and below 2^64 - 1 bytes. The controller stores each value as
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,9 @@ fn memory_max(value: &str) -> Result<String, String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `value` as systemd reads a percentage, in hundredths of a percent: digits,
|
/// `value` as systemd reads a percentage, in hundredths of a percent: digits,
|
||||||
/// optionally `.` and one or two digits, then `%`. `None` for anything else.
|
/// optionally `.` and one or two digits, then `%`. `None` for anything else,
|
||||||
|
/// and for a whole part with a leading zero other than `0` itself: systemd
|
||||||
|
/// ignores `08%` and may read `010%` as octal.
|
||||||
fn hundredths(value: &str) -> Option<u64> {
|
fn hundredths(value: &str) -> Option<u64> {
|
||||||
let number = value.strip_suffix('%')?;
|
let number = value.strip_suffix('%')?;
|
||||||
let (int, frac) = match number.split_once('.') {
|
let (int, frac) = match number.split_once('.') {
|
||||||
|
|
@ -113,7 +115,7 @@ fn hundredths(value: &str) -> Option<u64> {
|
||||||
Some(_) => return None,
|
Some(_) => return None,
|
||||||
None => (number, ""),
|
None => (number, ""),
|
||||||
};
|
};
|
||||||
if !digits(int) {
|
if !digits(int) || (int.len() > 1 && int.starts_with('0')) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let frac = match frac.len() {
|
let frac = match frac.len() {
|
||||||
|
|
@ -324,7 +326,6 @@ mod tests {
|
||||||
"0.01%",
|
"0.01%",
|
||||||
"1500%",
|
"1500%",
|
||||||
"400.12%",
|
"400.12%",
|
||||||
"05%",
|
|
||||||
"21474836.47%",
|
"21474836.47%",
|
||||||
] {
|
] {
|
||||||
assert_eq!(cpu_quota(ok).as_deref(), Ok(ok));
|
assert_eq!(cpu_quota(ok).as_deref(), Ok(ok));
|
||||||
|
|
@ -345,6 +346,11 @@ mod tests {
|
||||||
"0.001%",
|
"0.001%",
|
||||||
"99999999999999999999%",
|
"99999999999999999999%",
|
||||||
"21474836.48%",
|
"21474836.48%",
|
||||||
|
"05%",
|
||||||
|
"08%",
|
||||||
|
"085480%",
|
||||||
|
"010%",
|
||||||
|
"00.5%",
|
||||||
"1.%",
|
"1.%",
|
||||||
".5%",
|
".5%",
|
||||||
"400%\nExecStartPre=/bin/sh -c id #%",
|
"400%\nExecStartPre=/bin/sh -c id #%",
|
||||||
|
|
@ -391,6 +397,10 @@ mod tests {
|
||||||
"150%",
|
"150%",
|
||||||
"100.01%",
|
"100.01%",
|
||||||
"12.345%",
|
"12.345%",
|
||||||
|
"08%",
|
||||||
|
"085480%",
|
||||||
|
"010%",
|
||||||
|
"00.5%",
|
||||||
"8X",
|
"8X",
|
||||||
"G",
|
"G",
|
||||||
"8 G",
|
"8 G",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue