Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Daemon mode #424

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/chalk.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ when isMainModule:
of "docker": runCmdDocker(getArgs())
of "exec": runCmdExec(getArgs())
of "setup": runCmdSetup()
of "daemon": runCmdDaemon()
of "docgen": runChalkDocGen() # in cmd_help
of "__.onbuild": runCmdOnBuild() # in cmd_internal
else:
Expand Down
4 changes: 2 additions & 2 deletions src/commands.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@

import commands/[cmd_insert, cmd_extract, cmd_delete, cmd_docker, cmd_exec,
cmd_env, cmd_dump, cmd_load, cmd_version, cmd_setup, cmd_help,
cmd_internal]
cmd_internal, cmd_daemon]
export cmd_insert, cmd_extract, cmd_delete, cmd_docker, cmd_exec, cmd_env,
cmd_dump, cmd_load, cmd_version, cmd_setup, cmd_help, cmd_internal
cmd_dump, cmd_load, cmd_version, cmd_setup, cmd_help, cmd_internal, cmd_daemon
47 changes: 47 additions & 0 deletions src/commands/cmd_daemon.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
##
## Copyright (c) 2024, Crash Override, Inc.
##
## This file is part of Chalk
## (see https://crashoverride.com/docs/chalk)
##

##
## chalk `daemon` command
##

import os, std/posix
import ".."/[config, util, reporting]

# this const is not available in nim stdlib hence manual c import
var TIOCNOTTY {.importc, header: "sys/ioctl.h"}: cuint

proc daemon(period: int) =
while true:
doReporting()
sleep period

proc runCmdDaemon*() =
let
period = get[int](getChalkScope(), "daemon.period")

let pid = fork()
if pid == -1:
error("Could not spawn daemon process.")
setExitCode(1)
if pid != 0:
quit()

let is_err = setpgid(0, 0)
if is_err == -1:
setExitCode(1)
error("Chalk couldn't reset the process group: $1" % [$strerror(errno)])
quit()

if isatty(0) != 0:
let is_err = ioctl(0, TIOCNOTTY)
if is_err == -1:
setExitCode(1)
error("Error on disconnecting from tty: $1" % [$strerror(errno)])

# loop forever
daemon(period)
13 changes: 13 additions & 0 deletions src/con4mfuncs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ proc c4mParseJson(args: seq[Box], unused = ConfigState(nil)): Option[Box] =
proc dockerExe(args: seq[Box], unused = ConfigState(nil)): Option[Box] =
return some(pack(getDockerExeLocation()))

proc c4mParseInt(args: seq[Box], unused = ConfigState(nil)): Option[Box] =
let
data = unpack[string](args[0])
try:
result = some(pack(parseInt(data)))
except:
result = none(Box)

let chalkCon4mBuiltins* = [
("version() -> string",
BuiltinFn(getExeVersion),
Expand Down Expand Up @@ -182,6 +190,11 @@ Generally, these can get very noisy, and are intended more for testing,
debugging, etc.
""",
@["chalk"]),
("parseInt(string) -> int",
BuiltinFn(c4mParseInt),
"Parses an int from a string",
@["chalk"]
),
("command_argv() -> list[string]",
BuiltInFn(getArgvLocal),
"""
Expand Down
2 changes: 2 additions & 0 deletions src/configs/base_init.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ exec {
# TODO Remove all sections below
# Currently, these need to be here for singleton defaults to take hold.

daemon { }

extract { }

source_marks { }
Expand Down
4 changes: 4 additions & 0 deletions src/configs/base_outconf.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ outconf heartbeat {
report_template: "report_default"
}

outconf daemon {
report_template: "report_default"
}

outconf delete {
report_template: "report_default"
}
Expand Down
20 changes: 19 additions & 1 deletion src/configs/chalk.c42spec
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ default_key_priority := 4611686018427387904 # 2^62.
# These are the valid command-line commands.
valid_chalk_cmds := ["help", "insert", "extract", "delete", "config",
"load", "dump", "docker", "version", "env", "exec",
"setup", "docgen", "__"]
"daemon", "setup", "docgen", "__"]

all_cmds_that_insert := ["insert", "build", "push", "load", "setup"]

Expand Down Expand Up @@ -2197,6 +2197,23 @@ final report, if the monitored process has exited.
}
}

singleton daemon {
gen_fieldname: "daemonConfig"
gen_typename: "DaemonConfig"
gen_setters: false
user_def_ok: false

field period {
type: int
default: 5000
shortdoc: "How often the daemon should wake and process in milliseconds"
doc: """
The chalk daemon will sleep for this amount of time before reporting on the host
"""

}
}

singleton env_config {
gen_fieldname: "envConfig"
gen_typename: "EnvConfig"
Expand Down Expand Up @@ -2624,6 +2641,7 @@ root {
allow extract
allow docker
allow exec
allow daemon
allow load
allow env_config
allow source_marks
Expand Down
24 changes: 24 additions & 0 deletions src/configs/getopts.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,21 @@ The named reporting template must already exist in your configuration.
"""
}
}

command daemon {
aliases: []
args: (0, high())
shortdoc: "Run in daemon mode"

flag_arg period {
aliases: ["p"]
callback: func set_daemon_period
doc: """
How long the daemon will sleep before submitting a new report in milliseconds
"""
}
}

command config {
aliases: []
shortdoc: "Show configuration variables and settings"
Expand Down Expand Up @@ -786,3 +801,12 @@ func set_artifact_search_path(args: list[string]) {
func on_conf_load(args: list[string]) {
add_override("artifact_search_path", [program_path() + "/" + program_name()])
}

func set_daemon_period(period: string) {
val := parseInt(period)
if val > 0 {
add_override("daemon.period", val)
return ""
}
return "Not a valid argument for period"
}
Loading