aah/src/upload.rs

133 lines
3.1 KiB
Rust
Raw Normal View History

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(())
}