feat: implement and refactor container engine module
This commit introduces a comprehensive implementation and refactoring of the container engine module. Key enhancements include the addition of abstract classes and the implementation of container engines. New features: - Developed `DockerEngine` and `PodmanEngine` classes, deriving from `AbstractContainerEngine` to provide modular functionality. - Added a CLI `--container-runtime` option, allowing users to select their preferred runtime, defaulting to Docker if unspecified. - Introduced a `container_runtime` property in `DocMachine::Build::Config` for improved runtime management. Refactoring: - Refactored code to replace hardcoded Docker commands with method calls to `AbstractContainerEngine`, promoting code reuse and abstraction. Signed-off-by: Glenn Y. Rolland <glenux@glenux.net>
This commit is contained in:
parent
60ab198a69
commit
e59ea9ff44
6 changed files with 328 additions and 69 deletions
|
@ -36,6 +36,10 @@ module DocMachine::Build
|
||||||
config.enable_multiple = true
|
config.enable_multiple = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
opts.on("-r", "--container-runtime RUNTIME", "Container runtime (default docker)") do |runtime|
|
||||||
|
config.container_runtime = runtime
|
||||||
|
end
|
||||||
|
|
||||||
opts.on("-t", "--tty", "Enable TTY mode (needed for shell)") do
|
opts.on("-t", "--tty", "Enable TTY mode (needed for shell)") do
|
||||||
config.enable_tty = true
|
config.enable_tty = true
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
module DocMachine::Build
|
module DocMachine::Build
|
||||||
class Config
|
class Config
|
||||||
property data_dir : String = Dir.current
|
property data_dir : String = Dir.current
|
||||||
|
@ -8,6 +7,7 @@ module DocMachine::Build
|
||||||
property enable_multiple : Bool = false
|
property enable_multiple : Bool = false
|
||||||
property enable_cache : Bool = false
|
property enable_cache : Bool = false
|
||||||
property image_tag : String = "glenux/docmachine:latest"
|
property image_tag : String = "glenux/docmachine:latest"
|
||||||
|
property container_runtime : String = "docker"
|
||||||
|
|
||||||
def initialize(@parent : DocMachine::Config)
|
def initialize(@parent : DocMachine::Config)
|
||||||
end
|
end
|
||||||
|
|
112
src/build/run.cr
112
src/build/run.cr
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
require "path"
|
require "path"
|
||||||
require "file_utils"
|
require "file_utils"
|
||||||
require "socket"
|
require "socket"
|
||||||
|
@ -6,25 +5,46 @@ require "socket"
|
||||||
require "./module"
|
require "./module"
|
||||||
require "./config"
|
require "./config"
|
||||||
require "../common/network"
|
require "../common/network"
|
||||||
|
require "../container/abstract_container_engine"
|
||||||
|
require "../container/docker_engine"
|
||||||
|
require "../container/podman_engine"
|
||||||
|
|
||||||
module DocMachine::Build
|
module DocMachine::Build
|
||||||
class Run
|
class Run
|
||||||
Log = DocMachine::Build::Log.for("run")
|
Log = DocMachine::Build::Log.for("run")
|
||||||
|
|
||||||
|
# Instance variable for the container engine
|
||||||
|
property container_engine : DocMachine::Container::AbstractContainerEngine
|
||||||
|
|
||||||
|
@basehash : String
|
||||||
|
@docker_name : String
|
||||||
|
@docker_opts : Array(String)
|
||||||
|
@process : Process?
|
||||||
|
|
||||||
def initialize(@config : DocMachine::Build::Config)
|
def initialize(@config : DocMachine::Build::Config)
|
||||||
data = "#{@config.data_dir}:#{@config.port}"
|
data = "#{@config.data_dir}:#{@config.port}"
|
||||||
@basehash = Digest::SHA256.hexdigest(data)[0..6]
|
@basehash = Digest::SHA256.hexdigest(data)[0..6]
|
||||||
@docker_name = "docmachine-#{@basehash}"
|
@docker_name = "docmachine-#{@basehash}"
|
||||||
@docker_opts = [] of String
|
@docker_opts = [] of String
|
||||||
@process = nil
|
@process = nil
|
||||||
|
|
||||||
|
# Initialize the container engine based on configuration
|
||||||
|
@container_engine = (
|
||||||
|
if @config.container_runtime == "podman"
|
||||||
|
DocMachine::Container::PodmanEngine.new
|
||||||
|
else
|
||||||
|
DocMachine::Container::DockerEngine.new
|
||||||
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# cleanup environment
|
# Cleanup environment
|
||||||
# create directories
|
# Create directories
|
||||||
# setup permissions
|
# Setup permissions
|
||||||
def prepare()
|
def prepare()
|
||||||
Log.info { "basedir = #{@config.data_dir}" }
|
Log.info { "basedir = #{@config.data_dir}" }
|
||||||
Log.info { "docker_image = #{@config.image_tag}" }
|
Log.info { "container_image = #{@config.image_tag}" }
|
||||||
|
Log.info { "container_runtime = #{@config.container_runtime}" }
|
||||||
Log.info { "action = #{@config.action}" }
|
Log.info { "action = #{@config.action}" }
|
||||||
|
|
||||||
self._pull_image()
|
self._pull_image()
|
||||||
|
@ -33,14 +53,14 @@ module DocMachine::Build
|
||||||
|
|
||||||
private def _avoid_duplicates
|
private def _avoid_duplicates
|
||||||
Log.info { "Multiple Instances: stopping duplicate containers (for #{@docker_name})" }
|
Log.info { "Multiple Instances: stopping duplicate containers (for #{@docker_name})" }
|
||||||
docker_cid = %x{docker ps -f "name=#{@docker_name}" -q}.strip
|
container_id = @container_engine.find_container_id(@docker_name)
|
||||||
|
|
||||||
Log.info { "Multiple Instances: docker_name: #{@docker_name}" }
|
Log.info { "Multiple Instances: container_name: #{@docker_name}" }
|
||||||
Log.info { "Multiple Instances: docker_cid: #{docker_cid || "-"}" }
|
Log.info { "Multiple Instances: container_id: #{container_id || "-"}" }
|
||||||
|
|
||||||
if !docker_cid.empty?
|
if !container_id.empty?
|
||||||
Process.run("docker", ["kill", @docker_name])
|
@container_engine.kill_container(@docker_name)
|
||||||
Process.run("docker", ["rm", @docker_name])
|
@container_engine.remove_container(@docker_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,47 +68,26 @@ module DocMachine::Build
|
||||||
# FIXME: add option to force update
|
# FIXME: add option to force update
|
||||||
data_cache_dir = if ENV["XDG_CACHE_HOME"]?
|
data_cache_dir = if ENV["XDG_CACHE_HOME"]?
|
||||||
Path[ENV["XDG_CACHE_HOME"], "docmachine"]
|
Path[ENV["XDG_CACHE_HOME"], "docmachine"]
|
||||||
else Path[ENV["HOME"], ".cache", "docmachine"]
|
else
|
||||||
|
Path[ENV["HOME"], ".cache", "docmachine"]
|
||||||
end
|
end
|
||||||
|
|
||||||
## Build cache if it doesnt exist
|
## Build cache if it doesn't exist
|
||||||
data_cache_file = data_cache_dir / "image.tar"
|
data_cache_file = data_cache_dir / "image.tar"
|
||||||
Log.info { "Checking cache #{data_cache_file}..." }
|
Log.info { "Checking cache #{data_cache_file}..." }
|
||||||
if !File.exists? data_cache_file.to_s
|
if !File.exists? data_cache_file.to_s
|
||||||
Log.info { "Downloading #{@config.image_tag} image..." }
|
Log.info { "Downloading #{@config.image_tag} image..." }
|
||||||
Process.run("docker", ["pull", @config.image_tag], output: STDOUT)
|
@container_engine.pull_image(@config.image_tag)
|
||||||
Log.info { "Building cache for image (#{data_cache_dir})" }
|
Log.info { "Building cache for image (#{data_cache_dir})" }
|
||||||
FileUtils.mkdir_p(data_cache_dir)
|
FileUtils.mkdir_p(data_cache_dir)
|
||||||
status = Process.run(
|
status = @container_engine.save_image(@config.image_tag, data_cache_file.to_s)
|
||||||
"docker",
|
|
||||||
["image", "save", @config.image_tag, "-o", data_cache_file.to_s],
|
|
||||||
output: STDOUT
|
|
||||||
)
|
|
||||||
if status.success?
|
|
||||||
Log.info { "done" }
|
|
||||||
else
|
else
|
||||||
Log.error { "Unable to save cache image" }
|
Log.info { "Cache already exists. Skipping." }
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
Log.info { "Cache already exist. Skipping." }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if @config.enable_cache
|
if @config.enable_cache
|
||||||
Log.info { "Loading #{@config.image_tag} image from cache..." }
|
Log.info { "Loading #{@config.image_tag} image from cache..." }
|
||||||
docker_image_loaded = false
|
status = @container_engine.load_image(data_cache_file.to_s)
|
||||||
status = Process.run(
|
|
||||||
"docker",
|
|
||||||
["image", "load", "-i", data_cache_file.to_s],
|
|
||||||
output: STDOUT
|
|
||||||
)
|
|
||||||
if status.success?
|
|
||||||
Log.info { "done" }
|
|
||||||
else
|
|
||||||
Log.error { "Unable to load cache image" }
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
Log.info { "Loading #{@config.image_tag} image from local registry..." }
|
Log.info { "Loading #{@config.image_tag} image from local registry..." }
|
||||||
# FIXME: check that local image exists
|
# FIXME: check that local image exists
|
||||||
|
@ -96,35 +95,34 @@ module DocMachine::Build
|
||||||
end
|
end
|
||||||
|
|
||||||
def start()
|
def start()
|
||||||
# start with default uid/gid
|
# Start with default uid/gid
|
||||||
ext_uid = %x{id -u}.strip.to_i
|
ext_uid = %x{id -u}.strip.to_i
|
||||||
ext_gid = %x{id -g}.strip.to_i
|
ext_gid = %x{id -g}.strip.to_i
|
||||||
|
|
||||||
# ...but use subuid/subgid if available
|
# ...but use subuid/subgid if available
|
||||||
File.each_line("/etc/subuid") do |line|
|
File.each_line("/etc/subuid") do |line|
|
||||||
split = line.split(":")
|
split = line.split(":")
|
||||||
next if split[0] != %x{id -u -n}
|
next if split[0] != %x{id -u -n}.strip
|
||||||
|
|
||||||
subuid = split[1].to_i
|
subuid = split[1].to_i
|
||||||
ext_uid += subuid - 1
|
ext_uid += subuid - 1
|
||||||
end
|
end
|
||||||
File.each_line("/etc/subgid") do |line|
|
File.each_line("/etc/subgid") do |line|
|
||||||
split = line.split(":")
|
split = line.split(":")
|
||||||
next if split[0] != %x{id -g -n}
|
next if split[0] != %x{id -g -n}.strip
|
||||||
|
|
||||||
subgid = split[1].to_i
|
subgid = split[1].to_i
|
||||||
ext_gid += subgid - 1
|
ext_gid += subgid - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
Log.info { "ext uid: #{ext_uid}" }
|
Log.info { "ext uid: #{ext_uid}" }
|
||||||
Log.info { "ext cid: #{ext_gid}" }
|
Log.info { "ext gid: #{ext_gid}" }
|
||||||
|
|
||||||
docker_opts = [] of String
|
docker_opts = [] of String
|
||||||
docker_opts << "run"
|
|
||||||
docker_opts << "-i"
|
docker_opts << "-i"
|
||||||
# add tty support
|
# Add tty support
|
||||||
docker_opts << "-t" if @config.enable_tty
|
docker_opts << "-t" if @config.enable_tty
|
||||||
# add container name
|
# Add container name
|
||||||
docker_opts.concat ["--name", @docker_name]
|
docker_opts.concat ["--name", @docker_name]
|
||||||
docker_opts << "--rm"
|
docker_opts << "--rm"
|
||||||
docker_opts << "--shm-size=1gb"
|
docker_opts << "--shm-size=1gb"
|
||||||
|
@ -188,10 +186,17 @@ module DocMachine::Build
|
||||||
docker_opts << @config.action
|
docker_opts << @config.action
|
||||||
|
|
||||||
Log.info {
|
Log.info {
|
||||||
docker_str = ["docker"].concat(docker_opts).join(" ").colorize(:yellow)
|
docker_str = [@config.container_runtime].concat(docker_opts).join(" ").colorize(:yellow)
|
||||||
"Docker: #{docker_str.to_s}"
|
"#{@config.container_runtime.capitalize}: #{docker_str}"
|
||||||
}
|
}
|
||||||
@process = Process.new("docker", docker_opts, input: STDIN, output: STDOUT, error: STDERR)
|
|
||||||
|
@process = @container_engine.run_container(
|
||||||
|
@config.image_tag,
|
||||||
|
@config.action,
|
||||||
|
@docker_name,
|
||||||
|
docker_opts,
|
||||||
|
@config.enable_tty
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def wait()
|
def wait()
|
||||||
|
@ -200,16 +205,9 @@ module DocMachine::Build
|
||||||
|
|
||||||
Signal::INT.trap do
|
Signal::INT.trap do
|
||||||
Log.warn { "Received CTRL-C" }
|
Log.warn { "Received CTRL-C" }
|
||||||
process.signal(Signal::KILL)
|
@container_engine.kill_container(@docker_name)
|
||||||
Process.run("docker", ["kill", @docker_name])
|
|
||||||
end
|
end
|
||||||
process.wait
|
process.wait
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop()
|
|
||||||
end
|
|
||||||
|
|
||||||
def docker_opts()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
41
src/container/abstract_container_engine.cr
Normal file
41
src/container/abstract_container_engine.cr
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
module DocMachine::Container
|
||||||
|
|
||||||
|
class ContainerError < Exception ; end
|
||||||
|
|
||||||
|
class SaveError < ContainerError ; end
|
||||||
|
class KillError < ContainerError ; end
|
||||||
|
class RemoveError < ContainerError ; end
|
||||||
|
class LoadError < ContainerError ; end
|
||||||
|
class RunError < ContainerError ; end
|
||||||
|
class PullError < ContainerError ; end
|
||||||
|
|
||||||
|
abstract class AbstractContainerEngine
|
||||||
|
# Pulls the specified Docker/Podman image
|
||||||
|
abstract def pull_image(image_tag : String) : Nil
|
||||||
|
|
||||||
|
# Loads the Docker/Podman image from a local cache
|
||||||
|
abstract def load_image(cache_path : String) : Nil
|
||||||
|
|
||||||
|
# Saves the Docker/Podman image to a local cache
|
||||||
|
abstract def save_image(image_tag : String, cache_path : String) : Nil
|
||||||
|
|
||||||
|
# Runs a container with the given options
|
||||||
|
abstract def run_container(
|
||||||
|
image_tag : String,
|
||||||
|
action : String,
|
||||||
|
docker_name : String,
|
||||||
|
docker_opts : Array(String),
|
||||||
|
enable_tty : Bool
|
||||||
|
) : Process
|
||||||
|
|
||||||
|
# Kills a running container by name
|
||||||
|
abstract def kill_container(container_name : String) : Nil
|
||||||
|
|
||||||
|
# Removes a container by name
|
||||||
|
abstract def remove_container(container_name : String) : Nil
|
||||||
|
|
||||||
|
# Finds the container ID based on its name
|
||||||
|
abstract def find_container_id(name : String) : String
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
109
src/container/docker_engine.cr
Normal file
109
src/container/docker_engine.cr
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
module DocMachine::Container
|
||||||
|
|
||||||
|
class DockerEngine < AbstractContainerEngine
|
||||||
|
# Pulls the specified Docker image
|
||||||
|
def pull_image(image_tag : String) : Nil
|
||||||
|
Log.info { "Pulling Docker image: #{image_tag}" }
|
||||||
|
status = Process.run("docker", ["pull", image_tag], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully pulled Docker image: #{image_tag}" }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to pull Docker image: #{image_tag}" }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Loads the Docker image from a local cache
|
||||||
|
def load_image(cache_path : String) : Nil
|
||||||
|
Log.info { "Loading Docker image from cache: #{cache_path}" }
|
||||||
|
status = Process.run("docker", ["image", "load", "-i", cache_path], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully loaded Docker image from cache." }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to load Docker image from cache." }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Saves the Docker image to a local cache
|
||||||
|
def save_image(image_tag : String, cache_path : String) : Nil
|
||||||
|
Log.info { "Saving Docker image #{image_tag} to cache at #{cache_path}" }
|
||||||
|
status = Process.run("docker", ["image", "save", image_tag, "-o", cache_path], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully saved Docker image to cache." }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to save Docker image to cache." }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs a Docker container with the given options
|
||||||
|
def run_container(
|
||||||
|
image_tag : String,
|
||||||
|
action : String,
|
||||||
|
docker_name : String,
|
||||||
|
docker_opts : Array(String),
|
||||||
|
enable_tty : Bool
|
||||||
|
) : Process
|
||||||
|
Log.info { "Running Docker container: #{docker_name}" }
|
||||||
|
|
||||||
|
# Construct the full Docker run command
|
||||||
|
cmd = ["docker", "run"] + docker_opts + [image_tag, action]
|
||||||
|
|
||||||
|
# Log the command for debugging
|
||||||
|
Log.debug { "Docker run command: #{cmd.join(" ")}" }
|
||||||
|
|
||||||
|
# Start the Docker container process
|
||||||
|
process = Process.new("docker", ["run"] + docker_opts + [image_tag, action], input: STDIN, output: STDOUT, error: STDERR)
|
||||||
|
|
||||||
|
Log.info { "Docker container #{docker_name} started." }
|
||||||
|
|
||||||
|
process
|
||||||
|
end
|
||||||
|
|
||||||
|
# Kills a running Docker container by name
|
||||||
|
def kill_container(container_name : String) : Nil
|
||||||
|
Log.info { "Killing Docker container: #{container_name}" }
|
||||||
|
status = Process.run("docker", ["kill", container_name], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully killed Docker container: #{container_name}" }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to kill Docker container: #{container_name}" }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Removes a Docker container by name
|
||||||
|
def remove_container(container_name : String) : Nil
|
||||||
|
Log.info { "Removing Docker container: #{container_name}" }
|
||||||
|
status = Process.run("docker", ["rm", container_name], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully removed Docker container: #{container_name}" }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to remove Docker container: #{container_name}" }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Finds the container ID based on its name
|
||||||
|
def find_container_id(name : String) : String
|
||||||
|
Log.info { "Finding Docker container ID for name: #{name}" }
|
||||||
|
output = IO::Memory.new
|
||||||
|
status = Process.run("docker", ["ps", "-f", "name=#{name}", "-q"], output: output, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
container_id = output.to_s.strip
|
||||||
|
Log.info { "Found Docker container ID: #{container_id}" }
|
||||||
|
container_id
|
||||||
|
else
|
||||||
|
Log.error { "Failed to find Docker container ID for name: #{name}" }
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
107
src/container/podman_engine.cr
Normal file
107
src/container/podman_engine.cr
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
module DocMachine::Container
|
||||||
|
|
||||||
|
class PodmanEngine < AbstractContainerEngine
|
||||||
|
# Pulls the specified Podman image
|
||||||
|
def pull_image(image_tag : String) : Nil
|
||||||
|
Log.info { "Pulling Podman image: #{image_tag}" }
|
||||||
|
status = Process.run("podman", ["pull", image_tag], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully pulled Podman image: #{image_tag}" }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to pull Podman image: #{image_tag}" }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Loads the Podman image from a local cache
|
||||||
|
def load_image(cache_path : String) : Nil
|
||||||
|
Log.info { "Loading Podman image from cache: #{cache_path}" }
|
||||||
|
status = Process.run("podman", ["image", "load", "-i", cache_path], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully loaded Podman image from cache." }
|
||||||
|
else
|
||||||
|
Log.error { "Failed to load Podman image from cache." }
|
||||||
|
raise LoadError.new("Failed to load Podman image from cache.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Saves the Podman image to a local cache
|
||||||
|
def save_image(image_tag : String, cache_path : String) : Nil
|
||||||
|
Log.info { "Saving Podman image #{image_tag} to cache at #{cache_path}" }
|
||||||
|
status = Process.run("podman", ["image", "save", image_tag, "-o", cache_path], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully saved Podman image to cache." }
|
||||||
|
else
|
||||||
|
Log.error { "Failed to save Podman image to cache." }
|
||||||
|
raise SaveError.new("Failed to save Podman image to cache.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs a Podman container with the given options
|
||||||
|
def run_container(
|
||||||
|
image_tag : String,
|
||||||
|
action : String,
|
||||||
|
docker_name : String,
|
||||||
|
docker_opts : Array(String),
|
||||||
|
enable_tty : Bool
|
||||||
|
) : Process
|
||||||
|
Log.info { "Running Podman container: #{docker_name}" }
|
||||||
|
|
||||||
|
# Construct the full Podman run command
|
||||||
|
cmd = ["podman", "run"] + docker_opts + [image_tag, action]
|
||||||
|
|
||||||
|
# Log the command for debugging
|
||||||
|
Log.debug { "Podman run command: #{cmd.join(" ")}" }
|
||||||
|
|
||||||
|
# Start the Podman container process
|
||||||
|
process = Process.new("podman", ["run"] + docker_opts + [image_tag, action], input: STDIN, output: STDOUT, error: STDERR)
|
||||||
|
|
||||||
|
Log.info { "Podman container #{docker_name} started." }
|
||||||
|
|
||||||
|
process
|
||||||
|
end
|
||||||
|
|
||||||
|
# Kills a running Podman container by name
|
||||||
|
def kill_container(container_name : String) : Nil
|
||||||
|
Log.info { "Killing Podman container: #{container_name}" }
|
||||||
|
status = Process.run("podman", ["kill", container_name], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully killed Podman container: #{container_name}" }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to kill Podman container: #{container_name}" }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Removes a Podman container by name
|
||||||
|
def remove_container(container_name : String) : Nil
|
||||||
|
Log.info { "Removing Podman container: #{container_name}" }
|
||||||
|
status = Process.run("podman", ["rm", container_name], output: STDOUT, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
Log.info { "Successfully removed Podman container: #{container_name}" }
|
||||||
|
true
|
||||||
|
else
|
||||||
|
Log.error { "Failed to remove Podman container: #{container_name}" }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Finds the container ID based on its name
|
||||||
|
def find_container_id(name : String) : String
|
||||||
|
Log.info { "Finding Podman container ID for name: #{name}" }
|
||||||
|
output = IO::Memory.new
|
||||||
|
status = Process.run("podman", ["ps", "-f", "name=#{name}", "-q"], output: output, error: STDERR)
|
||||||
|
if status.success?
|
||||||
|
container_id = output.to_s.strip
|
||||||
|
Log.info { "Found Podman container ID: #{container_id}" }
|
||||||
|
container_id
|
||||||
|
else
|
||||||
|
Log.error { "Failed to find Podman container ID for name: #{name}" }
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Add table
Reference in a new issue