mirror of
https://github.com/moghtech/komodo.git
synced 2026-04-28 11:49:39 -05:00
implement update for most resources
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -2594,6 +2594,9 @@ dependencies = [
|
||||
"futures-util",
|
||||
"komodo_client",
|
||||
"logger",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_qs",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -21,10 +21,13 @@ config.workspace = true
|
||||
logger.workspace = true
|
||||
# external
|
||||
futures-util.workspace = true
|
||||
serde_json.workspace = true
|
||||
serde_qs.workspace = true
|
||||
tracing.workspace = true
|
||||
colored.workspace = true
|
||||
dotenvy.workspace = true
|
||||
anyhow.workspace = true
|
||||
tokio.workspace = true
|
||||
serde.workspace = true
|
||||
clap.workspace = true
|
||||
envy.workspace = true
|
||||
@@ -1,10 +1,21 @@
|
||||
use anyhow::Context;
|
||||
use colored::Colorize;
|
||||
use komodo_client::entities::optional_string;
|
||||
use komodo_client::entities::{
|
||||
config::cli::DatabaseCommand, optional_string,
|
||||
};
|
||||
|
||||
use crate::config::cli_config;
|
||||
|
||||
pub async fn backup(yes: bool) -> anyhow::Result<()> {
|
||||
pub async fn handle(command: &DatabaseCommand) -> anyhow::Result<()> {
|
||||
match command {
|
||||
DatabaseCommand::Backup { yes, .. } => backup(*yes).await,
|
||||
DatabaseCommand::Restore { yes, .. } => restore(*yes).await,
|
||||
DatabaseCommand::Prune { yes, .. } => prune(*yes).await,
|
||||
DatabaseCommand::Copy { yes, .. } => copy(*yes).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn backup(yes: bool) -> anyhow::Result<()> {
|
||||
let config = cli_config();
|
||||
|
||||
println!(
|
||||
@@ -63,7 +74,7 @@ pub async fn backup(yes: bool) -> anyhow::Result<()> {
|
||||
prune_inner().await
|
||||
}
|
||||
|
||||
pub async fn restore(yes: bool) -> anyhow::Result<()> {
|
||||
async fn restore(yes: bool) -> anyhow::Result<()> {
|
||||
let config = cli_config();
|
||||
|
||||
println!(
|
||||
@@ -116,7 +127,7 @@ pub async fn restore(yes: bool) -> anyhow::Result<()> {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn prune(yes: bool) -> anyhow::Result<()> {
|
||||
async fn prune(yes: bool) -> anyhow::Result<()> {
|
||||
let config = cli_config();
|
||||
|
||||
println!(
|
||||
@@ -218,7 +229,7 @@ async fn prune_inner() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn copy(yes: bool) -> anyhow::Result<()> {
|
||||
async fn copy(yes: bool) -> anyhow::Result<()> {
|
||||
let config = cli_config();
|
||||
|
||||
println!(
|
||||
|
||||
@@ -16,8 +16,8 @@ enum ExecutionResult {
|
||||
Batch(BatchExecutionResponse),
|
||||
}
|
||||
|
||||
pub async fn execute(
|
||||
execution: Execution,
|
||||
pub async fn handle(
|
||||
execution: &Execution,
|
||||
yes: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
if matches!(execution, Execution::None(_)) {
|
||||
@@ -28,7 +28,7 @@ pub async fn execute(
|
||||
}
|
||||
|
||||
println!("\n{}: Execution", "Mode".dimmed());
|
||||
match &execution {
|
||||
match execution {
|
||||
Execution::None(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
@@ -229,7 +229,7 @@ pub async fn execute(
|
||||
|
||||
let client = super::komodo_client().await?;
|
||||
|
||||
let res = match execution {
|
||||
let res = match execution.clone() {
|
||||
Execution::RunAction(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
|
||||
@@ -8,12 +8,9 @@ use tokio::sync::OnceCell;
|
||||
use crate::config::cli_config;
|
||||
|
||||
pub mod database;
|
||||
pub mod execute;
|
||||
pub mod update;
|
||||
|
||||
mod execute;
|
||||
|
||||
pub use execute::execute;
|
||||
|
||||
async fn komodo_client() -> anyhow::Result<&'static KomodoClient> {
|
||||
static KOMODO_CLIENT: OnceCell<KomodoClient> =
|
||||
OnceCell::const_new();
|
||||
|
||||
@@ -1,13 +1,66 @@
|
||||
use anyhow::Context;
|
||||
use colored::Colorize;
|
||||
use komodo_client::api::{
|
||||
read::GetVariable,
|
||||
write::{
|
||||
CreateVariable, UpdateVariableIsSecret, UpdateVariableValue,
|
||||
use komodo_client::{
|
||||
api::{
|
||||
read::GetVariable,
|
||||
write::{
|
||||
CreateVariable, UpdateBuild, UpdateDeployment, UpdateRepo,
|
||||
UpdateResourceSync, UpdateServer, UpdateStack,
|
||||
UpdateVariableIsSecret, UpdateVariableValue,
|
||||
},
|
||||
},
|
||||
entities::{
|
||||
build::PartialBuildConfig, config::cli::UpdateCommand,
|
||||
deployment::PartialDeploymentConfig, repo::PartialRepoConfig,
|
||||
server::PartialServerConfig, stack::PartialStackConfig,
|
||||
sync::PartialResourceSyncConfig,
|
||||
},
|
||||
};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
|
||||
pub async fn variable(
|
||||
pub async fn handle(command: &UpdateCommand) -> anyhow::Result<()> {
|
||||
match command {
|
||||
UpdateCommand::Variable {
|
||||
name,
|
||||
value,
|
||||
secret,
|
||||
yes,
|
||||
} => update_variable(name, value, *secret, *yes).await,
|
||||
UpdateCommand::Build { build, update, yes } => {
|
||||
update_resource::<PartialBuildConfig>(build, update, *yes).await
|
||||
}
|
||||
UpdateCommand::Deployment {
|
||||
deployment,
|
||||
update,
|
||||
yes,
|
||||
} => {
|
||||
update_resource::<PartialDeploymentConfig>(
|
||||
deployment, update, *yes,
|
||||
)
|
||||
.await
|
||||
}
|
||||
UpdateCommand::Repo { repo, update, yes } => {
|
||||
update_resource::<PartialRepoConfig>(repo, update, *yes).await
|
||||
}
|
||||
UpdateCommand::Server {
|
||||
server,
|
||||
update,
|
||||
yes,
|
||||
} => {
|
||||
update_resource::<PartialServerConfig>(server, update, *yes)
|
||||
.await
|
||||
}
|
||||
UpdateCommand::Stack { stack, update, yes } => {
|
||||
update_resource::<PartialStackConfig>(stack, update, *yes).await
|
||||
}
|
||||
UpdateCommand::Sync { sync, update, yes } => {
|
||||
update_resource::<PartialResourceSyncConfig>(sync, update, *yes)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn update_variable(
|
||||
name: &str,
|
||||
value: &str,
|
||||
secret: Option<bool>,
|
||||
@@ -68,3 +121,137 @@ pub async fn variable(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_resource<
|
||||
T: std::fmt::Debug + Serialize + DeserializeOwned + ResourceUpdate,
|
||||
>(
|
||||
resource: &str,
|
||||
update: &str,
|
||||
yes: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
println!("\n{}: Update {}\n", "Mode".dimmed(), T::resource_type());
|
||||
println!(" - {}: {resource}", "Name".dimmed());
|
||||
|
||||
let config = serde_qs::from_str::<T>(update)
|
||||
.context("Failed to deserialize config")?;
|
||||
|
||||
match serde_json::to_string_pretty(&config) {
|
||||
Ok(config) => {
|
||||
println!(" - {}: {config}", "Update".dimmed());
|
||||
}
|
||||
Err(_) => {
|
||||
println!(" - {}: {config:#?}", "Update".dimmed());
|
||||
}
|
||||
}
|
||||
|
||||
super::wait_for_enter("update resource", yes)?;
|
||||
|
||||
config.apply(resource).await
|
||||
}
|
||||
|
||||
trait ResourceUpdate {
|
||||
fn resource_type() -> &'static str;
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
impl ResourceUpdate for PartialBuildConfig {
|
||||
fn resource_type() -> &'static str {
|
||||
"Build"
|
||||
}
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()> {
|
||||
let client = super::komodo_client().await?;
|
||||
client
|
||||
.write(UpdateBuild {
|
||||
id: resource.to_string(),
|
||||
config: self,
|
||||
})
|
||||
.await
|
||||
.context("Failed to update build config")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceUpdate for PartialDeploymentConfig {
|
||||
fn resource_type() -> &'static str {
|
||||
"Deployment"
|
||||
}
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()> {
|
||||
let client = super::komodo_client().await?;
|
||||
client
|
||||
.write(UpdateDeployment {
|
||||
id: resource.to_string(),
|
||||
config: self,
|
||||
})
|
||||
.await
|
||||
.context("Failed to update deployment config")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceUpdate for PartialRepoConfig {
|
||||
fn resource_type() -> &'static str {
|
||||
"Repo"
|
||||
}
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()> {
|
||||
let client = super::komodo_client().await?;
|
||||
client
|
||||
.write(UpdateRepo {
|
||||
id: resource.to_string(),
|
||||
config: self,
|
||||
})
|
||||
.await
|
||||
.context("Failed to update repo config")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceUpdate for PartialServerConfig {
|
||||
fn resource_type() -> &'static str {
|
||||
"Server"
|
||||
}
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()> {
|
||||
let client = super::komodo_client().await?;
|
||||
client
|
||||
.write(UpdateServer {
|
||||
id: resource.to_string(),
|
||||
config: self,
|
||||
})
|
||||
.await
|
||||
.context("Failed to update server config")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceUpdate for PartialStackConfig {
|
||||
fn resource_type() -> &'static str {
|
||||
"Stack"
|
||||
}
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()> {
|
||||
let client = super::komodo_client().await?;
|
||||
client
|
||||
.write(UpdateStack {
|
||||
id: resource.to_string(),
|
||||
config: self,
|
||||
})
|
||||
.await
|
||||
.context("Failed to update stack config")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceUpdate for PartialResourceSyncConfig {
|
||||
fn resource_type() -> &'static str {
|
||||
"Sync"
|
||||
}
|
||||
async fn apply(self, resource: &str) -> anyhow::Result<()> {
|
||||
let client = super::komodo_client().await?;
|
||||
client
|
||||
.write(UpdateResourceSync {
|
||||
id: resource.to_string(),
|
||||
config: self,
|
||||
})
|
||||
.await
|
||||
.context("Failed to update sync config")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,29 +28,14 @@ async fn app() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
cli::Command::Execute { execution, yes, .. } => {
|
||||
command::execute(execution.clone(), *yes).await
|
||||
command::execute::handle(execution, *yes).await
|
||||
}
|
||||
cli::Command::Update { command } => {
|
||||
command::update::handle(command).await
|
||||
}
|
||||
cli::Command::Database { command } => {
|
||||
command::database::handle(command).await
|
||||
}
|
||||
cli::Command::Update {
|
||||
command:
|
||||
cli::UpdateCommand::Variable {
|
||||
name,
|
||||
value,
|
||||
secret,
|
||||
yes,
|
||||
},
|
||||
} => command::update::variable(name, value, *secret, *yes).await,
|
||||
cli::Command::Database {
|
||||
command: cli::DatabaseCommand::Backup { yes, .. },
|
||||
} => command::database::backup(*yes).await,
|
||||
cli::Command::Database {
|
||||
command: cli::DatabaseCommand::Restore { yes, .. },
|
||||
} => command::database::restore(*yes).await,
|
||||
cli::Command::Database {
|
||||
command: cli::DatabaseCommand::Prune { yes, .. },
|
||||
} => command::database::prune(*yes).await,
|
||||
cli::Command::Database {
|
||||
command: cli::DatabaseCommand::Copy { yes, .. },
|
||||
} => command::database::copy(*yes).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,25 +60,27 @@ pub enum Execution {
|
||||
None(NoData),
|
||||
|
||||
// ACTION
|
||||
/// Run the target action. (alias: `action`)
|
||||
#[clap(alias = "action")]
|
||||
/// Run the target action. (alias: `action`, `act`)
|
||||
#[clap(alias = "action", alias = "act")]
|
||||
RunAction(RunAction),
|
||||
BatchRunAction(BatchRunAction),
|
||||
|
||||
// PROCEDURE
|
||||
/// Run the target procedure. (alias: `procedure`)
|
||||
#[clap(alias = "procedure")]
|
||||
/// Run the target procedure. (alias: `procedure`, `proc`)
|
||||
#[clap(alias = "procedure", alias = "proc")]
|
||||
RunProcedure(RunProcedure),
|
||||
BatchRunProcedure(BatchRunProcedure),
|
||||
|
||||
// BUILD
|
||||
/// Run the target build. (alias: `build`)
|
||||
#[clap(alias = "build")]
|
||||
/// Run the target build. (alias: `build`, `bld`)
|
||||
#[clap(alias = "build", alias = "bld")]
|
||||
RunBuild(RunBuild),
|
||||
BatchRunBuild(BatchRunBuild),
|
||||
CancelBuild(CancelBuild),
|
||||
|
||||
// DEPLOYMENT
|
||||
/// Deploy the target deployment. (alias: `dep`)
|
||||
#[clap(alias = "dep")]
|
||||
Deploy(Deploy),
|
||||
BatchDeploy(BatchDeploy),
|
||||
PullDeployment(PullDeployment),
|
||||
@@ -91,6 +93,8 @@ pub enum Execution {
|
||||
BatchDestroyDeployment(BatchDestroyDeployment),
|
||||
|
||||
// REPO
|
||||
/// Clone the target repo
|
||||
#[clap(alias = "clone")]
|
||||
CloneRepo(CloneRepo),
|
||||
BatchCloneRepo(BatchCloneRepo),
|
||||
PullRepo(PullRepo),
|
||||
@@ -125,10 +129,15 @@ pub enum Execution {
|
||||
PruneSystem(PruneSystem),
|
||||
|
||||
// SYNC
|
||||
/// Execute a Resource Sync. (alias: `sync`)
|
||||
#[clap(alias = "sync")]
|
||||
RunSync(RunSync),
|
||||
/// Commit a Resource Sync. (alias: `commit`)
|
||||
#[clap(alias = "commit")]
|
||||
CommitSync(CommitSync), // This is a special case, its actually a write operation.
|
||||
|
||||
// STACK
|
||||
#[clap(alias = "stack", alias = "stk")]
|
||||
DeployStack(DeployStack),
|
||||
BatchDeployStack(BatchDeployStack),
|
||||
DeployStackIfChanged(DeployStackIfChanged),
|
||||
|
||||
@@ -60,8 +60,8 @@ pub enum Command {
|
||||
unsanitized: bool,
|
||||
},
|
||||
|
||||
/// Run Komodo executions. (aliases: `x`, `run`)
|
||||
#[clap(alias = "x", alias = "run")]
|
||||
/// Run Komodo executions. (aliases: `x`, `run`, `deploy`, `dep`)
|
||||
#[clap(alias = "x", alias = "run", alias = "deploy", alias = "dep")]
|
||||
Execute {
|
||||
#[command(subcommand)]
|
||||
execution: Execution,
|
||||
@@ -80,7 +80,7 @@ pub enum Command {
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update resource properties. (alias `set`)
|
||||
/// Update resource configuration. (alias `set`)
|
||||
#[clap(alias = "set")]
|
||||
Update {
|
||||
#[command(subcommand)]
|
||||
@@ -112,6 +112,126 @@ pub enum UpdateCommand {
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update a Build's configuration. (alias: `bld`)
|
||||
#[clap(alias = "bld")]
|
||||
Build {
|
||||
/// The name / id of the Build.
|
||||
build: String,
|
||||
/// The update string, parsed using 'https://docs.rs/serde_qs/latest/serde_qs'.
|
||||
///
|
||||
/// The fields can be found here: 'https://docs.rs/komodo_client/latest/komodo_client/entities/build/struct.BuildConfig.html'
|
||||
///
|
||||
/// Example: `km update build example-build "version=1.13.4&branch=release"`
|
||||
///
|
||||
/// Note. Should be enclosed in single or double quotes.
|
||||
/// Values containing complex characters (like URLs)
|
||||
/// will need to be url-encoded in order to be parsed correctly.
|
||||
update: String,
|
||||
/// Always continue on user confirmation prompts.
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update a Deployments's configuration. (alias: `dep`)
|
||||
#[clap(alias = "dep")]
|
||||
Deployment {
|
||||
/// The name / id of the Deployment.
|
||||
deployment: String,
|
||||
/// The update string, parsed using 'https://docs.rs/serde_qs/latest/serde_qs'.
|
||||
///
|
||||
/// The fields can be found here: 'https://docs.rs/komodo_client/latest/komodo_client/entities/deployment/struct.DeploymentConfig.html'
|
||||
///
|
||||
/// Example: `km update deployment example-deployment "restart=unless-stopped"`
|
||||
///
|
||||
/// Note. Should be enclosed in single or double quotes.
|
||||
/// Values containing complex characters (like URLs)
|
||||
/// will need to be url-encoded in order to be parsed correctly.
|
||||
update: String,
|
||||
/// Always continue on user confirmation prompts.
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update a Repos's configuration.
|
||||
Repo {
|
||||
/// The name / id of the Repo.
|
||||
repo: String,
|
||||
/// The update string, parsed using 'https://docs.rs/serde_qs/latest/serde_qs'.
|
||||
///
|
||||
/// The fields can be found here: 'https://docs.rs/komodo_client/latest/komodo_client/entities/repo/struct.RepoConfig.html'
|
||||
///
|
||||
/// Example: `km update repo example-repo "branch=testing"`
|
||||
///
|
||||
/// Note. Should be enclosed in single or double quotes.
|
||||
/// Values containing complex characters (like URLs)
|
||||
/// will need to be url-encoded in order to be parsed correctly.
|
||||
update: String,
|
||||
/// Always continue on user confirmation prompts.
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update a Servers's configuration. (alias: `srv`)
|
||||
#[clap(alias = "srv")]
|
||||
Server {
|
||||
/// The name / id of the Server.
|
||||
server: String,
|
||||
/// The update string, parsed using 'https://docs.rs/serde_qs/latest/serde_qs'.
|
||||
///
|
||||
/// The fields can be found here: 'https://docs.rs/komodo_client/latest/komodo_client/entities/server/struct.ServerConfig.html'
|
||||
///
|
||||
/// Example: `km update server example-server "enabled=true&address=https%3A%2F%2Fmy.periphery%3A8120"`
|
||||
///
|
||||
/// The above includes example of url encoded address `https://my.periphery:8120`.
|
||||
///
|
||||
/// Note. Should be enclosed in single or double quotes.
|
||||
/// Values containing complex characters (like URLs)
|
||||
/// will need to be url-encoded in order to be parsed correctly.
|
||||
update: String,
|
||||
/// Always continue on user confirmation prompts.
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update a Stacks's configuration. (alias: `stk`)
|
||||
#[clap(alias = "stk")]
|
||||
Stack {
|
||||
/// The name / id of the Stack.
|
||||
stack: String,
|
||||
/// The update string, parsed using 'https://docs.rs/serde_qs/latest/serde_qs'.
|
||||
///
|
||||
/// The fields can be found here: 'https://docs.rs/komodo_client/latest/komodo_client/entities/stack/struct.StackConfig.html'
|
||||
///
|
||||
/// Example: `km update stack example-stack "branch=testing"`
|
||||
///
|
||||
/// Note. Should be enclosed in single or double quotes.
|
||||
/// Values containing complex characters (like URLs)
|
||||
/// will need to be url-encoded in order to be parsed correctly.
|
||||
update: String,
|
||||
/// Always continue on user confirmation prompts.
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
|
||||
/// Update a Syncs's configuration.
|
||||
Sync {
|
||||
/// The name / id of the Sync.
|
||||
sync: String,
|
||||
/// The update string, parsed using 'https://docs.rs/serde_qs/latest/serde_qs'.
|
||||
///
|
||||
/// The fields can be found here: 'https://docs.rs/komodo_client/latest/komodo_client/entities/sync/struct.ResourceSyncConfig.html'
|
||||
///
|
||||
/// Example: `km update sync example-sync "branch=testing"`
|
||||
///
|
||||
/// Note. Should be enclosed in single or double quotes.
|
||||
/// Values containing complex characters (like URLs)
|
||||
/// will need to be url-encoded in order to be parsed correctly.
|
||||
update: String,
|
||||
/// Always continue on user confirmation prompts.
|
||||
#[arg(long, short = 'y', default_value_t = false)]
|
||||
yes: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
|
||||
Reference in New Issue
Block a user