Add declarative attic cache
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
162
overlays/attic-client/declarative-key-pair.patch
Normal file
162
overlays/attic-client/declarative-key-pair.patch
Normal file
@@ -0,0 +1,162 @@
|
||||
diff --git a/client/src/cli.rs b/client/src/cli.rs
|
||||
index ee86783..e96b1b6 100644
|
||||
--- a/client/src/cli.rs
|
||||
+++ b/client/src/cli.rs
|
||||
@@ -9,6 +9,7 @@ use enum_as_inner::EnumAsInner;
|
||||
|
||||
use crate::command::cache::{self, Cache};
|
||||
use crate::command::get_closure::{self, GetClosure};
|
||||
+use crate::command::key::{self, Key};
|
||||
use crate::command::login::{self, Login};
|
||||
use crate::command::push::{self, Push};
|
||||
use crate::command::r#use::{self, Use};
|
||||
@@ -30,6 +31,7 @@ pub enum Command {
|
||||
Push(Push),
|
||||
Cache(Cache),
|
||||
WatchStore(WatchStore),
|
||||
+ Key(Key),
|
||||
|
||||
#[clap(hide = true)]
|
||||
GetClosure(GetClosure),
|
||||
@@ -57,6 +59,7 @@ pub async fn run() -> Result<()> {
|
||||
Command::Cache(_) => cache::run(opts).await,
|
||||
Command::WatchStore(_) => watch_store::run(opts).await,
|
||||
Command::GetClosure(_) => get_closure::run(opts).await,
|
||||
+ Command::Key(_) => key::run(opts).await,
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/client/src/command/cache.rs b/client/src/command/cache.rs
|
||||
index af01378..af24d8c 100644
|
||||
--- a/client/src/command/cache.rs
|
||||
+++ b/client/src/command/cache.rs
|
||||
@@ -7,8 +7,11 @@ use crate::api::ApiClient;
|
||||
use crate::cache::CacheRef;
|
||||
use crate::cli::Opts;
|
||||
use crate::config::Config;
|
||||
-use attic::api::v1::cache_config::{
|
||||
- CacheConfig, CreateCacheRequest, KeypairConfig, RetentionPeriodConfig,
|
||||
+use attic::{
|
||||
+ api::v1::cache_config::{
|
||||
+ CacheConfig, CreateCacheRequest, KeypairConfig, RetentionPeriodConfig,
|
||||
+ },
|
||||
+ signing::NixKeypair,
|
||||
};
|
||||
|
||||
/// Manage caches on an Attic server.
|
||||
@@ -72,6 +75,12 @@ struct Create {
|
||||
default_value = "cache.nixos.org-1"
|
||||
)]
|
||||
upstream_cache_key_names: Vec<String>,
|
||||
+
|
||||
+ /// The signing keypair to use for the cache.
|
||||
+ ///
|
||||
+ /// If not specified, a new keypair will be generated.
|
||||
+ #[clap(long)]
|
||||
+ keypair_path: Option<String>,
|
||||
}
|
||||
|
||||
/// Configure a cache.
|
||||
@@ -91,6 +100,14 @@ struct Configure {
|
||||
#[clap(long)]
|
||||
regenerate_keypair: bool,
|
||||
|
||||
+ /// Set a keypair for the cache.
|
||||
+ ///
|
||||
+ /// The server-side signing key will be set to the
|
||||
+ /// specified keypair. This is useful for setting up
|
||||
+ /// a cache with a pre-existing keypair.
|
||||
+ #[clap(long, conflicts_with = "regenerate_keypair")]
|
||||
+ keypair_path: Option<String>,
|
||||
+
|
||||
/// Make the cache public.
|
||||
///
|
||||
/// Use `--private` to make it private.
|
||||
@@ -179,9 +196,15 @@ async fn create_cache(sub: Create) -> Result<()> {
|
||||
let (server_name, server, cache) = config.resolve_cache(&sub.cache)?;
|
||||
let api = ApiClient::from_server_config(server.clone())?;
|
||||
|
||||
+ let keypair = if let Some(keypair_path) = &sub.keypair_path {
|
||||
+ let contents = std::fs::read_to_string(keypair_path)?;
|
||||
+ KeypairConfig::Keypair(NixKeypair::from_str(&contents)?)
|
||||
+ } else {
|
||||
+ KeypairConfig::Generate
|
||||
+ };
|
||||
+
|
||||
let request = CreateCacheRequest {
|
||||
- // TODO: Make this configurable?
|
||||
- keypair: KeypairConfig::Generate,
|
||||
+ keypair,
|
||||
is_public: sub.public,
|
||||
priority: sub.priority,
|
||||
store_dir: sub.store_dir,
|
||||
@@ -230,6 +253,10 @@ async fn configure_cache(sub: Configure) -> Result<()> {
|
||||
|
||||
if sub.regenerate_keypair {
|
||||
patch.keypair = Some(KeypairConfig::Generate);
|
||||
+ } else if let Some(keypair_path) = &sub.keypair_path {
|
||||
+ let contents = std::fs::read_to_string(keypair_path)?;
|
||||
+ let keypair = KeypairConfig::Keypair(NixKeypair::from_str(&contents)?);
|
||||
+ patch.keypair = Some(keypair);
|
||||
}
|
||||
|
||||
patch.store_dir = sub.store_dir;
|
||||
diff --git a/client/src/command/key.rs b/client/src/command/key.rs
|
||||
new file mode 100644
|
||||
index 0000000..807d8a7
|
||||
--- /dev/null
|
||||
+++ b/client/src/command/key.rs
|
||||
@@ -0,0 +1,42 @@
|
||||
+use anyhow::Result;
|
||||
+use clap::{Parser, Subcommand};
|
||||
+
|
||||
+use crate::cli::Opts;
|
||||
+use attic::signing::NixKeypair;
|
||||
+
|
||||
+/// Manage signing keys.
|
||||
+#[derive(Debug, Parser)]
|
||||
+pub struct Key {
|
||||
+ #[clap(subcommand)]
|
||||
+ command: KeyCommand,
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug, Subcommand)]
|
||||
+enum KeyCommand {
|
||||
+ Generate(Generate),
|
||||
+}
|
||||
+
|
||||
+/// Generate a key.
|
||||
+#[derive(Debug, Clone, Parser)]
|
||||
+pub struct Generate {
|
||||
+ /// Name of the key (must not contain colons).
|
||||
+ name: String,
|
||||
+}
|
||||
+
|
||||
+pub async fn run(opts: Opts) -> Result<()> {
|
||||
+ let sub = opts.command.as_key().unwrap();
|
||||
+ match &sub.command {
|
||||
+ KeyCommand::Generate(sub) => generate_key(sub).await,
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+async fn generate_key(sub: &Generate) -> Result<()> {
|
||||
+ let keypair = NixKeypair::generate(&sub.name)?;
|
||||
+
|
||||
+ println!("🔑 Generated keypair \"{}\"", sub.name);
|
||||
+ println!();
|
||||
+ println!(" Private key: {}", keypair.export_keypair());
|
||||
+ println!(" Public key: {}", keypair.export_public_key());
|
||||
+
|
||||
+ Ok(())
|
||||
+}
|
||||
diff --git a/client/src/command/mod.rs b/client/src/command/mod.rs
|
||||
index cca423f..26b105a 100644
|
||||
--- a/client/src/command/mod.rs
|
||||
+++ b/client/src/command/mod.rs
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod cache;
|
||||
pub mod get_closure;
|
||||
+pub mod key;
|
||||
pub mod login;
|
||||
pub mod push;
|
||||
pub mod r#use;
|
Reference in New Issue
Block a user