Skip to content

Commit

Permalink
remove managed fields when using dry-run to ease the apply on a cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
shigedangao committed Feb 5, 2025
1 parent 35ba933 commit a1dda09
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 45 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "bakkutteh"
version = "0.1.5"
version = "0.1.6"
edition = "2021"

[dependencies]
clap = { version = "4.5.26", features = ["derive"] }
clap = { version = "4.5.28", features = ["derive"] }
kube = { version = "0.98.0", features = ["runtime", "derive"] }
k8s-openapi = { version = "0.24.0", features = ["latest"] }
tokio = { version = "1.43.0", features = ["full"] }
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ Just run without the option `-j`. A prompt will appear showing the list of cronj
bakkutteh -- -t dodo --dry-run
```

### Create a Job from a Deployment

You can also create a Job from an existing deployment. You just need to add the `--deployment` option. Example below

```sh
bakkutteh -- -t dodo --dry-run --deployment
```

### Add additionals environment variable

The CLI also allows you to add additional environment variables. The prompt will ask you whether you wanna add additional environment variable.
If you wish to do so please follow this format e.g below. Quote don't need to be added.

```sh
DATA_START_TIME=2025-02-05T00:00:00
```

### Output example

```sh
Expand Down
9 changes: 5 additions & 4 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const SPLIT_ENV_OPERATOR: &str = "=";

#[derive(Parser)]
#[command(
version = "0.1.5",
version = "0.1.6",
about = "A command to dispatch a kubernetes job from a cronjob spec"
)]
pub struct Cli {
Expand All @@ -27,7 +27,7 @@ pub struct Cli {
target_name: String,

#[arg(short, long, default_value = "false")]
dry_run: bool,
pub dry_run: bool,

#[arg(short, long, default_value = "default")]
pub namespace: String,
Expand Down Expand Up @@ -81,8 +81,9 @@ impl Cli {

kube_handler
.build_manual_job(&self.target_name, job_spec, self.backoff_limit)?
.apply_manual_job(self.dry_run)
.await?;
.apply_manual_job()
.await
.and_then(|job| kube_handler.display_spec(job))?;

Ok(())
}
Expand Down
94 changes: 63 additions & 31 deletions src/kube/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ use std::fmt::Debug;

pub(crate) mod spec;

// Constant
const BATCH_UID_REMOVE: &str = "batch.kubernetes.io/controller-uid";
const UID_REMOVE: &str = "controller-uid";

#[derive(Clone)]
pub struct KubeHandler<S: AsRef<str>> {
client: Client,
namespace: S,
job: Option<Job>,
dry_run: bool,
}

impl<S> KubeHandler<S>
Expand All @@ -33,13 +38,14 @@ where
/// # Arguments
///
/// * `ns` - S
pub async fn new(ns: S) -> Result<Self> {
pub async fn new(ns: S, dry_run: bool) -> Result<Self> {
let client = Client::try_default().await?;

Ok(Self {
client,
namespace: ns,
job: None,
dry_run,
})
}

Expand Down Expand Up @@ -175,47 +181,73 @@ where
}

/// Apply the manual job in K8S
///
/// # Arguments
///
/// * `dry_run` - bool
pub async fn apply_manual_job(&self, dry_run: bool) -> Result<()> {
pub async fn apply_manual_job(&self) -> Result<Job> {
let job_api: Api<Job> = Api::namespaced(self.client.clone(), self.namespace.as_ref());
let mut pp = PostParams::default();

if dry_run {
if self.dry_run {
pp.dry_run = true;
}

let Some(job) = &self.job else {
return Err(anyhow!("Unable to create the job as building spec failed"));
};

match job_api.create(&pp, job).await {
Ok(res) => match dry_run {
true => {
let yaml = serde_yml::to_string(&res)?;
println!(
"\nDry run result for job {}",
res.metadata.name.unwrap_or_default().bright_purple().bold()
);
let job = job_api.create(&pp, job).await?;

println!("\n{}", yaml)
}
false => println!(
"Job {} created",
res.metadata
.name
.unwrap_or_default()
.truecolor(7, 174, 237)
.bold()
),
},
Err(err) => println!(
"Unable to create job due to error: {}",
err.to_string().red().bold()
),
};
Ok(job)
}

/// Display the spec in the case if the user asked for a dry run
///
/// # Arguments
///
/// * `job` - Job
pub fn display_spec(&self, mut job: Job) -> Result<()> {
if !self.dry_run {
println!(
"Job {} created",
job.metadata
.name
.unwrap_or_default()
.truecolor(7, 174, 237)
.bold()
);

return Ok(());
}

// Remove presence of managed fields from the job
job.metadata.managed_fields = None;
// Remove presence of labels containing "controler-uid" in the metadata & template
if let Some(fields) = job.metadata.labels.as_mut() {
fields.remove(BATCH_UID_REMOVE);
fields.remove(UID_REMOVE);
}

if let Some(labels) = job
.spec
.as_mut()
.and_then(|spec| spec.template.metadata.as_mut())
.and_then(|tmpl| tmpl.labels.as_mut())
{
labels.remove(UID_REMOVE);
labels.remove(BATCH_UID_REMOVE);
}

job.spec
.as_mut()
.and_then(|spec| spec.selector.as_mut())
.and_then(|selector| selector.match_labels.as_mut())
.map(|selector| selector.remove(BATCH_UID_REMOVE));

let yaml = serde_yml::to_string(&job)?;
println!(
"\nDry run result for job {}",
job.metadata.name.unwrap_or_default().bright_purple().bold()
);

println!("\n{}", yaml);

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = cli::Cli::parse();

// Initialize the kube handler
let mut kube_handler = kube::KubeHandler::new(&cli.namespace).await?;
let mut kube_handler = kube::KubeHandler::new(&cli.namespace, cli.dry_run).await?;

// Run the command
if let Err(err) = cli.run(&mut kube_handler).await {
Expand Down

0 comments on commit a1dda09

Please sign in to comment.