git.delta.rocks / jrsonnet / refs/commits / 89d35672dcfd

difftreelog

refactor perform build using nix repl

Yaroslav Bolyukin2023-12-24parent: #e85b4da.patch.diff
in: trunk

8 files changed

modifiedcmds/fleet/src/better_nix_eval.rsdiffbeforeafterboth
1use std::collections::HashMap;
1use std::ffi::{OsStr, OsString};2use std::ffi::{OsStr, OsString};
2use std::fmt::Display;3use std::fmt::{self, Display};
4use std::path::PathBuf;
3use std::process::Stdio;5use std::process::Stdio;
4use std::sync::{Arc, OnceLock};6use std::sync::{Arc, OnceLock};
57
8use itertools::Itertools;10use itertools::Itertools;
9use r2d2::{Pool, PooledConnection};11use r2d2::{Pool, PooledConnection};
10use serde::de::DeserializeOwned;12use serde::de::DeserializeOwned;
11use serde::Deserialize;13use serde::{Deserialize, Serialize};
12use tokio::io::AsyncWriteExt;14use tokio::io::AsyncWriteExt;
13use tokio::process::{ChildStderr, ChildStdin, ChildStdout, Command};15use tokio::process::{ChildStderr, ChildStdin, ChildStdout, Command};
14use tokio::select;16use tokio::select;
150 }158 }
151}159}
160
161struct WarnHandler;
162impl Handler for WarnHandler {
163 fn handle_line(&mut self, e: &str) {
164 warn!(target: "nix", "{e}")
165 }
166}
152167
153impl NixSessionInner {168impl NixSessionInner {
154 async fn new(flake: &OsStr, extra_args: impl IntoIterator<Item = &OsStr>) -> Result<Self> {169 async fn new(flake: &OsStr, extra_args: impl IntoIterator<Item = &OsStr>) -> Result<Self> {
174 stdin.flush().await?;189 stdin.flush().await?;
175 let nix_handler = NixHandler::default();190 let nix_handler = NixHandler::default();
176 let mut full_delimiter = None;191 let mut full_delimiter = None;
192 let mut errors = vec![];
177 while let Some(line) = out.next().await {193 while let Some(line) = out.next().await {
178 let line = match line {194 let line = match line {
179 OutputLine::Out(o) => o,195 OutputLine::Out(o) => o,
180 OutputLine::Err(_e) => {196 OutputLine::Err(_e) => {
181 // Handle startup errors, but skip repl hello?197 // Handle startup errors, but skip repl hello?
182 //nix_handler.handle_line(&e);198 errors.push(_e);
183 continue;199 continue;
184 }200 }
185 };201 };
190 }206 }
191 }207 }
192 let Some(full_delimiter) = full_delimiter else {208 let Some(full_delimiter) = full_delimiter else {
209 for e in errors {
210 error!("{e}");
211 }
193 bail!("failed to discover delimiter");212 bail!("failed to discover delimiter");
194 };213 };
195 let mut res = Self {214 let mut res = Self {
342#[derive(Clone)]361#[derive(Clone)]
343pub struct NixSession(Arc<tokio::sync::Mutex<PooledConnection<NixSessionPoolInner>>>);362pub struct NixSession(Arc<tokio::sync::Mutex<PooledConnection<NixSessionPoolInner>>>);
363
364#[macro_export]
365macro_rules! nix_path {
366 (@o($o:ident) $var:ident $($tt:tt)*) => {{
367 $o.push(Index::var(stringify!($var)));
368 nix_path!(@o($o) $($tt)*);
369 }};
370 (@o($o:ident) . $var:ident $($tt:tt)*) => {{
371 $o.push(Index::attr(stringify!($var)));
372 nix_path!(@o($o) $($tt)*);
373 }};
374 (@o($o:ident) . $var:literal $($tt:tt)*) => {{
375 $o.push(Index::attr($var));
376 nix_path!(@o($o) $($tt)*);
377 }};
378 (@o($o:ident) . { $var:expr } $($tt:tt)*) => {{
379 $o.push(Index::attr($var));
380 nix_path!(@o($o) $($tt)*);
381 }};
382 (@o($o:ident) [ $var:literal ] $($tt:tt)*) => {{
383 $o.push(Index::idx($var));
384 nix_path!(@o($o) $($tt)*);
385 }};
386 (@o($o:ident) ($e:expr) $($tt:tt)*) => {
387 $o.push(Index::apply($e));
388 nix_path!(@o($o) $($tt)*);
389 };
390 (@o($o:ident)) => {};
391 ($($tt:tt)+) => {{
392 use $crate::{nix_path, better_nix_eval::Index};
393 let mut out = vec![];
394 nix_path!(@o(out) $($tt)*);
395 out
396 }}
397}
344398
345#[derive(Clone)]399#[derive(Clone)]
346enum Index {400pub enum Index {
401 Var(String),
347 String(String),402 String(String),
348 // Idx(u32),403 Apply(String),
404 Idx(u32),
349}405}
406impl Index {
407 pub fn var(v: impl AsRef<str>) -> Self {
408 let v = v.as_ref();
409 assert!(
410 !(v.contains('.') | v.contains(' ')),
411 "bad variable name: {v}"
412 );
413 Self::Var(v.to_owned())
414 }
415 pub fn attr(v: impl AsRef<str>) -> Self {
416 Self::String(v.as_ref().to_owned())
417 }
418 pub fn idx(v: u32) -> Self {
419 Self::Idx(v)
420 }
421 pub fn apply(v: impl Serialize) -> Self {
422 let serialized = nixlike::serialize(v).expect("invalid value for apply");
423 Self::Apply(serialized)
424 }
425}
350impl Display for Index {426impl Display for Index {
351 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {427 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352 match self {428 match self {
429 Index::Var(v) => {
430 write!(f, "{v}")
431 }
353 Index::String(k) => {432 Index::String(k) => {
354 let v = nixlike::format_identifier(k.as_str());433 let v = nixlike::format_identifier(k.as_str());
355 write!(f, ".{v}")434 write!(f, ".{v}")
356 }435 }
436 Index::Apply(o) => {
437 let v = nixlike::serialize(o).map_err(|_| fmt::Error)?;
438 write!(f, "<apply>({v})")
439 }
440 Index::Idx(i) => {
441 write!(f, "[{i}]")
442 }
357 }443 }
358 }444 }
359}445}
446impl fmt::Debug for Index {
447 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448 write!(f, "{self}")
449 }
450}
360struct PathDisplay<'i>(&'i [Index]);451struct PathDisplay<'i>(&'i [Index]);
361impl Display for PathDisplay<'_> {452impl Display for PathDisplay<'_> {
362 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {453 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
381 }472 }
382 }473 }
383 pub async fn field(session: NixSession, field: &str) -> Result<Self> {474 pub async fn field(session: NixSession, field: &str) -> Result<Self> {
384 Self::root(session).get_field_deep([field]).await475 Self::root(session)
476 .select([Index::var(field)])
477 .await
385 }478 }
386 pub async fn get_json_deep<'a, V: DeserializeOwned>(479 pub async fn get_json_deep<'a, V: DeserializeOwned>(
387 &self,480 &self,
388 name: impl IntoIterator<Item = &'a str>,481 name: impl IntoIterator<Item = Index>,
389 ) -> Result<V> {482 ) -> Result<V> {
390 let field = self.get_field_deep(name).await?;483 let field = self.select(name).await?;
391 field.as_json().await484 field.as_json().await
392 }485 }
393 pub async fn get_field(&self, name: &str) -> Result<Self> {
394 self.get_field_deep([name]).await
395 }
396 pub async fn get_field_deep<'a>(486 pub async fn select<'a>(&self, name: impl IntoIterator<Item = Index>) -> Result<Self> {
397 &self,
398 name: impl IntoIterator<Item = &'a str>,
399 ) -> Result<Self> {
400 let mut iter = name.into_iter();487 let mut name = name.into_iter();
401488
402 let mut full_path = self.full_path.clone();489 let mut full_path = self.full_path.clone();
403 let mut query = if let Some(id) = self.value {490 let mut query = if let Some(id) = self.value {
404 format!("sess_field_{id}")491 format!("sess_field_{id}")
405 } else {492 } else {
406 let first = iter.next().expect("name not empty");493 let first = name.next();
407 ensure!(494 if let Some(Index::Var(i)) = first {
408 !(first.contains('.') | first.contains(' ')),
409 "bad name for root query: {first}"
410 );
411 full_path.push(Index::String(first.to_string()));495 full_path.push(Index::Var(i.clone()));
412 first.to_string()496 i.clone()
497 } else {
498 panic!("first path item should be variable, got {first:?}")
499 }
413 };500 };
414 for v in iter {501 for v in name {
415 full_path.push(Index::String(v.to_string()));502 full_path.push(v.clone());
416 // Escape503 match v {
504 Index::Var(_) => panic!("var item may only be first"),
505 Index::String(s) => {
417 let escaped = nixlike::serialize(v)?;506 let escaped = nixlike::serialize(s)?;
418 let escaped = escaped.trim();507 query.push('.');
508 query.push_str(escaped.trim());
509 }
510 Index::Apply(a) => {
419 query.push('.');511 query.push(' ');
420 query.push_str(escaped);512 query.push_str(&a);
513 }
514 Index::Idx(idx) => {
515 query = format!("builtins.elemAt ({query}) {idx}");
516 }
517 }
421 }518 }
422519
423 let vid = self520 let vid = self
454 .await551 .await
455 .with_context(|| format!("full path: {}", PathDisplay(&self.full_path)))552 .with_context(|| format!("full path: {}", PathDisplay(&self.full_path)))
456 }553 }
554 pub async fn build(&self) -> Result<HashMap<String, PathBuf>> {
555 let id = self.value.expect("can't use build on not-value");
556 let vid = self
557 .session
558 .0
559 .lock()
560 .await
561 .execute_expression_raw(&format!(":b sess_field_{id}"), &mut NixHandler::default())
562 .await?;
563 ensure!(!vid.is_empty(), "build failed");
564 let Some(vid) = vid.strip_prefix("This derivation produced the following outputs:\n")
565 else {
566 panic!("unexpected build output: {vid:?}");
567 };
568 let outputs = vid
569 .split('\n')
570 .filter(|v| !v.is_empty())
571 .map(|v| v.split_once(" -> ").expect("unexpected build output"))
572 .map(|(a, b)| (a.trim_start().to_owned(), PathBuf::from(b)))
573 .collect();
574 Ok(outputs)
575 }
457}576}
458impl Drop for Field {577impl Drop for Field {
459 fn drop(&mut self) {578 fn drop(&mut self) {
modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
1use std::os::unix::fs::symlink;
1use std::path::PathBuf;2use std::path::PathBuf;
2use std::{env::current_dir, time::Duration};3use std::{env::current_dir, time::Duration};
34
4use crate::command::MyCommand;5use crate::command::MyCommand;
5use crate::host::Config;6use crate::host::Config;
7use crate::nix_path;
6use anyhow::{anyhow, Result};8use anyhow::{anyhow, Result};
7use clap::Parser;9use clap::Parser;
8use itertools::Itertools;10use itertools::Itertools;
1113
12#[derive(Parser, Clone)]14#[derive(Parser, Clone)]
13pub struct BuildSystems {15pub struct BuildSystems {
14 /// Do not continue on error
15 #[clap(long)]
16 fail_fast: bool,
17 /// Disable automatic rollback16 /// Disable automatic rollback
18 #[clap(long)]17 #[clap(long)]
19 disable_rollback: bool,18 disable_rollback: bool,
20 /// Run builds as sudo
21 #[clap(long)]
22 privileged_build: bool,
23 #[clap(subcommand)]19 #[clap(subcommand)]
24 subcommand: Subcommand,20 subcommand: Subcommand,
25}21}
294 async fn build_task(self, config: Config, host: String) -> Result<()> {290 async fn build_task(self, config: Config, host: String) -> Result<()> {
295 info!("building");291 info!("building");
296 let action = Action::from(self.subcommand.clone());292 let action = Action::from(self.subcommand.clone());
297 let built = {
298 let dir = tempfile::tempdir()?;
299 dir.path().to_owned()
300 };
301
302 let mut nix_build = MyCommand::new("nix");293 let drv = config
303 nix_build
304 .args([
305 "build",
306 "--impure",
307 "--json",
308 // "--show-trace",
309 "--no-link",
310 ])
311 .comparg("--out-link", &built)294 .fleet_field
312 .arg(295 .select(nix_path!(.buildSystems.{action.build_attr()}.{&host}))
313 config.configuration_attr_name(&format!(
314 "buildSystems.{}.{host}",
315 action.build_attr()
316 )),
317 )
318 .args(&config.nix_args);296 .await?;
319
320 if self.privileged_build {
321 nix_build = nix_build.sudo();
322 }
323
324 nix_build.run_nix().await.map_err(|e| {297 let outputs = drv.build().await.map_err(|e| {
325 if action.build_attr() == "sdImage" {298 if action.build_attr() == "sdImage" {
326 info!("sd-image build failed");299 info!("sd-image build failed");
327 info!("Make sure you have imported modulesPath/installer/sd-card/sd-image-<arch>[-installer].nix (For installer, you may want to check config)");300 info!("Make sure you have imported modulesPath/installer/sd-card/sd-image-<arch>[-installer].nix (For installer, you may want to check config)");
328 info!("This module was automatically imported before, but was removed for better customization")301 info!("This module was automatically imported before, but was removed for better customization")
329 }302 }
330 e303 e
331 })?;304 })?;
332 let built = std::fs::canonicalize(built)?;305 let out_output = outputs
306 .get("out")
307 .ok_or_else(|| anyhow!("system build should produce \"out\" output"))?;
333308
334 match action {309 match action {
335 Action::Upload { action } => {310 Action::Upload { action } => {
342 .arg("sign")317 .arg("sign")
343 .comparg("--key-file", "/etc/nix/private-key")318 .comparg("--key-file", "/etc/nix/private-key")
344 .arg("-r")319 .arg("-r")
345 .arg(&built);320 .arg(out_output);
346 if let Err(e) = sign.sudo().run_nix().await {321 if let Err(e) = sign.sudo().run_nix().await {
347 warn!("Failed to sign store paths: {e}");322 warn!("Failed to sign store paths: {e}");
348 };323 };
353 nix.arg("copy")328 nix.arg("copy")
354 .arg("--substitute-on-destination")329 .arg("--substitute-on-destination")
355 .comparg("--to", format!("ssh-ng://{host}"))330 .comparg("--to", format!("ssh-ng://{host}"))
356 .arg(&built);331 .arg(out_output);
357 match nix.run_nix().await {332 match nix.run_nix().await {
358 Ok(()) => break,333 Ok(()) => break,
359 Err(e) if tries < 3 => {334 Err(e) if tries < 3 => {
366 }341 }
367 }342 }
368 if let Some(action) = action {343 if let Some(action) = action {
369 execute_upload(&self, &config, action, &host, built).await?344 execute_upload(&self, &config, action, &host, out_output.clone()).await?
370 }345 }
371 }346 }
372 Action::Package(PackageAction::SdImage) => {347 Action::Package(PackageAction::SdImage) => {
373 let mut out = current_dir()?;348 let mut out = current_dir()?;
374 out.push(format!("sd-image-{}", host));349 out.push(format!("sd-image-{}", host));
375350
376 info!("building sd image to {:?}", out);351 info!("linking sd image to {:?}", out);
377 let mut nix_build = MyCommand::new("nix");
378 nix_build
379 .args(["build", "--impure", "--no-link"])
380 .comparg("--out-link", &out)352 symlink(out_output, out)?;
381 .arg(config.configuration_attr_name(&format!("buildSystems.sdImage.{}", host,)))
382 .args(&config.nix_args);
383 if !self.fail_fast {
384 nix_build.arg("--keep-going");
385 }
386 if self.privileged_build {
387 nix_build = nix_build.sudo();
388 }
389
390 nix_build.run_nix().await?;
391 }353 }
392 Action::Package(PackageAction::InstallationCd) => {354 Action::Package(PackageAction::InstallationCd) => {
393 let mut out = current_dir()?;355 let mut out = current_dir()?;
394 out.push(format!("installation-cd-{}", host));356 out.push(format!("installation-cd-{}", host));
395357
396 info!("building sd image to {:?}", out);358 info!("linking iso image to {:?}", out);
397 let mut nix_build = MyCommand::new("nix");
398 nix_build
399 .args(["build", "--impure", "--no-link"])
400 .comparg("--out-link", &out)359 symlink(out_output, out)?;
401 .arg(
402 config.configuration_attr_name(&format!(
403 "buildSystems.installationCd.{}",
404 host,
405 )),
406 )
407 .args(&config.nix_args);
408 if !self.fail_fast {
409 nix_build.arg("--keep-going");
410 }
411 if self.privileged_build {
412 nix_build = nix_build.sudo();
413 }
414
415 nix_build.run_nix().await?;
416 }360 }
417 };361 };
418 Ok(())362 Ok(())
modifiedcmds/fleet/src/cmds/info.rsdiffbeforeafterboth
1use std::collections::BTreeSet;1use std::collections::BTreeSet;
22
3use crate::host::Config;3use crate::host::Config;
4use crate::nix_path;
4use anyhow::{ensure, Result};5use anyhow::{ensure, Result};
5use clap::Parser;6use clap::Parser;
67
38 if !tagged.is_empty() {39 if !tagged.is_empty() {
39 let tags: Vec<String> = config40 let tags: Vec<String> = config
40 .fleet_field41 .fleet_field
41 .get_field_deep(["configuredSystems", &host.name, "config", "tags"])42 .select(nix_path!(.configuredSystems.{&host.name}.config.tags))
42 .await?43 .await?
43 .as_json()44 .as_json()
44 .await?;45 .await?;
64 let host = config.system_config(&host).await?;65 let host = config.system_config(&host).await?;
65 if external {66 if external {
66 out.extend(67 out.extend(
67 host.get_field_deep(["network", "externalIps"])68 host.select(nix_path!(.network.externalIps))
68 .await?69 .await?
69 .as_json::<Vec<String>>()70 .as_json::<Vec<String>>()
70 .await?,71 .await?,
71 );72 );
72 }73 }
73 if internal {74 if internal {
74 out.extend(75 out.extend(
75 host.get_field_deep(["network", "internalIps"])76 host.select(nix_path!(.network.internalIps))
76 .await?77 .await?
77 .as_json::<Vec<String>>()78 .as_json::<Vec<String>>()
78 .await?,79 .await?,
modifiedcmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 fleetdata::{FleetSecret, FleetSharedSecret},2 fleetdata::{FleetSecret, FleetSharedSecret},
3 host::Config,3 host::Config, nix_path,
4};4};
5use anyhow::{bail, ensure, Context, Result};5use anyhow::{bail, ensure, Context, Result};
6use chrono::Utc;6use chrono::Utc;
339 let mut data = config.shared_secret(name)?;339 let mut data = config.shared_secret(name)?;
340 let expected_owners: Vec<String> = config340 let expected_owners: Vec<String> = config
341 .config_field341 .config_field
342 .get_json_deep(["sharedSecrets", name, "expectedOwners"])342 .get_json_deep(nix_path!(sharedSecrets.{name}.expectedOwners))
343 .await?;343 .await?;
344 if expected_owners.is_empty() {344 if expected_owners.is_empty() {
345 warn!("secret was removed from fleet config: {name}, removing from data");345 warn!("secret was removed from fleet config: {name}, removing from data");
352 if set != expected_set {352 if set != expected_set {
353 let owner_dependent: bool = config353 let owner_dependent: bool = config
354 .config_field354 .config_field
355 .get_json_deep(["sharedSecrets", name, "ownerDependent"])355 .get_json_deep(nix_path!(.sharedSecrets.{name}.ownerDependent))
356 .await?;356 .await?;
357 if !owner_dependent {357 if !owner_dependent {
358 warn!("reencrypting secret '{name}' for new owner set");358 warn!("reencrypting secret '{name}' for new owner set");
modifiedcmds/fleet/src/command.rsdiffbeforeafterboth
1use std::{1use std::{
2 borrow::Cow,
3 collections::HashMap,2 collections::HashMap,
4 ffi::OsStr,3 ffi::OsStr,
5 process::Stdio,4 process::Stdio,
247pub struct NixHandler {246pub struct NixHandler {
248 spans: HashMap<u64, Span>,247 spans: HashMap<u64, Span>,
249}248}
250fn process_message(m: &str) -> Cow<'_, str> {249fn process_message(m: &str) -> String {
251 static OSC_CLEANER: Lazy<Regex> =250 static OSC_CLEANER: Lazy<Regex> =
252 Lazy::new(|| Regex::new(r"\x1B\]([^\x07\x1C]*[\x07\x1C])?|\r").unwrap());251 Lazy::new(|| Regex::new(r"\x1B\]([^\x07\x1C]*[\x07\x1C])?|\r").unwrap());
252 static DETABBER: Lazy<Regex> = Lazy::new(|| Regex::new(r"\t").unwrap());
253 OSC_CLEANER.replace_all(m, "")253 let m = OSC_CLEANER.replace_all(m, "");
254 // Indicatif can't format tabs. This is not the correct tab formatting, as correct one should be aligned,
255 // and not just be replaced with the constant number of spaces, but it's ok for now, as statuses are single-line.
256 DETABBER.replace_all(m.as_ref(), " ").to_string()
254}257}
255impl Handler for NixHandler {258impl Handler for NixHandler {
256 fn handle_line(&mut self, e: &str) {259 fn handle_line(&mut self, e: &str) {
modifiedcmds/fleet/src/host.rsdiffbeforeafterboth
13use tempfile::NamedTempFile;13use tempfile::NamedTempFile;
1414
15use crate::{15use crate::{
16 better_nix_eval::{Field, NixSessionPool},16 better_nix_eval::{Field, Index, NixSessionPool},
17 command::MyCommand,17 command::MyCommand,
18 fleetdata::{FleetData, FleetSecret, FleetSharedSecret},18 fleetdata::{FleetData, FleetSecret, FleetSharedSecret},
19 nix_path,
19};20};
2021
21pub struct FleetConfigInternals {22pub struct FleetConfigInternals {
24 pub opts: FleetOpts,25 pub opts: FleetOpts,
25 pub data: Mutex<FleetData>,26 pub data: Mutex<FleetData>,
26 pub nix_args: Vec<OsString>,27 pub nix_args: Vec<OsString>,
27 // fleetConfigurations.<name>28 /// fleetConfigurations.<name>.<localSystem>
28 pub fleet_field: Field,29 pub fleet_field: Field,
29 // fleet_config.configUnchecked30 /// fleet_config.configUnchecked
30 pub config_field: Field,31 pub config_field: Field,
31}32}
3233
93 command.run_string().await94 command.run_string().await
94 }95 }
95
96 pub fn configuration_attr_name(&self, name: &str) -> OsString {
97 let mut str = self.directory.as_os_str().to_owned();
98 str.push("#");
99 str.push(&format!(
100 "fleetConfigurations.default.{}.{}",
101 self.local_system, name
102 ));
103 str
104 }
10596
106 pub async fn list_hosts(&self) -> Result<Vec<ConfigHost>> {97 pub async fn list_hosts(&self) -> Result<Vec<ConfigHost>> {
107 let names = self98 let names = self
108 .fleet_field99 .fleet_field
109 .get_field_deep(["configuredHosts"])100 .select(nix_path!(.configuredHosts))
110 .await?101 .await?
111 .list_fields()102 .list_fields()
112 .await?;103 .await?;
118 }109 }
119 pub async fn system_config(&self, host: &str) -> Result<Field> {110 pub async fn system_config(&self, host: &str) -> Result<Field> {
120 self.fleet_field111 self.fleet_field
121 .get_field_deep(["configuredSystems", host, "config"])112 .select(nix_path!(.configuredSystems.{host}.config))
122 .await113 .await
123 }114 }
124115
131 /// Shared secrets configured in fleet.nix or in flake122 /// Shared secrets configured in fleet.nix or in flake
132 pub async fn list_configured_shared(&self) -> Result<Vec<String>> {123 pub async fn list_configured_shared(&self) -> Result<Vec<String>> {
133 self.config_field124 self.config_field
134 .get_field("sharedSecrets")125 .select(nix_path!(.sharedSecrets))
135 .await?126 .await?
136 .list_fields()127 .list_fields()
137 .await128 .await
221 }212 }
222 pub async fn shared_secret_expected_owners(&self, secret: &str) -> Result<Vec<String>> {213 pub async fn shared_secret_expected_owners(&self, secret: &str) -> Result<Vec<String>> {
223 self.config_field214 self.config_field
224 .get_field_deep(["sharedSecrets", secret, "expectedOwners"])215 .select(nix_path!(.sharedSecrets.{secret}.expectedOwners))
225 .await?216 .await?
226 .as_json()217 .as_json()
227 .await218 .await
279270
280 if self.local_system == "detect" {271 if self.local_system == "detect" {
281 let builtins_field = Field::field(root_field.clone(), "builtins").await?;272 let builtins_field = Field::field(root_field.clone(), "builtins").await?;
282 let system = builtins_field.get_field("currentSystem").await?;273 let system = builtins_field
274 .select(nix_path!(.currentSystem))
275 .await?;
283 self.local_system = system.as_json().await?;276 self.local_system = system.as_json().await?;
284 }277 }
287 let fleet_root = Field::field(root_field, "fleetConfigurations").await?;280 let fleet_root = Field::field(root_field, "fleetConfigurations").await?;
288281
289 let fleet_field = fleet_root282 let fleet_field = fleet_root
290 .get_field_deep(["default", &local_system])283 .select(nix_path!(.default.{&local_system}))
291 .await?;284 .await?;
292 let config_field = fleet_field.get_field("configUnchecked").await?;285 let config_field = fleet_field
286 .select(nix_path!(.configUnchecked))
287 .await?;
293288
294 let mut fleet_data_path = directory.clone();289 let mut fleet_data_path = directory.clone();
modifiedcmds/fleet/src/main.rsdiffbeforeafterboth
1#![recursion_limit = "512"]
1#![feature(try_blocks)]2#![feature(try_blocks)]
23
3pub(crate) mod cmds;4pub(crate) mod cmds;
modifiedflake.nixdiffbeforeafterboth
19 rustPlatform = pkgs.makeRustPlatform { cargo = rust; rustc = rust; };19 rustPlatform = pkgs.makeRustPlatform { cargo = rust; rustc = rust; };
20 in20 in
21 {21 {
22 packages = (import ./pkgs) pkgs pkgs;
22 devShell = (pkgs.mkShell.override { stdenv = llvmPkgs.stdenv; }) {23 devShell = (pkgs.mkShell.override { stdenv = llvmPkgs.stdenv; }) {
23 nativeBuildInputs = with pkgs; [24 nativeBuildInputs = with pkgs; [
24 rust25 rust