refactor: externalize container and image base directories
- Add `base_dir` field to `ContainerFactory` - Initialize `base_dir` from `CONTAINERS_DIR` env or user home - Replace hardcoded `/containers` paths with `base_dir` variable - Update image `created_at` retrieval to use `os.stat`
This commit is contained in:
@@ -1,3 +1,16 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.virt.heropods
|
||||
// Initialize factory
|
||||
|
||||
mut factory := heropods.new(
|
||||
reset: false
|
||||
use_podman: true
|
||||
) or { panic('Failed to init ContainerFactory: ${err}') }
|
||||
|
||||
container := factory.new(
|
||||
name: 'myalpine'
|
||||
image: .custom
|
||||
custom_image_name: 'alpine_3_20'
|
||||
docker_url: 'docker.io/library/alpine:3.20'
|
||||
)!
|
||||
|
||||
@@ -36,22 +36,22 @@ pub fn (mut self ContainerFactory) new(args ContainerNewArgs) !&Container {
|
||||
match args.image {
|
||||
.alpine_3_20 {
|
||||
image_name = 'alpine'
|
||||
rootfs_path = '/containers/images/alpine/rootfs'
|
||||
rootfs_path = '${self.base_dir}/images/alpine/rootfs'
|
||||
}
|
||||
.ubuntu_24_04 {
|
||||
image_name = 'ubuntu_24_04'
|
||||
rootfs_path = '/containers/images/ubuntu/24.04/rootfs'
|
||||
rootfs_path = '${self.base_dir}/images/ubuntu/24.04/rootfs'
|
||||
}
|
||||
.ubuntu_25_04 {
|
||||
image_name = 'ubuntu_25_04'
|
||||
rootfs_path = '/containers/images/ubuntu/25.04/rootfs'
|
||||
rootfs_path = '${self.base_dir}/images/ubuntu/25.04/rootfs'
|
||||
}
|
||||
.custom {
|
||||
if args.custom_image_name == '' {
|
||||
return error('custom_image_name is required when using custom image type')
|
||||
}
|
||||
image_name = args.custom_image_name
|
||||
rootfs_path = '/containers/images/${image_name}/rootfs'
|
||||
rootfs_path = '${self.base_dir}/images/${image_name}/rootfs'
|
||||
|
||||
// Check if image exists, if not and docker_url provided, create it
|
||||
if !os.is_dir(rootfs_path) && args.docker_url != '' {
|
||||
@@ -75,7 +75,7 @@ pub fn (mut self ContainerFactory) new(args ContainerNewArgs) !&Container {
|
||||
|
||||
// Create container using crun
|
||||
osal.exec(
|
||||
cmd: 'crun create --bundle /containers/configs/${args.name} ${args.name}'
|
||||
cmd: 'crun create --bundle ${self.base_dir}/configs/${args.name} ${args.name}'
|
||||
stdout: true
|
||||
)!
|
||||
|
||||
@@ -89,7 +89,7 @@ pub fn (mut self ContainerFactory) new(args ContainerNewArgs) !&Container {
|
||||
}
|
||||
|
||||
fn (self ContainerFactory) create_container_config(container_name string, rootfs_path string) ! {
|
||||
config_dir := '/containers/configs/${container_name}'
|
||||
config_dir := '${self.base_dir}/configs/${container_name}'
|
||||
osal.exec(cmd: 'mkdir -p ${config_dir}', stdout: false)!
|
||||
|
||||
// Generate OCI config.json using template
|
||||
|
||||
@@ -10,7 +10,7 @@ import json
|
||||
@[heap]
|
||||
pub struct ContainerImage {
|
||||
pub mut:
|
||||
image_name string @[required] // image is located in /containers/images/<image_name>/rootfs
|
||||
image_name string @[required] // image is located in ${self.factory.base_dir}/images/<image_name>/rootfs
|
||||
docker_url string // optional docker image URL
|
||||
rootfs_path string // path to the extracted rootfs
|
||||
size_mb f64 // size in MB
|
||||
@@ -21,7 +21,7 @@ pub mut:
|
||||
@[params]
|
||||
pub struct ContainerImageArgs {
|
||||
pub mut:
|
||||
image_name string @[required] // image is located in /containers/images/<image_name>/rootfs
|
||||
image_name string @[required] // image is located in ${self.factory.base_dir}/images/<image_name>/rootfs
|
||||
docker_url string // docker image URL like "alpine:3.20" or "ubuntu:24.04"
|
||||
reset bool
|
||||
}
|
||||
@@ -43,7 +43,7 @@ pub mut:
|
||||
// Create new image or get existing
|
||||
pub fn (mut self ContainerFactory) image_new(args ContainerImageArgs) !&ContainerImage {
|
||||
mut image_name := texttools.name_fix(args.image_name)
|
||||
rootfs_path := '/containers/images/${image_name}/rootfs'
|
||||
rootfs_path := '${self.base_dir}/images/${image_name}/rootfs'
|
||||
|
||||
// Check if image already exists
|
||||
if image_name in self.images && !args.reset {
|
||||
@@ -84,7 +84,7 @@ fn (mut self ContainerImage) download_from_docker(docker_url string, reset bool)
|
||||
console.print_header('Downloading image: ${docker_url}')
|
||||
|
||||
// Clean image name for local storage
|
||||
image_dir := '/containers/images/${self.image_name}'
|
||||
image_dir := '${self.factory.base_dir}/images/${self.image_name}'
|
||||
|
||||
// Remove existing if reset is true
|
||||
if reset && os.is_dir(image_dir) {
|
||||
@@ -133,15 +133,15 @@ fn (mut self ContainerImage) update_metadata() ! {
|
||||
self.size_mb = size_str.f64()
|
||||
|
||||
// Get creation time
|
||||
stat_result := osal.exec(cmd: 'stat -c "%Y" ${self.rootfs_path}', stdout: false)!
|
||||
self.created_at = stat_result.output.trim_space() // TODO: should this be ourtime?
|
||||
info := os.stat(self.rootfs_path) or { return error('stat failed: ${err}') }
|
||||
self.created_at = info.ctime.str() // or mtime.str(), depending on what you want
|
||||
}
|
||||
|
||||
// List all available images
|
||||
pub fn (mut self ContainerFactory) images_list() ![]&ContainerImage {
|
||||
mut images := []&ContainerImage{}
|
||||
|
||||
images_base_dir := '/containers/images'
|
||||
images_base_dir := '${self.base_dir}/images'
|
||||
if !os.is_dir(images_base_dir) {
|
||||
return images
|
||||
}
|
||||
@@ -206,7 +206,7 @@ pub fn (mut self ContainerFactory) image_import(args ImageImportArgs) !&Containe
|
||||
|
||||
console.print_header('Importing image from ${args.source_path}')
|
||||
|
||||
image_dir := '/containers/images/${image_name_clean}'
|
||||
image_dir := '${self.base_dir}/images/${image_name_clean}'
|
||||
rootfs_path := '${image_dir}/rootfs'
|
||||
|
||||
// Check if image already exists
|
||||
|
||||
@@ -11,6 +11,7 @@ pub mut:
|
||||
tmux_session string
|
||||
containers map[string]&Container
|
||||
images map[string]&ContainerImage
|
||||
base_dir string
|
||||
}
|
||||
|
||||
@[params]
|
||||
@@ -28,8 +29,10 @@ pub fn new(args FactoryInitArgs) !ContainerFactory {
|
||||
|
||||
fn (mut self ContainerFactory) init(args FactoryInitArgs) ! {
|
||||
// Ensure base directories exist
|
||||
self.base_dir = os.getenv_opt('CONTAINERS_DIR') or { os.home_dir() + '/.containers' }
|
||||
|
||||
osal.exec(
|
||||
cmd: 'mkdir -p /containers/images /containers/configs /containers/runtime'
|
||||
cmd: 'mkdir -p ${self.base_dir}/images ${self.base_dir}/configs ${self.base_dir}/runtime'
|
||||
stdout: false
|
||||
)!
|
||||
|
||||
@@ -70,7 +73,7 @@ fn (mut self ContainerFactory) setup_default_images(reset bool) ! {
|
||||
|
||||
// Load existing images from filesystem into cache
|
||||
fn (mut self ContainerFactory) load_existing_images() ! {
|
||||
images_base_dir := '/containers/images'
|
||||
images_base_dir := '${self.base_dir}/containers/images'
|
||||
if !os.is_dir(images_base_dir) {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user