use anyhow::anyhow; use axum::extract::{Multipart, State}; use bollard::{ container::{ Config as ContainerConfig, CreateContainerOptions, StartContainerOptions, }, image::CreateImageOptions, Docker, }; use entity::service; use futures::TryStreamExt; use sea_orm::{ActiveModelTrait, Set}; use crate::{ config::{Config, SourceConfig}, error::AppError, AppState, }; pub async fn handle_upload_configuration( state: State, mut form: Multipart, ) -> Result<(), AppError> { let (name, config) = { let mut name = None; let mut config = None::; 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()), } } (name.unwrap(), config.unwrap()) }; println!("Loading config: {config:?}"); let docker = Docker::connect_with_local_defaults().unwrap(); for (_service_name, service_config) in config.service.iter() { let SourceConfig::Image { image: from_image } = &service_config.source; let result_stream = docker.create_image( Some(CreateImageOptions { from_image: from_image.to_owned(), ..Default::default() }), None, None, ); result_stream .try_for_each(|x| async move { println!("{x:?}"); Ok(()) }) .await .unwrap(); println!("completed pulling."); // create a container let result = docker .create_container( Some(CreateContainerOptions:: { ..Default::default() }), ContainerConfig { image: Some(from_image.to_owned()), ..Default::default() }, ) .await .unwrap(); docker .start_container(&result.id, None::>) .await .unwrap(); println!("result: {result:?}"); } service::ActiveModel { name: Set(name), config: Set(serde_json::to_string(&config).unwrap()), ..Default::default() } .save(&state.conn) .await .unwrap(); Ok(()) }