use serde::{Serialize, Deserialize};
use std::error::Error;
use reqwest::header::HeaderMap;
use std::collections::HashMap;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use serde_json::Value;
use sha256::digest;
pub async fn write_config_json(repositories_url_ip:String,username:String,password:String,image_name:String,image_digest:String) {
let url = format!("{}/v2/{}/blobs/{}",repositories_url_ip.clone(),image_name.clone(),image_digest.clone());
let client = reqwest::Client::new();
let mut headers = HeaderMap::new();
headers.insert("Content-Type", "application/vnd.docker.container.image.v1+json".parse().unwrap());
headers.insert("Accept-Language", "zh-CN,zh;q=0.9,zh-TW;q=0.8,en-US;q=0.7,en;q=0.6".parse().unwrap());
let image_storage_path_1 = image_digest.split(':');
let image_storage_path_2: Vec<&str> = image_storage_path_1.collect();
let image_storage_path_3 = image_storage_path_2[1];
let image_storage_path_4 = format!("{}",image_storage_path_3.clone());
let image_storage_path = format!("/var/lib/AntKing/images/{}",image_storage_path_4);
fs::create_dir_all(image_storage_path.clone()).unwrap();
let path = format!("{}/{}.json",image_storage_path.clone(),image_storage_path_4.clone());
let mut file = File::create(path.clone()).unwrap();
match client.get(url).basic_auth(username,Some(password)).headers(headers).timeout(std::time::Duration::from_secs(5)).send().await {
Ok(r) => {
match r.bytes().await {
Ok(r1) => {
let write_result = file.write(&*r1);
match write_result {
Ok(r2) => {
if r2 > 0 {
let config_json_sha256 = format!("sha256:{}",digest(fs::read_to_string(path.clone()).unwrap()));
if config_json_sha256 == image_digest {
println!("Download image configuration file successfully!")
}else {
println!("Failed to download image configuration file! Reason: sha256 is not match")
}
}else {
println!("The image configuration file is empty!")
}
}
Err(e) => {
println!("Failed to download image configuration file! Reason:{}",e)
}
}
}
_ => {}
}
},
Err(e) => {
println!("Failed to download image configuration file! Reason:{}",e)
}
}
}
pub async fn read_config_json(image_digest:String) -> Value {
let image_storage_path = format!("/var/lib/AntKing/images/{}",image_digest);
let path = format!("{}/{}.json",image_storage_path.clone(),image_digest.clone());
let read_result = fs::read_to_string(path.clone());
match read_result {
Ok(res) => {
let v = serde_json::from_str(&*res);
match v {
Ok(res1) => {
let v1:Value = res1;
v1
}
_ => {
Value::default()
}
}
},
_ => {
Value::default()
}
}
}
#[allow(non_snake_case)]
#[derive(Serialize,Deserialize,Debug,Default)]
pub struct Manifest {
pub architecture: String,
pub config: Config,
pub container: String,
pub container_config: ContainerConfig,
pub created: String,
pub docker_version: String,
pub os: String,
pub rootfs: Rootfs,
}
#[allow(non_snake_case)]
#[derive(Serialize,Deserialize,Debug,Default)]
pub struct Config {
pub AttachStderr: bool,
pub AttachStdin: bool,
pub AttachStdout: bool,
pub Cmd: Vec<String>,
pub Domainname: String,
pub Entrypoint: Vec<String>,
pub Env: Vec<String>,
pub ExposedPorts: HashMap<String,HashMap<String,String>>,
pub Hostname: String,
pub Image: String,
pub Labels: HashMap<String,String>,
pub OnBuild: Option<Vec<String>>,
pub OpenStdin: bool,
pub StdinOnce: bool,
pub StopSignal: String,
pub Tty: bool,
pub User: String,
pub Volumes: Option<HashMap<String,HashMap<String,String>>>,
pub WorkingDir: String,
}
#[allow(non_snake_case)]
#[derive(Serialize,Deserialize,Debug,Default)]
pub struct ContainerConfig {
pub AttachStderr: bool,
pub AttachStdin: bool,
pub AttachStdout: bool,
pub Cmd: Vec<String>,
pub Domainname: String,
pub Entrypoint: Vec<String>,
pub Env: Vec<String>,
pub ExposedPorts: HashMap<String,HashMap<String,String>>,
pub Hostname: String,
pub Image: String,
pub Labels: HashMap<String,String>,
pub OnBuild: Option<Vec<String>>,
pub OpenStdin: bool,
pub StdinOnce: bool,
pub StopSignal: String,
pub Tty: bool,
pub User: String,
pub Volumes: Option<HashMap<String,HashMap<String,String>>>,
pub WorkingDir: String,
}
#[allow(non_snake_case)]
#[derive(Serialize,Deserialize,Debug,Default)]
pub struct Rootfs {
pub diff_ids: Vec<String>,
#[serde(rename(serialize = "type", deserialize = "type"))]
pub type1: String,
}
pub async fn get_config_info(repositories_url_ip:String,username:String,password:String,image_name:String,image_digest:String) -> Result<Manifest, Box<dyn Error>> {
let url = format!("{}/v2/{}/blobs/{}",repositories_url_ip,image_name,image_digest);
let client = reqwest::Client::new();
let mut headers = HeaderMap::new();
headers.insert("Content-Type", "application/vnd.docker.container.image.v1+json".parse().unwrap());
headers.insert("Accept-Language", "zh-CN,zh;q=0.9,zh-TW;q=0.8,en-US;q=0.7,en;q=0.6".parse().unwrap());
match client.get(url).basic_auth(username,Some(password)).headers(headers).timeout(std::time::Duration::from_secs(5)).send().await {
Ok(r) => {
match r.json().await {
Ok(res) => Ok(res),
Err(e) => {
Err(Box::new(e))
}
}
},
Err(e) => {
Err(Box::new(e))
}
}
}