The guide · how-to
Add a resource to a package
Goal
Declare a new resource in an existing package and implement its check and apply functions in wscript against the host API, so a playbook step can invoke it. You need a playbook that already has a pkgs/<name>/package.wcl. The example adds a file_present resource; substitute your own name, params and script body.
1. Declare the resource and its params
Add a resource block to package.wcl. script is a path relative to the package directory. Declare one param block per input the resource accepts. Every param carries a description and a type, and is either required or has a default. The engine validates each step's properties against these params, so a step that passes an unknown or mistyped property fails validation before anything runs.
resource "file_present" {
description = "Ensure a file exists with the given content"
script = "resources/file_present.ws"
concurrency = "parallel"
param "path" { description = "Absolute path" type = "string" required = true }
param "content" { description = "File content" type = "string" default = "" }
}
concurrency names the class the scheduler uses for this resource. The classes and what they allow to run alongside each other are in package.wcl, and the reasoning is in Scheduling and concurrency.
2. Implement check and apply
Write the script at the path you declared. It exports check(params) and apply(params). Import each host module you use with use. The params value is a map of the step's properties, with defaults filled in.
use value
use fs
use path
// A missing or non-string property is an error the engine reports against the step.
match params.get Some => match v.as_string Some => Ok,
None => Err,
},
None => Err,
}
}
let p = param_str?
if !exists
if read? == param_str? Ok
} else
}
let p = param_str?
mkdir?
write?
Ok
}
The contract
check must never mutate the machine. apply must converge, so that a re-check returns AlreadyConfigured even in a fresh process. A resource that breaks either rule passes validation and fails at the second apply, or in the testlab.
The exact signatures, and the other variants of CheckResult and ApplyResult, are in Script entry points. Every fallible host function returns a Result, so propagate errors with ? and let the engine report them against the step.
To have your editor type-check the script against the real host surface, run config-weave wscripti in the playbook directory. It writes weave.wscripti and a wscript.toml that the wscript language server reads, so a misspelled host function is flagged as you type. config-weave wscripti describes the output.
3. Validate that the script compiles
Run validation. Its final stage compiles every script against the host API, so a wrong signature, an unknown host function or a type error is a hard error here.
$ config-weave validate ./my-playbook
ok: playbook 'My Playbook' v0.1.0 — 2 package(s), 1 play(s), 3 step(s)
Done
config-weave validate exits 0 with the new resource's script compiled. A step can now name it as core.file_present, or as file_present from inside the same package's tests.
Next steps
- Invoke the resource from a step and converge it: Check, then apply.
- Prove it converges and stays converged in a disposable instance: Test a package.
- The host modules a script can import: The host API, with one reference chapter per module starting at fs module.
- The full resource and param field list: package.wcl. The background on packages: Packages, resources and gatherers.