Skip to content

Commit

Permalink
reset command
Browse files Browse the repository at this point in the history
Signed-off-by: Navid Yaghoobi <[email protected]>
  • Loading branch information
navidys committed Sep 29, 2024
1 parent ad30ad1 commit a39d0cb
Show file tree
Hide file tree
Showing 18 changed files with 377 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@ homepage = "https://github.com/navidys/ocibuilder"
repository = "https://github.com/navidys/ocibuilder"

[dependencies]
clap = { version = "4.5.18", features = ["derive"] }
env_logger = "0.11.5"
fs2 = "0.4.3"
home = "0.5.9"
log = "0.4.22"
oci-spec = "0.7.0"
thiserror = "1.0.63"
url = "2.5.2"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ The project is under development and not ready for usage (feel free to contribut

| Command | Description |
| ---------- | ----------- |
| reset | Reset local storage.
2 changes: 2 additions & 0 deletions src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod oci;
pub mod reset;
87 changes: 87 additions & 0 deletions src/builder/oci.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use fs2::FileExt;

use std::{
fs::{self, File},
path::PathBuf,
};

use log::debug;

use crate::{
container::store::ContainerStore,
error::{BuilderError, BuilderResult},
image::store::ImageStore,
layer::store::LayerStore,
};

pub struct OCIBuilder {
image_store: ImageStore,
container_store: ContainerStore,
layer_store: LayerStore,
_root_dir: PathBuf,
_tmp_dir: PathBuf,
lock_file: File,
}

impl OCIBuilder {
pub fn new(root_dir: PathBuf) -> BuilderResult<Self> {
debug!("root directory: {:?}", root_dir);

// builder tmp directory
let mut tmp_dir = PathBuf::from(&root_dir);
tmp_dir.push("tmp/");

match fs::create_dir_all(&tmp_dir) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(tmp_dir, err)),
}

// builder lock file
let mut lfile = PathBuf::from(&root_dir);
lfile.push("builder.lock");

let lock_file = match File::create(&lfile) {
Ok(f) => f,
Err(err) => return Err(BuilderError::IoError(lfile, err)),
};

let image_store = ImageStore::new(&root_dir)?;
let container_store = ContainerStore::new(&root_dir)?;
let layer_store = LayerStore::new(&root_dir)?;

Ok(Self {
image_store,
container_store,
layer_store,
lock_file,
_tmp_dir: tmp_dir,
_root_dir: root_dir,
})
}

pub fn image_store(&self) -> &ImageStore {
&self.image_store
}

pub fn container_store(&self) -> &ContainerStore {
&self.container_store
}

pub fn layer_store(&self) -> &LayerStore {
&self.layer_store
}

pub fn lock(&self) -> BuilderResult<()> {
match self.lock_file.lock_exclusive() {
Ok(_) => Ok(()),
Err(err) => Err(BuilderError::BuilderLockError(err)),
}
}

pub fn unlock(&self) -> BuilderResult<()> {
match self.lock_file.unlock() {
Ok(_) => Ok(()),
Err(err) => Err(BuilderError::BuilderLockError(err)),
}
}
}
36 changes: 36 additions & 0 deletions src/builder/reset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::fs;

use crate::error::{BuilderError, BuilderResult};

use super::oci::OCIBuilder;

impl OCIBuilder {
pub fn reset(&self) -> BuilderResult<()> {
self.lock()?;

// remove image store directory content
let istore_path = self.image_store().istore_path();
match fs::remove_dir_all(istore_path) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(istore_path.clone(), err)),
}

// remove container store directory content
let cstore_path = self.container_store().cstore_path();
match fs::remove_dir_all(cstore_path) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(cstore_path.clone(), err)),
}

// remove layer store directory content
let lstore_path = self.layer_store().lstore_path();
match fs::remove_dir_all(lstore_path) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(lstore_path.clone(), err)),
}

self.unlock()?;

Ok(())
}
}
2 changes: 2 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod pull;
pub mod reset;
26 changes: 26 additions & 0 deletions src/commands/pull.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use std::ffi::OsString;

use clap::Parser;
use log::debug;

use crate::{builder, error::BuilderResult, utils};

#[derive(Parser, Debug)]
pub struct Pull {
image_name: String,
}

impl Pull {
pub fn new(image_name: String) -> Self {
Self { image_name }
}

pub fn exec(&self, root_dir: Option<OsString>) -> BuilderResult<()> {
debug!("pulling image...");

let root_dir_path = utils::get_root_dir(root_dir);
let _builder = builder::oci::OCIBuilder::new(root_dir_path)?;

Ok(())
}
}
46 changes: 46 additions & 0 deletions src/commands/reset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::{ffi::OsString, io};

use clap::Parser;
use log::debug;

use crate::{builder, error::BuilderResult, utils};

