From 6281ef76070f1ccf7b2bed05e06f9ca7cdf5322c Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 6 Dec 2022 13:50:25 +0100 Subject: [PATCH] feat: start of agent code --- src/agent/agent.v | 25 ++++++++++++++++++ src/agent/cli.v | 31 ++++++++++++++++++++++ src/agent/daemon.v | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/build/build.v | 10 +++++++ src/main.v | 2 ++ 5 files changed, 133 insertions(+) create mode 100644 src/agent/agent.v create mode 100644 src/agent/cli.v create mode 100644 src/agent/daemon.v diff --git a/src/agent/agent.v b/src/agent/agent.v new file mode 100644 index 0000000..3affd21 --- /dev/null +++ b/src/agent/agent.v @@ -0,0 +1,25 @@ +module agent + +import log +import os + +const log_file_name = 'vieter.agent.log' + +// agent start an agent service +pub fn agent(conf Config) ! { + // Configure logger + log_level := log.level_from_tag(conf.log_level) or { + return error('Invalid log level. The allowed values are FATAL, ERROR, WARN, INFO & DEBUG.') + } + + mut logger := log.Log{ + level: log_level + } + + log_file := os.join_path_single(conf.data_dir, agent.log_file_name) + logger.set_full_logpath(log_file) + logger.log_to_console_too() + + mut d := agent.agent_init(logger, conf) + d.run() +} diff --git a/src/agent/cli.v b/src/agent/cli.v new file mode 100644 index 0000000..46942ec --- /dev/null +++ b/src/agent/cli.v @@ -0,0 +1,31 @@ +module agent + +import cli +import conf as vconf + +struct Config { +pub: + log_level string = 'WARN' + api_key string + address string + data_dir string + max_concurrent_builds int = 1 + polling_frequency int = 30 + // Architecture of agent + /* arch string */ + /* image_rebuild_frequency int = 1440 */ +} + +// cmd returns the cli module that handles the cron daemon. +pub fn cmd() cli.Command { + return cli.Command{ + name: 'agent' + description: 'Start an agent service & start polling for new builds.' + execute: fn (cmd cli.Command) ! { + config_file := cmd.flags.get_string('config-file')! + conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! + + agent(conf)! + } + } +} diff --git a/src/agent/daemon.v b/src/agent/daemon.v new file mode 100644 index 0000000..389a148 --- /dev/null +++ b/src/agent/daemon.v @@ -0,0 +1,65 @@ +module agent + +import log +import sync.stdatomic +import build { BuildConfig } +import client + +const ( + build_empty = 0 + build_running = 1 + build_done = 2 +) + +struct AgentDaemon { + logger shared log.Log + conf Config + // Which builds are currently running; length is same as + // conf.max_concurrent_builds + builds []BuildConfig + // Atomic variables used to detect when a build has finished; length is the + // same as conf.max_concurrent_builds + client client.Client + atomics []u64 +} + +fn agent_init(logger log.Log, conf Config) AgentDaemon { + mut d := AgentDaemon{ + logger: logger + client: client.new(conf.address, conf.api_key) + conf: conf + builds: []BuildConfig{len: conf.max_concurrent_builds} + atomics: []u64{len: conf.max_concurrent_builds} + } + + return d +} + +pub fn (mut d AgentDaemon) run() { + for { + free_builds := d.update_atomics() + + if free_builds > 0 { + + } + + } +} + +// clean_finished_builds checks for each build whether it's completed, and sets +// it to free again if so. The return value is how many fields are now set to +// free. +fn (mut d AgentDaemon) update_atomics() int { + mut count := 0 + + for i in 0 .. d.atomics.len { + if stdatomic.load_u64(&d.atomics[i]) == agent.build_done { + stdatomic.store_u64(&d.atomics[i], agent.build_empty) + count++ + } else if stdatomic.load_u64(&d.atomics[i]) == agent.build_empty { + count++ + } + } + + return count +} diff --git a/src/build/build.v b/src/build/build.v index 247df6e..b7c5cb6 100644 --- a/src/build/build.v +++ b/src/build/build.v @@ -16,6 +16,16 @@ const ( '/usr/local/bin', '/usr/bin/site_perl', '/usr/bin/vendor_perl', '/usr/bin/core_perl'] ) +pub struct BuildConfig { +pub: + id int + kind string + url string + branch string + repo string + base_image string +} + // create_build_image creates a builder image given some base image which can // then be used to build & package Arch images. It mostly just updates the // system, install some necessary packages & creates a non-root user to run diff --git a/src/main.v b/src/main.v index fc09f7e..424e328 100644 --- a/src/main.v +++ b/src/main.v @@ -9,6 +9,7 @@ import console.schedule import console.man import console.aur import cron +import agent fn main() { mut app := cli.Command{ @@ -40,6 +41,7 @@ fn main() { schedule.cmd(), man.cmd(), aur.cmd(), + agent.cmd() ] } app.setup()