From 0f095a691d396e116c3c18fc252cb4dde37d449a Mon Sep 17 00:00:00 2001 From: root Date: Tue, 28 Jan 2025 16:17:33 +0100 Subject: [PATCH] feat: add docker installer - Add a new docker installer. - Includes functionality for installing, starting, stopping, and removing docker. Co-authored-by: mariobassem12 Co-authored-by: omda --- examples/installers/docker.vsh | 11 ++ lib/installers/virt/docker/.heroscript | 13 ++ lib/installers/virt/docker/docker.v | 64 -------- lib/installers/virt/docker/docker_actions.v | 106 +++++++++++++ lib/installers/virt/docker/docker_factory_.v | 147 +++++++++++++++++++ lib/installers/virt/docker/docker_model.v | 23 +++ lib/installers/virt/docker/readme.md | 42 ++++++ 7 files changed, 342 insertions(+), 64 deletions(-) create mode 100755 examples/installers/docker.vsh create mode 100644 lib/installers/virt/docker/.heroscript delete mode 100644 lib/installers/virt/docker/docker.v create mode 100644 lib/installers/virt/docker/docker_actions.v create mode 100644 lib/installers/virt/docker/docker_factory_.v create mode 100644 lib/installers/virt/docker/docker_model.v create mode 100644 lib/installers/virt/docker/readme.md diff --git a/examples/installers/docker.vsh b/examples/installers/docker.vsh new file mode 100755 index 00000000..1a0fe523 --- /dev/null +++ b/examples/installers/docker.vsh @@ -0,0 +1,11 @@ +#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.installers.virt.docker as docker_installer + +mut docker := docker_installer.get()! + +// To install +docker.install()! + +// To remove +docker.destroy()! diff --git a/lib/installers/virt/docker/.heroscript b/lib/installers/virt/docker/.heroscript new file mode 100644 index 00000000..09192ecd --- /dev/null +++ b/lib/installers/virt/docker/.heroscript @@ -0,0 +1,13 @@ + +!!hero_code.generate_installer + name:'docker' + classname:'DockerInstaller' + singleton:0 + templates:0 + default:1 + title:'' + supported_platforms:'' + reset:0 + startupmanager:1 + hasconfig:0 + build:0 \ No newline at end of file diff --git a/lib/installers/virt/docker/docker.v b/lib/installers/virt/docker/docker.v deleted file mode 100644 index 5a9bc665..00000000 --- a/lib/installers/virt/docker/docker.v +++ /dev/null @@ -1,64 +0,0 @@ -module docker - -import freeflowuniverse.herolib.osal -import freeflowuniverse.herolib.installers.base -import freeflowuniverse.herolib.ui.console - -// install docker will return true if it was already installed -pub fn install_() ! { - console.print_header('package install install docker') - if core.platform() != .ubuntu { - return error('only support ubuntu for now') - } - - base.install()! - - if !osal.done_exists('install_docker') && !osal.cmd_exists('docker') { - // osal.upgrade()! - osal.package_install('mc,wget,htop,apt-transport-https,ca-certificates,curl,software-properties-common')! - cmd := ' - rm -f /usr/share/keyrings/docker-archive-keyring.gpg - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - apt update - apt-cache policy docker-ce - #systemctl status docker - ' - osal.execute_silent(cmd)! - osal.package_install('docker-ce')! - check()! - osal.done_set('install_docker', 'OK')! - } - console.print_header('docker already done') -} - -pub fn check() ! { - // todo: do a monitoring check to see if it works - cmd := ' - # Check if docker command exists - if ! command -v docker &> /dev/null; then - echo "Error: Docker command-line tool is not installed." - exit 1 - fi - - # Check if Docker daemon is running - if ! pgrep -f "dockerd" &> /dev/null; then - echo "Error: Docker daemon is not running." - exit 1 - fi - - # Run the hello-world Docker container - output=$(docker run hello-world 2>&1) - - if [[ "\$output" == *"Hello from Docker!"* ]]; then - echo "Docker is installed and running properly." - else - echo "Error: Failed to run the Docker hello-world container." - echo "Output: \$output" - exit 1 - fi - - ' - r := osal.execute_silent(cmd)! - console.print_debug(r) -} diff --git a/lib/installers/virt/docker/docker_actions.v b/lib/installers/virt/docker/docker_actions.v new file mode 100644 index 00000000..5b4212b1 --- /dev/null +++ b/lib/installers/virt/docker/docker_actions.v @@ -0,0 +1,106 @@ +module docker + +import freeflowuniverse.herolib.core +import freeflowuniverse.herolib.osal +import freeflowuniverse.herolib.ui.console +import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.installers.ulist + +fn startupcmd() ![]zinit.ZProcessNewArgs { + mut res := []zinit.ZProcessNewArgs{} + res << zinit.ZProcessNewArgs{ + name: 'docker' + cmd: 'dockerd' + } + + return res +} + +fn running() !bool { + console.print_header('Checking if Docker is running') + is_installed := installed() or { + return error('Cannot execute command docker, check if the docker is installed or call the `install()` method: ${err}') + } + + if !is_installed { + return false + } + + // Checking if the docker server responed + cmd := 'docker ps' + osal.execute_stdout(cmd) or { return false } + + console.print_header('Docker is running') + return true +} + +fn start_pre() ! { +} + +fn start_post() ! { +} + +fn stop_pre() ! { +} + +fn stop_post() ! { +} + +//////////////////// following actions are not specific to instance of the object + +// checks if a certain version or above is installed +fn installed() !bool { + console.print_header('Checking if Docker is installed') + cmd := 'docker -v' + osal.execute_stdout(cmd) or { return false } + console.print_header('Docker is installed') + return true +} + +// get the Upload List of the files +fn ulist_get() !ulist.UList { + return ulist.UList{} +} + +// uploads to S3 server if configured +fn upload() ! {} + +fn install() ! { + console.print_header('Installing Docker') + if core.platform()! != .ubuntu { + return error('only support ubuntu for now') + } + + mut cmd := ' + sudo apt-get update -y + sudo apt-get install -y ca-certificates curl + sudo install -m 0755 -d /etc/apt/keyrings + sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + sudo chmod a+r /etc/apt/keyrings/docker.asc + + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "\$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + sudo apt-get update -y +' + + osal.execute_stdout(cmd) or { return error('Cannot install docker due to: ${err}') } + + cmd = 'sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin' + osal.execute_stdout(cmd) or { return error('Cannot install docker due to: ${err}') } + console.print_header('Docker installed sucessfully') +} + +fn destroy() ! { + console.print_header('Removing Docker') + // Uninstall the Docker Engine, CLI, containerd, and Docker Compose packages: + mut cmd := 'sudo apt-get purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras' + osal.execute_stdout(cmd) or { return error('Cannot uninstall docker due to: ${err}') } + + // Images, containers, volumes, or custom configuration files on your host aren't automatically removed. To delete all images, containers, and volumes: + cmd = 'sudo rm -rf /var/lib/docker && sudo rm -rf /var/lib/containerd' + osal.execute_stdout(cmd) or { return error('Cannot uninstall docker due to: ${err}') } + + // Remove source list and keyrings + cmd = 'sudo rm /etc/apt/sources.list.d/docker.list && sudo rm /etc/apt/keyrings/docker.asc' + osal.execute_stdout(cmd) or { return error('Cannot uninstall docker due to: ${err}') } + console.print_header('Docker is removed') +} diff --git a/lib/installers/virt/docker/docker_factory_.v b/lib/installers/virt/docker/docker_factory_.v new file mode 100644 index 00000000..58e91414 --- /dev/null +++ b/lib/installers/virt/docker/docker_factory_.v @@ -0,0 +1,147 @@ + +module docker + +import freeflowuniverse.herolib.ui.console +import freeflowuniverse.herolib.sysadmin.startupmanager +import freeflowuniverse.herolib.osal.zinit +import time + +__global ( + docker_global map[string]&DockerInstaller + docker_default string +) + +/////////FACTORY + +@[params] +pub struct ArgsGet { +pub mut: + name string +} + +pub fn get(args_ ArgsGet) !&DockerInstaller { + return &DockerInstaller{} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { + // unknown + // screen + // zinit + // tmux + // systemd + match cat { + .zinit { + console.print_debug('startupmanager: zinit') + return startupmanager.get(cat: .zinit)! + } + .systemd { + console.print_debug('startupmanager: systemd') + return startupmanager.get(cat: .systemd)! + } + else { + console.print_debug('startupmanager: auto') + return startupmanager.get()! + } + } +} + +pub fn (mut self DockerInstaller) start() ! { + switch(self.name) + if self.running()! { + return + } + + console.print_header('docker start') + + if !installed()! { + install()! + } + + configure()! + + start_pre()! + + for zprocess in startupcmd()! { + mut sm := startupmanager_get(zprocess.startuptype)! + + console.print_debug('starting docker with ${zprocess.startuptype}...') + + sm.new(zprocess)! + + sm.start(zprocess.name)! + } + + start_post()! + + for _ in 0 .. 50 { + if self.running()! { + return + } + time.sleep(100 * time.millisecond) + } + return error('docker did not install properly.') +} + +pub fn (mut self DockerInstaller) install_start(args InstallArgs) ! { + switch(self.name) + self.install(args)! + self.start()! +} + +pub fn (mut self DockerInstaller) stop() ! { + switch(self.name) + stop_pre()! + for zprocess in startupcmd()! { + mut sm := startupmanager_get(zprocess.startuptype)! + sm.stop(zprocess.name)! + } + stop_post()! +} + +pub fn (mut self DockerInstaller) restart() ! { + switch(self.name) + self.stop()! + self.start()! +} + +pub fn (mut self DockerInstaller) running() !bool { + switch(self.name) + + // walk over the generic processes, if not running return + for zprocess in startupcmd()! { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } + } + return running()! +} + +@[params] +pub struct InstallArgs { +pub mut: + reset bool +} + +pub fn (mut self DockerInstaller) install(args InstallArgs) ! { + switch(self.name) + if args.reset || (!installed()!) { + install()! + } +} + +pub fn (mut self DockerInstaller) destroy() ! { + switch(self.name) + self.stop() or {} + destroy()! +} + +// switch instance to be used for docker +pub fn switch(name string) { + docker_default = name +} diff --git a/lib/installers/virt/docker/docker_model.v b/lib/installers/virt/docker/docker_model.v new file mode 100644 index 00000000..86c08bbb --- /dev/null +++ b/lib/installers/virt/docker/docker_model.v @@ -0,0 +1,23 @@ +module docker + +pub const version = '1.14.3' +const singleton = false +const default = true + +// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED +@[heap] +pub struct DockerInstaller { +pub mut: + name string = 'default' +} + +fn obj_init(obj_ DockerInstaller) !DockerInstaller { + // never call get here, only thing we can do here is work on object itself + mut obj := obj_ + return obj +} + +// called before start if done +fn configure() ! { + // mut installer := get()! +} diff --git a/lib/installers/virt/docker/readme.md b/lib/installers/virt/docker/readme.md new file mode 100644 index 00000000..8cb368a3 --- /dev/null +++ b/lib/installers/virt/docker/readme.md @@ -0,0 +1,42 @@ +# docker + +To get started + +```vlang + + +import freeflowuniverse.herolib.installers.something.docker as docker_installer + +heroscript:=" +!!docker.configure name:'test' + password: '1234' + port: 7701 + +!!docker.start name:'test' reset:1 +" + +docker_installer.play(heroscript=heroscript)! + +//or we can call the default and do a start with reset +//mut installer:= docker_installer.get()! +//installer.start(reset:true)! + + + + +``` + +## example heroscript + +```hero +!!docker.configure + homedir: '/home/user/docker' + username: 'admin' + password: 'secretpassword' + title: 'Some Title' + host: 'localhost' + port: 8888 + +``` + +