#[derive(Parser, Debug)]
pub struct Reset {
/// Do not prompt for confirmation
#[clap(short, long)]
force: bool,
}

impl Reset {
pub fn new(force: bool) -> Self {
Self { force }
}

pub fn exec(&self, root_dir: Option<OsString>) -> BuilderResult<()> {
debug!("resetting storage...");

let root_dir_path = utils::get_root_dir(root_dir);
let builder = builder::oci::OCIBuilder::new(root_dir_path)?;

if self.force {
builder.reset()?;

return Ok(());
}

println!("WARNING! this will remove all containers, images and layers.");
println!("Are you sure you want to continue? [y/N]");

let mut user_input = String::new();
io::stdin()
.read_line(&mut user_input)
.expect("Failed to read input");

if user_input.to_lowercase() == "y\n" {
builder.reset()?
}

Ok(())
}
}
1 change: 1 addition & 0 deletions src/container/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod store;
25 changes: 25 additions & 0 deletions src/container/store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::{fs, path::PathBuf};

use crate::error::{BuilderError, BuilderResult};

pub struct ContainerStore {
cstore_path: PathBuf,
}

impl ContainerStore {
pub fn new(root_dir: &PathBuf) -> BuilderResult<Self> {
let mut cstore_path = PathBuf::from(&root_dir);
cstore_path.push("overlay-containers/");

match fs::create_dir_all(&cstore_path) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(cstore_path, err)),
}

Ok(Self { cstore_path })
}

pub fn cstore_path(&self) -> &PathBuf {
&self.cstore_path
}
}
20 changes: 20 additions & 0 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::{io, path::PathBuf};

use thiserror::Error;

pub type BuilderResult<T> = std::result::Result<T, BuilderError>;

#[derive(Debug, Error)]
pub enum BuilderError {
#[error("url {0} parse error: because {1}")]
UrlParseError(String, url::ParseError),

#[error("client call error: {0}")]
ClientCallError(String),

#[error("io error {0}: {1}")]
IoError(PathBuf, io::Error),

#[error("builder lock error: {0}")]
BuilderLockError(io::Error),
}
1 change: 1 addition & 0 deletions src/image/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod store;
25 changes: 25 additions & 0 deletions src/image/store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::{fs, path::PathBuf};

use crate::error::{BuilderError, BuilderResult};

pub struct ImageStore {
istore_path: PathBuf,
}

impl ImageStore {
pub fn new(root_dir: &PathBuf) -> BuilderResult<Self> {
let mut istore_path = PathBuf::from(&root_dir);
istore_path.push("overlay-images/");

match fs::create_dir_all(&istore_path) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(istore_path, err)),
}

Ok(Self { istore_path })
}

pub fn istore_path(&self) -> &PathBuf {
&self.istore_path
}
}
1 change: 1 addition & 0 deletions src/layer/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod store;
25 changes: 25 additions & 0 deletions src/layer/store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::{fs, path::PathBuf};

use crate::error::{BuilderError, BuilderResult};

pub struct LayerStore {
lstore_path: PathBuf,
}

impl LayerStore {
pub fn new(root_dir: &PathBuf) -> BuilderResult<Self> {
let mut lstore_path = PathBuf::from(&root_dir);
lstore_path.push("overlay-layers/");

match fs::create_dir_all(&lstore_path) {
Ok(_) => {}
Err(err) => return Err(BuilderError::IoError(lstore_path, err)),
}

Ok(Self { lstore_path })
}

pub fn lstore_path(&self) -> &PathBuf {
&self.lstore_path
}
}
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod builder;
pub mod commands;
pub mod container;
pub mod error;
pub mod image;
pub mod layer;
pub mod utils;
44 changes: 43 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
use std::ffi::OsString;

use clap::{Parser, Subcommand};
use ocibuilder::commands::reset;

#[derive(Parser, Debug)]
#[clap(version = env!("CARGO_PKG_VERSION"), about)]
struct Opts {
/// Path to storage root directory
#[clap(short, long)]
root: Option<OsString>,

/// ocibuilder commands
#[clap(subcommand)]
subcmd: SubCommand,
}

#[allow(clippy::large_enum_variant)]
#[derive(Subcommand, Debug)]
enum SubCommand {
/// Pull an image from specified registry
// Pull(pull::Pull),

/// Reset local storage
Reset(reset::Reset),
}

fn main() {
println!("Hello, world!");
env_logger::builder().format_timestamp(None).init();

let opts = Opts::parse();
let root_dir = opts.root;

let result = match opts.subcmd {
SubCommand::Reset(reset) => reset.exec(root_dir),
};

match result {
Ok(_) => {}
Err(err) => {
log::error!("{}", err);
std::process::exit(1);
}
}
}
Loading

0 comments on commit a39d0cb

Please sign in to comment.