Skip to content

Commit

Permalink
config mod
Browse files Browse the repository at this point in the history
  • Loading branch information
RCmerci committed Jan 20, 2019
1 parent 168a14d commit efd4483
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 19 deletions.
168 changes: 160 additions & 8 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ edition = "2018"
db = { path = "db" }
dockerclient = { path = "dockerclient"}
front = { path = "front" }
clap = "2.32.0"
config = { path = "config" }
clap = "2.32.0"
dirs = "1.0.4"
85 changes: 85 additions & 0 deletions config/Cargo.lock

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

10 changes: 10 additions & 0 deletions config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "config"
version = "0.1.0"
authors = ["RCmerci <[email protected]>"]
edition = "2018"

[dependencies]
serde_json = "1.0"
serde = "1.0.85"
serde_derive = "1.0.85"
18 changes: 18 additions & 0 deletions config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use serde_json::from_str;

#[derive(Serialize, Deserialize)]
pub struct Config {
pub server: String,
pub username: String,
pub password: String,
pub image_name: String,
}

pub fn get_config<P: AsRef<std::path::Path>>(path: P) -> Config {
let config_file = std::fs::read_to_string(path).unwrap();
let config: Config = from_str(&config_file).unwrap();
config
}
28 changes: 27 additions & 1 deletion db/src/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ pub struct ImageDrive {

impl ImageDrive {
pub fn new(image_name: &str, server: &str, username: &str, password: &str) -> ImageDrive {
let dockercli = dockerclient::DockerClient::new_with_logininfo(server, username, password);
let dockercli = dockerclient::DockerClient::new_with_logininfo(
Some(server),
Some(username),
Some(password),
);
ImageDrive {
image_name: image_name.to_string(),
dockercli: dockercli,
Expand Down Expand Up @@ -138,10 +142,32 @@ impl DB<Error> for ImageDrive {
// TODO: check image exist, if not , pull from registry

// image existed, so push to registry

// 1. commit all changed data in container to image
let c = get_or_run(&self.dockercli, &self.image_name)?;
if self.dockercli.diff_container_image_content(&c.id) {
let _ = self
.dockercli
.commit(&c.id, "commit by sync", &self.image_name)
.map_err(Error::DockerError)?;
}

// 2. push image
self.dockercli
.push(&self.image_name)
.map_err(Error::DockerError)
}

fn sync_from_remote(&self) -> Result<(), Error> {
let _ = self
.dockercli
.remove_image(&self.image_name)
.map_err(Error::DockerError);

self.dockercli
.pull(&self.image_name)
.map_err(Error::DockerError)
}
}

fn get_or_run(
Expand Down
2 changes: 2 additions & 0 deletions db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ where
/// sync local DB to remote DB
/// or sync remote DB to local DB if localDB not exists
fn sync(&self) -> Result<(), E>;
/// sync remote DB to local DB even localDB exists, so it will overwrite localDB
fn sync_from_remote(&self) -> Result<(), E>;
}
85 changes: 79 additions & 6 deletions dockerclient/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum Error {
CopyError(String),
PushError(String),
LoginError(String),
RemoveImageError(String),
DefaultError(String),
}

Expand All @@ -35,11 +36,15 @@ impl DockerClient {
}
}

pub fn new_with_logininfo(server: &str, username: &str, password: &str) -> Self {
pub fn new_with_logininfo(
server_: Option<&str>,
username_: Option<&str>,
password_: Option<&str>,
) -> Self {
let inner_cli = shiplift::Docker::new();
let server = Some(server.into());
let username = Some(username.into());
let password = Some(password.into());
let server = server_.map(String::from);
let username = username_.map(String::from);
let password = password_.map(String::from);
DockerClient {
inner_cli,
server,
Expand Down Expand Up @@ -180,6 +185,20 @@ impl DockerClient {
tokio_core::reactor::Core::new().unwrap().run(fut)
}

pub fn remove_image(&self, image: &str) -> Result<(), Error> {
let cmd = format!("docker rmi {}", image);
let r = std::process::Command::new("sh")
.arg("-c")
.arg(cmd)
.output()
.map_err(|e| Error::DefaultError(e.to_string()))?;
if !r.status.success() {
let errstr = String::from_utf8_lossy(&r.stderr).to_string();
return Err(Error::RemoveImageError(errstr));
}
Ok(())
}

pub fn squash(&self, image: &str, new_image: &str) -> Result<(), Error> {
let c = self.create(image)?;
let cmd = format!("docker export {} | docker import - {}", &c.id, new_image);
Expand All @@ -197,13 +216,14 @@ impl DockerClient {
Ok(())
}

pub fn push(&self, image: &str) -> Result<(), Error> {
let cmd = format!("docker push {}", image);
pub fn pull(&self, image: &str) -> Result<(), Error> {
let cmd = format!("docker pull {}", image);
let r = std::process::Command::new("sh")
.arg("-c")
.arg(&cmd)
.status()
.map_err(|e| Error::DefaultError(e.to_string()))?;

if r.success() {
return Ok(());
}
Expand All @@ -230,6 +250,54 @@ impl DockerClient {
} else if !r.success() {
return Err(Error::PushError(format!("code: {:?}", r.code())));
}
// login succ, retry pull
std::process::Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.map_err(|e| Error::DefaultError(e.to_string()))
.and_then(|r| {
if !r.status.success() {
let errstr = String::from_utf8_lossy(&r.stderr).to_string();
return Err(Error::PushError(errstr));
}
Ok(())
})
}

pub fn push(&self, image: &str) -> Result<(), Error> {
let cmd = format!("docker push {}", image);
let r = std::process::Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.map_err(|e| Error::DefaultError(e.to_string()))?;
if r.status.success() {
return Ok(());
}
if (!r.status.success())
&& self.server.is_some()
&& self.username.is_some()
&& self.password.is_some()
{
let login_cmd = format!(
"docker login {} --username={} --password={}",
self.server.as_ref().unwrap(),
self.username.as_ref().unwrap(),
self.password.as_ref().unwrap()
);
let output = std::process::Command::new("sh")
.arg("-c")
.arg(login_cmd)
.output()
.map_err(|e| Error::DefaultError(e.to_string()))?;
if !output.status.success() {
let errstr = String::from_utf8_lossy(&output.stderr).to_string();
return Err(Error::LoginError(errstr));
}
} else if !r.status.success() {
return Err(Error::PushError(format!("code: {:?}", r.status.code())));
}

// login succ, retry push

Expand All @@ -246,6 +314,11 @@ impl DockerClient {
Ok(())
})
}

/// return true if container's content is different with its image.
pub fn diff_container_image_content(&self, _container: &str) -> bool {
true
}
}

fn copy(
Expand Down
13 changes: 10 additions & 3 deletions front/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,19 @@ pub fn put(db: &ImageDrive, entry: &str, item: &str) {
pub fn export(db: &ImageDrive, entry: &str, dstdir: &str) {
match db.export_to_dir(Path::new(dstdir), entry) {
Err(e) => println!("export entry fail: {:?}", e),
Ok(r) => println!("{:?}", r),
Ok(_) => println!("export entry '{}' successfully", entry),
}
}

pub fn sync(db: &ImageDrive) {
db.sync();
pub fn sync(db: &ImageDrive, from_remote: bool) {
match if from_remote {
db.sync_from_remote()
} else {
db.sync()
} {
Err(e) => println!("sync fail: {:?}", e),
Ok(_) => println!("sync localDB to remoteDB successfully"),
}
}

#[cfg(test)]
Expand Down

0 comments on commit efd4483

Please sign in to comment.