Skip to content

Commit

Permalink
refactor: begin to avoid autogenerated getters (#235)
Browse files Browse the repository at this point in the history
To prepare for the transition to con4m v2, reduce our usage of
the autogenerated getters from c4autoconf.nim.

The all-encompassing object that c4autoconf.nim defines is ChalkConfig,
which currently looks like:

    type ChalkConfig* = ref object
      `@@attrscope@@`*: AttrScope
      [...]
      attestationConfig*: AttestationConfig
      [...]
      extractConfig*: ExtractConfig
      dockerConfig*: DockerConfig
      execConfig*: ExecConfig
      loadConfig*: LoadConfig
      envConfig*: EnvConfig
      srcConfig*: SrcConfig
      cloudProviderConfig*: CloudProviderConfig
      [...]

As a starting point, refactor away all accesses of ChalkConfig fields
that end in Config (which are those shown above).

That is, with this commit, the following command no longer returns
matches:

    git grep 'chalkConfig\.\w*Config\.'

In con4m v2, we'll be using the lookup proc:

    proc lookup*[T](ctx: RuntimeState, key: string): Option[T]

which is easier to move to from this commit's pattern of:

    get[T](chalkConfig, "foo.bar")

Refs: #214
  • Loading branch information
ee7 authored Mar 28, 2024
1 parent 45ef21d commit 66a5bb4
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 59 deletions.
9 changes: 4 additions & 5 deletions src/attestation/backup.nim
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,11 @@ proc restore(self: Backup,
proc initCallback(this: AttestationKeyProvider) =
let
self = Backup(this)
backupConfig = chalkConfig.attestationConfig.attestationKeyBackupConfig
authName = backupConfig.getAuth()
location = backupConfig.getLocation()
authName = get[string](chalkConfig, "attestation.attestation_key_backup.auth")
location = get[string](chalkConfig, "attestation.attestation_key_backup.location")
authOpt = getAuthConfigByName(authName)
url = backupConfig.getUri().removeSuffix("/")
timeout = cast[int](backupConfig.getTimeout())
url = get[string](chalkConfig, "attestation.attestation_key_backup.uri").removeSuffix("/")
timeout = cast[int](get[Con4mDuration](chalkConfig, "attestation.attestation_key_backup.timeout"))

if authOpt.isNone():
raise newException(ValueError,
Expand Down
3 changes: 1 addition & 2 deletions src/attestation/embed.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ type Embed = ref object of AttestationKeyProvider
proc initCallback(this: AttestationKeyProvider) =
let
self = Embed(this)
embedConfig = chalkConfig.attestationConfig.attestationKeyEmbedConfig
location = embedConfig.getLocation()
location = get[string](chalkConfig, "attestation.attestation_key_embed.location")
self.location = location

proc generateKeyCallback(this: AttestationKeyProvider): AttestationKey =
Expand Down
7 changes: 3 additions & 4 deletions src/attestation/get.nim
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,10 @@ proc request(self: Get, query = ""): JsonNode =
proc initCallback(this: AttestationKeyProvider) =
let
self = Get(this)
getConfig = chalkConfig.attestationConfig.attestationKeyGetConfig
authName = getConfig.getAuth()
authName = get[string](chalkConfig, "attestation.attestation_key_get.auth")
authOpt = getAuthConfigByName(authName)
url = getConfig.getUri().removeSuffix("/")
timeout = cast[int](getConfig.getTimeout())
url = get[string](chalkConfig, "attestation.attestation_key_get.uri").removeSuffix("/")
timeout = cast[int](get[Con4mDuration](chalkConfig, "attestation.attestation_key_get.timeout"))

if authOpt.isNone():
raise newException(ValueError,
Expand Down
2 changes: 1 addition & 1 deletion src/attestation_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ proc canAttest*(): bool =
return cosignKey.canAttest()

proc getProvider(): AttestationKeyProvider =
let name = chalk_common.chalkConfig.attestationConfig.getKeyProvider()
let name = get[string](chalkConfig, "attestation.key_provider")
if name notin keyProviders:
raise newException(KeyError, "Unsupported attestation key provider: " & name)
return keyProviders[name]
Expand Down
24 changes: 12 additions & 12 deletions src/commands/cmd_docker.nim
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ var labelPrefix: string

proc processLabelKey(s: string): string =
once:
labelPrefix = chalkConfig.dockerConfig.getLabelPrefix()
labelPrefix = get[string](chalkConfig, "docker.label_prefix")

result = labelPrefix

Expand All @@ -123,13 +123,13 @@ proc formatLabel(name: string, value: string, addLabel: bool): string =

proc addNewLabelsToDockerFile(ctx: DockerInvocation) =
# First, add totally custom labels.
let labelOps = chalkConfig.dockerConfig.getCustomLabels()
let labelOps = getOpt[TableRef[string, string]](chalkConfig, "docker.custom_labels")

if labelOps.isSome():
for k, v in labelOps.get():
ctx.addedInstructions.add(formatLabel(k, v, true))

let labelTemplName = chalkConfig.dockerConfig.getLabelTemplate()
let labelTemplName = get[string](chalkConfig, "docker.label_template")
if labelTemplName == "":
return

Expand Down Expand Up @@ -231,7 +231,7 @@ proc findProperBinaryToCopyIntoContainer(ctx: DockerInvocation): string =
if targetPlatform == buildPlatform:
return getMyAppPath()

let locOpt = chalkConfig.dockerConfig.getArchBinaryLocations()
let locOpt = getOpt[TableRef[string, string]](chalkConfig, "docker.arch_binary_locations")

if locOpt.isNone():
return noBinaryForPlatform()
Expand Down Expand Up @@ -261,8 +261,8 @@ proc formatChalkExec(args: JsonNode = newJArray()): string =

proc rewriteEntryPoint*(ctx: DockerInvocation) =
let
fromArgs = chalkConfig.execConfig.getCommandNameFromArgs()
wrapCmd = chalkConfig.dockerConfig.getWrapCmd()
fromArgs = get[bool](chalkConfig, "exec.command_name_from_args")
wrapCmd = get[bool](chalkConfig, "docker.wrap_cmd")
(entryPoint, cmd, _) = ctx.getTargetEntrypoints()

if not fromArgs:
Expand Down Expand Up @@ -362,7 +362,7 @@ proc pullValueFromKey(ctx: DockerInvocation, k: string): string =
proc addAnyExtraEnvVars(ctx: DockerInvocation) =
var
toAdd: seq[string] = @[]
map = chalkConfig.dockerConfig.getAdditionalEnvVars()
map = get[TableRef[string, string]](chalkConfig, "docker.additional_env_vars")
value: string

for k, v in map:
Expand All @@ -384,7 +384,7 @@ proc addAnyExtraEnvVars(ctx: DockerInvocation) =
info("Added to Dockerfile: " & newEnvLine)

proc handleTrueInsertion(ctx: DockerInvocation, mark: string) =
if chalkConfig.dockerConfig.getWrapEntryPoint():
if get[bool](chalkConfig, "docker.wrap_entrypoint"):
ctx.rewriteEntryPoint()
ctx.addAnyExtraEnvVars()
ctx.writeChalkMark(mark)
Expand All @@ -403,10 +403,10 @@ proc prepVirtualInsertion(ctx: DockerInvocation) =
# Virtual insertion for Docker does not rewrite the entry point
# either.

if chalkConfig.dockerConfig.getWrapEntryPoint():
if get[bool](chalkConfig, "docker.wrap_entrypoint"):
warn("Cannot wrap entry point in virtual chalking mode.")

let labelOps = chalkConfig.dockerConfig.getCustomLabels()
let labelOps = getOpt[TableRef[string, string]](chalkConfig, "docker.custom_labels")

if labelOps.isSome():
for k, v in labelOps.get():
Expand All @@ -416,7 +416,7 @@ proc prepVirtualInsertion(ctx: DockerInvocation) =
ctx.newCmdLine.add("--label")
ctx.newCmdline.add(k & "=" & escapeJson(v))

let labelTemplName = chalkConfig.dockerConfig.getLabelTemplate()
let labelTemplName = get[string](chalkConfig, "docker.label_template")
if labelTemplName == "":
return

Expand Down Expand Up @@ -568,7 +568,7 @@ template passThroughLogic() =
try:
# Silently pass through other docker commands right now.
exitCode = runCmdNoOutputCapture(exe, args)
if chalkConfig.dockerConfig.getReportUnwrappedCommands():
if get[bool](chalkConfig, "docker.report_unwrapped_commands"):
reporting.doReporting("report")
except:
dumpExOnDebug()
Expand Down
29 changes: 14 additions & 15 deletions src/commands/cmd_exec.nim
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ proc doHeartbeatReport(chalkOpt: Option[ChalkObj]) =

template doHeartbeat(chalkOpt: Option[ChalkObj], pid: Pid, fn: untyped) =
let
inMicroSec = int(chalkConfig.execConfig.getHeartbeatRate())
inMicroSec = int(get[Con4mDuration](chalkConfig, "exec.heartbeat_rate"))
sleepInterval = int(inMicroSec / 1000)

setCommandName("heartbeat")
Expand All @@ -187,17 +187,16 @@ proc runCmdExec*(args: seq[string]) =
return

let
execConfig = chalkConfig.execConfig
fromArgs = execConfig.getCommandNameFromArgs()
cmdPath = execConfig.getSearchPath()
defaults = execConfig.getDefaultArgs()
appendArgs = execConfig.getAppendCommandLineArgs()
overrideOk = execConfig.getOverrideOk()
usePath = execConfig.getUsePath()
pct = execConfig.getReportingProbability()
fromArgs = get[bool](chalkConfig, "exec.command_name_from_args")
cmdPath = get[seq[string]](chalkConfig, "exec.search_path")
defaults = get[seq[string]](chalkConfig, "exec.default_args")
appendArgs = get[bool](chalkConfig, "exec.append_command_line_args")
overrideOk = get[bool](chalkConfig, "exec.override_ok")
usePath = get[bool](chalkConfig, "exec.use_path")
pct = get[int](chalkConfig, "exec.reporting_probability")
ppid = getpid() # Get the current pid before we fork.
var
cmdName = execConfig.getCommandName()
cmdName = get[string](chalkConfig, "exec.command_name")

var argsToPass = defaults

Expand Down Expand Up @@ -239,7 +238,7 @@ proc runCmdExec*(args: seq[string]) =

let pid = fork()

if execConfig.getChalkAsParent():
if get[bool](chalkConfig, "exec.chalk_as_parent"):
if pid == 0:
handleExec(allOpts, argsToPass)
elif pid == -1:
Expand All @@ -254,7 +253,7 @@ proc runCmdExec*(args: seq[string]) =
#
# Yes this is also racy but a proper fix will be more complicated.
let
inMicroSec = int(execConfig.getInitialSleepTime())
inMicroSec = int(get[Con4mDuration](chalkConfig, "exec.initial_sleep_time"))
initialSleep = int(inMicroSec / 1000)

sleep(initialSleep)
Expand All @@ -266,7 +265,7 @@ proc runCmdExec*(args: seq[string]) =
chalkOpt.get().collectRunTimeArtifactInfo()
doReporting()

if execConfig.getHeartbeat():
if get[bool](chalkConfig, "exec.heartbeat"):
chalkOpt.doHeartbeatAsParent(pid)
else:
trace("Waiting for spawned process to exit.")
Expand All @@ -287,7 +286,7 @@ proc runCmdExec*(args: seq[string]) =
trace("Chalk is child process: " & $(cpid))

let
inMicroSec = int(execConfig.getInitialSleepTime())
inMicroSec = int(get[Con4mDuration](chalkConfig, "exec.initial_sleep_time"))
initialSleep = int(inMicroSec / 1000)

sleep(initialSleep)
Expand All @@ -306,5 +305,5 @@ proc runCmdExec*(args: seq[string]) =
chalkOpt.get().collectRunTimeArtifactInfo()
doReporting()

if execConfig.getHeartbeat():
if get[bool](chalkConfig, "exec.heartbeat"):
chalkOpt.doHeartbeatAsChild(ppid)
7 changes: 7 additions & 0 deletions src/config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

## Wrappers for more abstracted accessing of configuration information

from pkg/con4m import get, getOpt
import "."/[run_management, config_version]
export run_management

Expand Down Expand Up @@ -119,3 +120,9 @@ proc getPluginConfig*(name: string): Option[PluginSpec] =

var autoHelp*: string = ""
proc getAutoHelp*(): string = autoHelp

proc get*[T](chalkConfig: ChalkConfig, fqn: string): T =
get[T](chalkConfig.`@@attrscope@@`, fqn)

proc getOpt*[T](chalkConfig: ChalkConfig, fqn: string): Option[T] =
getOpt[T](chalkConfig.`@@attrscope@@`, fqn)
6 changes: 3 additions & 3 deletions src/plugins/cloudMetadata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ proc isAwsEc2Host(vendor: string): bool =
# ref: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html

# older Xen instances
let uuid = tryToLoadFile(chalkConfig.cloudProviderConfig.cloudInstanceHwConfig.getSysHypervisorPath())
let uuid = tryToLoadFile(get[string](chalkConfig, "cloud_provider.cloud_instance_hw_identifiers.sys_hypervisor_path"))
if strutils.toLowerAscii(uuid).startswith("ec2"):
return true

Expand All @@ -143,7 +143,7 @@ proc isAwsEc2Host(vendor: string): bool =

# this will only work if we have root, normally sudo dmidecode --string system-uuid
# gives the same output
let product_uuid = tryToLoadFile(chalkConfig.cloudProviderConfig.cloudInstanceHwConfig.getSysProductPath())
let product_uuid = tryToLoadFile(get[string](chalkConfig, "cloud_provider.cloud_instance_hw_identifiers.sys_product_path"))
if strutils.toLowerAscii(product_uuid).startsWith("ec2"):
return true

Expand All @@ -158,7 +158,7 @@ proc isAzureHost(vendor: string): bool =
proc cloudMetadataGetrunTimeHostInfo*(self: Plugin, objs: seq[ChalkObj]):
ChalkDict {.cdecl.} =
result = ChalkDict()
let vendor = tryToLoadFile(chalkConfig.cloudProviderConfig.cloudInstanceHwConfig.getSysVendorPath())
let vendor = tryToLoadFile(get[string](chalkConfig, "cloud_provider.cloud_instance_hw_identifiers.sys_vendor_path"))

#
# GCP
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/codecDocker.nim
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ proc extractImageMark(chalk: ChalkObj): ChalkDict =
return

else:
if not chalkConfig.extractConfig.getSearchBaseLayersForMarks():
if not get[bool](chalkConfig, "extract.search_base_layers_for_marks"):
return

# We're only going to go deeper if there's no chalk mark found.
Expand Down Expand Up @@ -468,7 +468,7 @@ proc getPartialJsonObject(top: JsonNode, key: string): Option[JsonNode] =
proc jsonAutoKey(map: OrderedTable[string, string],
top: JsonNode,
dict: ChalkDict) =
let reportEmpty = chalkConfig.dockerConfig.getReportEmptyFields()
let reportEmpty = get[bool](chalkConfig, "docker.report_empty_fields")

for jsonKey, chalkKey in map:
let subJsonOpt = top.getPartialJsonObject(jsonKey)
Expand Down
20 changes: 11 additions & 9 deletions src/plugins/codecSource.nim
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ proc sourceScan*(self: Plugin, path: string): Option[ChalkObj] {.cdecl.} =
hasBang = false

if not isExe and isChalkingOp() and
chalkConfig.srcConfig.getOnlyMarkWhenExecuteSet():
get[bool](chalkConfig, "source_marks.only_mark_when_execute_set"):
return none(ChalkObj)

var
Expand All @@ -80,12 +80,13 @@ proc sourceScan*(self: Plugin, path: string): Option[ChalkObj] {.cdecl.} =

if ext != "":
ext = ext[1 .. ^1] # No need for the period.
if ext in chalkConfig.srcConfig.getTextOnlyExtensions():
if ext in get[seq[string]](chalkConfig, "source_marks.text_only_extensions"):
return none(ChalkObj)

if ext in chalkConfig.srcConfig.extensionsToLanguagesMap:
let exts = get[TableRef[string, string]](chalkConfig, "source_marks.extensions_to_languages_map")
if ext in exts:
# We might revise this if there's a shebang line; it takes precidence.
lang = chalkConfig.srcConfig.extensionsToLanguagesMap[ext]
lang = exts[ext]
trace(path & ": By file type, language is: " & lang)

withFileStream(path, mode = fmRead, strict = false):
Expand All @@ -96,7 +97,7 @@ proc sourceScan*(self: Plugin, path: string): Option[ChalkObj] {.cdecl.} =
let bytes = stream.peekStr(2)

if bytes != "#!":
if isChalkingOp() and chalkConfig.srcConfig.getOnlyMarkShebangs():
if isChalkingOp() and get[bool](chalkConfig, "source_marks.only_mark_shebangs"):
return none(ChalkObj)
elif not stream.seemsToBeUtf8():
return none(ChalkObj)
Expand All @@ -110,7 +111,7 @@ proc sourceScan*(self: Plugin, path: string): Option[ChalkObj] {.cdecl.} =
# While we already checked this above, if the shebang was there,
# but was invalid, we'll behave as if it wasn't there at all.
if not hasBang and isChalkingOp() and
chalkConfig.srcConfig.getOnlyMarkShebangs():
get[bool](chalkConfig, "source_marks.only_mark_shebangs"):
return none(ChalkObj)

if lang == "":
Expand All @@ -120,7 +121,7 @@ proc sourceScan*(self: Plugin, path: string): Option[ChalkObj] {.cdecl.} =
# At this point, *if* there's a custom_logic callback, we need to
# call it, otherwise we are done.

let opt = chalkConfig.srcConfig.getCustomLogic()
let opt = getOpt[CallbackObj](chalkConfig, "source_marks.custom_logic")

if opt.isSome():
let
Expand All @@ -130,8 +131,9 @@ proc sourceScan*(self: Plugin, path: string): Option[ChalkObj] {.cdecl.} =
if not proceed:
return none(ChalkObj)

if lang in chalkConfig.srcConfig.languageToCommentMap:
commentPrefix = chalkConfig.srcConfig.languageToCommentMap[lang]
let langs = get[TableRef[string, string]](chalkConfig, "source_marks.language_to_comment_map")
if lang in langs:
commentPrefix = langs[lang]
else:
commentPrefix = "#"

Expand Down
12 changes: 6 additions & 6 deletions src/selfextract.nim
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ proc writeSelfConfig*(selfChalk: ChalkObj): bool
proc testConfigFile*(uri: string, newCon4m: string, params: seq[Box]):
ConfigState =
info(uri & ": Validating configuration.")
if chalkConfig.loadConfig.getValidationWarning():
if get[bool](chalkConfig, "load.validation_warning"):
warn("Note: validation involves creating a new configuration context" &
" and evaluating your code to make sure it at least evaluates " &
"fine on a default path. subscribe() and unsubscribe() will " &
Expand Down Expand Up @@ -279,10 +279,10 @@ proc updateArchBinaries*(newConfig: string, newParams: seq[Box],

if bins != nil:
binInfo = bins
elif not chalkConfig.loadConfig.getUpdateArchBinaries():
elif not get[bool](chalkConfig, "load.update_arch_binaries"):
return
else:
binInfo = chalkConfig.dockerConfig.getArchBinaryLocations().getOrElse(nil)
binInfo = getOpt[typeof(binInfo)](chalkConfig, "docker.arch_binary_locations").get(nil)

if binInfo == nil or len(binInfo) == 0:
trace("No multi-arch binaries to load.")
Expand Down Expand Up @@ -332,8 +332,8 @@ proc handleConfigLoad*(inpath: string) =
path = inpath

let
validate = chalkConfig.loadConfig.getValidateConfigsOnLoad()
replace = chalkConfig.loadConfig.getReplaceConf()
validate = get[bool](chalkConfig, "load.validate_configs_on_load")
replace = get[bool](chalkConfig, "load.replace_conf")
confPaths = chalkConfig.getConfigPath()
confFilename = chalkConfig.getConfigFilename()

Expand Down Expand Up @@ -380,7 +380,7 @@ proc handleConfigLoad*(inpath: string) =
newEmbedded & "\n" & useLine
newEmbedded = withUse.strip()

if chalkConfig.loadConfig.getParamsViaStdin():
if get[bool](chalkConfig, "load.params_via_stdin"):
try:
let
chalkJsonTree = newStringStream(stdin.readLine()).chalkParseJson()
Expand Down

0 comments on commit 66a5bb4

Please sign in to comment.