Add container registry pull, image source settings, and global AWS config
All checks were successful
Build Container / build-container (push) Successful in 1m59s
All checks were successful
Build Container / build-container (push) Successful in 1m59s
Support pulling images from registry (default: repo.anhonesthost.net/cybercovellc/triple-c/triple-c-sandbox:latest), local builds, or custom images via a new settings UI. Add global AWS configuration (config path auto-detect, profile picker, region) that serves as defaults overridable per-project for Bedrock auth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use bollard::image::{BuildImageOptions, ListImagesOptions};
|
||||
use bollard::image::{BuildImageOptions, CreateImageOptions, ListImagesOptions};
|
||||
use bollard::models::ImageSummary;
|
||||
use futures_util::StreamExt;
|
||||
use std::collections::HashMap;
|
||||
@@ -10,13 +10,12 @@ use crate::models::container_config;
|
||||
const DOCKERFILE: &str = include_str!("../../../../container/Dockerfile");
|
||||
const ENTRYPOINT: &str = include_str!("../../../../container/entrypoint.sh");
|
||||
|
||||
pub async fn image_exists() -> Result<bool, String> {
|
||||
pub async fn image_exists(image_name: &str) -> Result<bool, String> {
|
||||
let docker = get_docker()?;
|
||||
let full_name = container_config::full_image_name();
|
||||
|
||||
let filters: HashMap<String, Vec<String>> = HashMap::from([(
|
||||
"reference".to_string(),
|
||||
vec![full_name],
|
||||
vec![image_name.to_string()],
|
||||
)]);
|
||||
|
||||
let images: Vec<ImageSummary> = docker
|
||||
@@ -30,14 +29,65 @@ pub async fn image_exists() -> Result<bool, String> {
|
||||
Ok(!images.is_empty())
|
||||
}
|
||||
|
||||
pub async fn pull_image<F>(image_name: &str, on_progress: F) -> Result<(), String>
|
||||
where
|
||||
F: Fn(String) + Send + 'static,
|
||||
{
|
||||
let docker = get_docker()?;
|
||||
|
||||
// Parse image name into from_image and tag
|
||||
let (from_image, tag) = if let Some(pos) = image_name.rfind(':') {
|
||||
// Check that the colon is part of a tag, not a port
|
||||
let after_colon = &image_name[pos + 1..];
|
||||
if after_colon.contains('/') {
|
||||
// The colon is part of a port (e.g., host:port/repo)
|
||||
(image_name, "latest")
|
||||
} else {
|
||||
(&image_name[..pos], after_colon)
|
||||
}
|
||||
} else {
|
||||
(image_name, "latest")
|
||||
};
|
||||
|
||||
let options = CreateImageOptions {
|
||||
from_image,
|
||||
tag,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut stream = docker.create_image(Some(options), None, None);
|
||||
|
||||
while let Some(result) = stream.next().await {
|
||||
match result {
|
||||
Ok(info) => {
|
||||
let mut msg_parts = Vec::new();
|
||||
if let Some(ref status) = info.status {
|
||||
msg_parts.push(status.clone());
|
||||
}
|
||||
if let Some(ref progress) = info.progress {
|
||||
msg_parts.push(progress.clone());
|
||||
}
|
||||
if !msg_parts.is_empty() {
|
||||
on_progress(msg_parts.join(" "));
|
||||
}
|
||||
if let Some(ref error) = info.error {
|
||||
return Err(format!("Pull error: {}", error));
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(format!("Pull stream error: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn build_image<F>(on_progress: F) -> Result<(), String>
|
||||
where
|
||||
F: Fn(String) + Send + 'static,
|
||||
{
|
||||
let docker = get_docker()?;
|
||||
let full_name = container_config::full_image_name();
|
||||
let full_name = container_config::local_build_image_name();
|
||||
|
||||
// Create a tar archive in memory containing Dockerfile and entrypoint.sh
|
||||
let tar_bytes = create_build_context().map_err(|e| format!("Failed to create build context: {}", e))?;
|
||||
|
||||
let options = BuildImageOptions {
|
||||
@@ -71,7 +121,6 @@ fn create_build_context() -> Result<Vec<u8>, std::io::Error> {
|
||||
{
|
||||
let mut archive = tar::Builder::new(&mut buf);
|
||||
|
||||
// Add Dockerfile
|
||||
let dockerfile_bytes = DOCKERFILE.as_bytes();
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_size(dockerfile_bytes.len() as u64);
|
||||
@@ -79,7 +128,6 @@ fn create_build_context() -> Result<Vec<u8>, std::io::Error> {
|
||||
header.set_cksum();
|
||||
archive.append_data(&mut header, "Dockerfile", dockerfile_bytes)?;
|
||||
|
||||
// Add entrypoint.sh
|
||||
let entrypoint_bytes = ENTRYPOINT.as_bytes();
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_size(entrypoint_bytes.len() as u64);
|
||||
@@ -90,7 +138,6 @@ fn create_build_context() -> Result<Vec<u8>, std::io::Error> {
|
||||
archive.finish()?;
|
||||
}
|
||||
|
||||
// Flush to make sure all data is written
|
||||
let _ = buf.flush();
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user