feat: start of agent code

pull/301/head
Jef Roosens 2022-12-06 13:50:25 +01:00
parent 9e11237ff9
commit 6281ef7607
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 133 additions and 0 deletions

25
src/agent/agent.v 100644
View File

@ -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()
}

31
src/agent/cli.v 100644
View File

@ -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<Config>(prefix: 'VIETER_', default_path: config_file)!
agent(conf)!
}
}
}

65
src/agent/daemon.v 100644
View File

@ -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
}

View File

@ -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

View File

@ -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()