swarm-builder: an agent option whose eval failed is left out of the reply, not read as its default
This commit is contained in:
parent
cd1b77b078
commit
5d2b0c9a54
2 changed files with 340 additions and 158 deletions
|
|
@ -40,15 +40,15 @@ pub struct AgentClosure {
|
|||
pub cached: bool,
|
||||
/// Whether the agent's evaluated config sets
|
||||
/// `services.hyperhive.agent.user.privateUsers`: the agent runs in its own
|
||||
/// user namespace. A record written before the field existed reads as
|
||||
/// false, which keeps the agent out of one.
|
||||
#[serde(default)]
|
||||
pub private_users: bool,
|
||||
/// user namespace. `None` when the builder could not read it, and for a
|
||||
/// record written before the field existed: the record says nothing, and
|
||||
/// the reader leaves the agent as its last start set it.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub private_users: Option<bool>,
|
||||
/// The agent's `services.hyperhive.agent.nixBuilds`: where its nix builds
|
||||
/// run. A record written before the field existed reads as
|
||||
/// [`NixBuilds::Host`], which is what every agent did before it.
|
||||
#[serde(default)]
|
||||
pub nix_builds: NixBuilds,
|
||||
/// run. `None` as for `private_users`.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub nix_builds: Option<NixBuilds>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -69,8 +69,8 @@ mod tests {
|
|||
system: "x86_64-linux".to_owned(),
|
||||
built_unix: 7,
|
||||
cached: true,
|
||||
private_users: true,
|
||||
nix_builds: NixBuilds::Disabled,
|
||||
private_users: Some(true),
|
||||
nix_builds: Some(NixBuilds::Disabled),
|
||||
};
|
||||
let wire = serde_json::json!({
|
||||
"meta_rev": "abc",
|
||||
|
|
@ -89,7 +89,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn a_record_without_the_fields_reads_as_not_cached_not_namespaced_and_host_builds() {
|
||||
fn a_record_without_the_fields_reads_as_not_cached_and_says_nothing_of_the_options() {
|
||||
let old = serde_json::json!({
|
||||
"meta_rev": "abc",
|
||||
"store_path": "/nix/store/x",
|
||||
|
|
@ -98,7 +98,41 @@ mod tests {
|
|||
});
|
||||
let record = serde_json::from_value::<AgentClosure>(old).expect("decodes");
|
||||
assert!(!record.cached);
|
||||
assert!(!record.private_users);
|
||||
assert_eq!(record.nix_builds, NixBuilds::Host);
|
||||
assert_eq!(record.private_users, None);
|
||||
assert_eq!(record.nix_builds, None);
|
||||
}
|
||||
|
||||
/// An option the builder could not read is left out of the record, not
|
||||
/// written as `null`: a reader that predates the option still decodes it.
|
||||
#[test]
|
||||
fn an_unread_option_is_left_out_of_the_record() {
|
||||
// The shape a reader before the option had: a bool that defaults to false.
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Before {
|
||||
#[serde(default)]
|
||||
private_users: bool,
|
||||
}
|
||||
let record = AgentClosure {
|
||||
meta_rev: "abc".to_owned(),
|
||||
store_path: "/nix/store/x".to_owned(),
|
||||
system: "x86_64-linux".to_owned(),
|
||||
built_unix: 7,
|
||||
cached: true,
|
||||
private_users: None,
|
||||
nix_builds: Some(NixBuilds::Host),
|
||||
};
|
||||
let wire = serde_json::to_value(&record).expect("encodes");
|
||||
let fields = wire.as_object().expect("an object");
|
||||
assert!(!fields.contains_key("private_users"), "{wire}");
|
||||
assert_eq!(fields["nix_builds"], "host");
|
||||
assert!(
|
||||
!serde_json::from_value::<Before>(wire.clone())
|
||||
.expect("decodes")
|
||||
.private_users
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_value::<AgentClosure>(wire).expect("decodes"),
|
||||
record
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,15 +151,15 @@ pub enum FromMetaReply {
|
|||
#[serde(default)]
|
||||
cached: bool,
|
||||
/// Whether the agent's evaluated config sets
|
||||
/// `services.hyperhive.agent.user.privateUsers`. A builder that
|
||||
/// predates the field answers without it, which reads as false.
|
||||
#[serde(default)]
|
||||
private_users: bool,
|
||||
/// The agent's `services.hyperhive.agent.nixBuilds`. A builder that
|
||||
/// predates the field answers without it, which reads as
|
||||
/// [`NixBuilds::Host`].
|
||||
#[serde(default)]
|
||||
nix_builds: NixBuilds,
|
||||
/// `services.hyperhive.agent.user.privateUsers`. Absent (`None`) when
|
||||
/// the builder could not read it: its eval failed or timed out. A
|
||||
/// builder that predates the field answers without it too.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
private_users: Option<bool>,
|
||||
/// The agent's `services.hyperhive.agent.nixBuilds`. Absent (`None`)
|
||||
/// when the builder could not read it, as for `private_users`.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
nix_builds: Option<NixBuilds>,
|
||||
},
|
||||
/// The build did not succeed: the last lines `nix` printed, or why it
|
||||
/// stopped (it timed out, or could not start). The controller holds the
|
||||
|
|
@ -273,8 +273,8 @@ mod tests {
|
|||
out_path: "/nix/store/x".to_owned(),
|
||||
system: "x86_64-linux".to_owned(),
|
||||
cached: true,
|
||||
private_users: true,
|
||||
nix_builds: NixBuilds::Disabled,
|
||||
private_users: Some(true),
|
||||
nix_builds: Some(NixBuilds::Disabled),
|
||||
},
|
||||
json!({
|
||||
"state": "built",
|
||||
|
|
@ -307,8 +307,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn a_built_reply_from_a_builder_without_the_fields_reads_as_not_cached_not_namespaced_and_host_builds()
|
||||
{
|
||||
fn a_built_reply_from_a_builder_without_the_fields_reads_as_not_cached_and_unknown() {
|
||||
let old = json!({"state": "built", "out_path": "/nix/store/x", "system": "s"});
|
||||
assert_eq!(
|
||||
serde_json::from_value::<FromMetaReply>(old).expect("decodes"),
|
||||
|
|
@ -316,12 +315,44 @@ mod tests {
|
|||
out_path: "/nix/store/x".to_owned(),
|
||||
system: "s".to_owned(),
|
||||
cached: false,
|
||||
private_users: false,
|
||||
nix_builds: NixBuilds::Host,
|
||||
private_users: None,
|
||||
nix_builds: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// A value the builder could not read is left out of the reply, not sent as
|
||||
/// `null`: a controller that predates the option still decodes it.
|
||||
#[test]
|
||||
fn an_unread_option_is_left_out_of_the_built_reply() {
|
||||
// The shape a reader before the option had: a bool that defaults to false.
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Before {
|
||||
#[serde(default)]
|
||||
private_users: bool,
|
||||
}
|
||||
let reply = FromMetaReply::Built {
|
||||
out_path: "/nix/store/x".to_owned(),
|
||||
system: "s".to_owned(),
|
||||
cached: false,
|
||||
private_users: None,
|
||||
nix_builds: Some(NixBuilds::Host),
|
||||
};
|
||||
let wire = serde_json::to_value(&reply).expect("encodes");
|
||||
let fields = wire.as_object().expect("an object");
|
||||
assert!(!fields.contains_key("private_users"), "{wire}");
|
||||
assert_eq!(fields["nix_builds"], "host");
|
||||
assert!(
|
||||
!serde_json::from_value::<Before>(wire.clone())
|
||||
.expect("decodes")
|
||||
.private_users
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_value::<FromMetaReply>(wire).expect("decodes"),
|
||||
reply
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_subjects_are_pinned() {
|
||||
assert_eq!(SUBJECT, "$SWARM.builder.build");
|
||||
|
|
|
|||
Loading…
Reference in a new issue