2023-08-07 09:21:47 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
use anyhow::{anyhow, Result};
|
2023-08-07 08:00:32 +00:00
|
|
|
use axum::extract::{Multipart, State};
|
|
|
|
use bollard::{
|
|
|
|
container::{
|
|
|
|
Config as ContainerConfig, CreateContainerOptions, StartContainerOptions,
|
|
|
|
},
|
|
|
|
image::CreateImageOptions,
|
|
|
|
Docker,
|
|
|
|
};
|
|
|
|
use entity::service;
|
2023-08-07 09:21:47 +00:00
|
|
|
use futures::{FutureExt, TryStreamExt};
|
2023-08-07 08:00:32 +00:00
|
|
|
use sea_orm::{ActiveModelTrait, Set};
|
2023-08-07 09:21:47 +00:00
|
|
|
use tokio::time::sleep;
|
2023-08-07 08:00:32 +00:00
|
|
|
|
|
|
|
use crate::{
|
|
|
|
config::{Config, SourceConfig},
|
|
|
|
error::AppError,
|
2023-08-07 09:21:47 +00:00
|
|
|
jobs::{Job, Schedule},
|
2023-08-07 08:00:32 +00:00
|
|
|
AppState,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub async fn handle_upload_configuration(
|
|
|
|
state: State<AppState>,
|
2023-08-07 09:21:47 +00:00
|
|
|
form: Multipart,
|
2023-08-07 08:00:32 +00:00
|
|
|
) -> Result<(), AppError> {
|
2023-08-07 09:21:47 +00:00
|
|
|
let upload_form = extract_multipart(form).await.unwrap();
|
|
|
|
let config_string = serde_json::to_string(&upload_form.config).unwrap();
|
|
|
|
|
|
|
|
state
|
|
|
|
.tx
|
|
|
|
.send(Job {
|
|
|
|
code: async move {
|
|
|
|
spawn_docker(&upload_form.config).await.unwrap();
|
|
|
|
println!("done with job");
|
2023-08-07 08:00:32 +00:00
|
|
|
}
|
2023-08-07 09:21:47 +00:00
|
|
|
.boxed(),
|
|
|
|
schedule: Schedule::ASAP,
|
|
|
|
})
|
|
|
|
.unwrap();
|
|
|
|
println!("spawned job");
|
|
|
|
|
|
|
|
service::ActiveModel {
|
|
|
|
name: Set(upload_form.name),
|
|
|
|
config: Set(config_string),
|
|
|
|
overall_status: Set("New".into()),
|
|
|
|
..Default::default()
|
|
|
|
}
|
|
|
|
.save(&state.conn)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
struct UploadForm {
|
|
|
|
name: String,
|
|
|
|
config: Config,
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn extract_multipart(mut form: Multipart) -> Result<UploadForm> {
|
|
|
|
let mut name = None;
|
|
|
|
let mut config = None::<Config>;
|
|
|
|
while let Some(field) = form.next_field().await.unwrap() {
|
|
|
|
let key = field.name().unwrap().to_owned();
|
|
|
|
let value =
|
|
|
|
String::from_utf8(field.bytes().await.unwrap().to_vec()).unwrap();
|
|
|
|
match key.as_ref() {
|
|
|
|
"name" => name = Some(value),
|
|
|
|
"config" => config = Some(serde_yaml::from_str(&value).unwrap()),
|
|
|
|
_ => return Err(anyhow!("error").into()),
|
2023-08-07 08:00:32 +00:00
|
|
|
}
|
2023-08-07 09:21:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(UploadForm {
|
|
|
|
name: name.unwrap(),
|
|
|
|
config: config.unwrap(),
|
|
|
|
})
|
|
|
|
}
|
2023-08-07 08:00:32 +00:00
|
|
|
|
2023-08-07 09:21:47 +00:00
|
|
|
async fn spawn_docker(config: &Config) -> Result<()> {
|
2023-08-07 08:00:32 +00:00
|
|
|
println!("Loading config: {config:?}");
|
|
|
|
|
|
|
|
let docker = Docker::connect_with_local_defaults().unwrap();
|
2023-08-07 09:21:47 +00:00
|
|
|
println!("connected to docker {docker:?}");
|
|
|
|
sleep(Duration::from_secs(1)).await;
|
2023-08-07 08:00:32 +00:00
|
|
|
|
2023-08-07 09:21:47 +00:00
|
|
|
for (service_name, service_config) in config.service.iter() {
|
|
|
|
println!("preparing config for {}", service_name);
|
2023-08-07 08:00:32 +00:00
|
|
|
let SourceConfig::Image { image: from_image } = &service_config.source;
|
2023-08-07 09:21:47 +00:00
|
|
|
|
|
|
|
println!("creating image {}", from_image);
|
|
|
|
let mut result_stream = docker.create_image(
|
2023-08-07 08:00:32 +00:00
|
|
|
Some(CreateImageOptions {
|
|
|
|
from_image: from_image.to_owned(),
|
|
|
|
..Default::default()
|
|
|
|
}),
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
);
|
2023-08-07 09:21:47 +00:00
|
|
|
println!("result stream: ");
|
2023-08-07 08:00:32 +00:00
|
|
|
|
2023-08-07 09:21:47 +00:00
|
|
|
while let Ok(Some(v)) = result_stream.try_next().await {
|
|
|
|
println!("v: {v:?}");
|
|
|
|
}
|
2023-08-07 08:00:32 +00:00
|
|
|
println!("completed pulling.");
|
|
|
|
|
|
|
|
// create a container
|
|
|
|
let result = docker
|
|
|
|
.create_container(
|
|
|
|
Some(CreateContainerOptions::<String> {
|
|
|
|
..Default::default()
|
|
|
|
}),
|
|
|
|
ContainerConfig {
|
|
|
|
image: Some(from_image.to_owned()),
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
docker
|
|
|
|
.start_container(&result.id, None::<StartContainerOptions<String>>)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
println!("result: {result:?}");
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|