Resources and Resource Types
Resources are rich objects in JSON that allow to store configuration and credentials.
In Windmill, Resources represent connections to third party systems. Resources are a good way to define a connection to a frequently used third party system such as a database. Think of Resources as a structured way to store configuration and credentials, and access them from scripts.
Each Resource has a Resource Type (RT for short) - for example MySQL, MongoDB, OpenAI, etc. - that defines the schema that the resource of this type needs to implement. Schemas implement the JSON Schema specification.
Check our list of integrations (or, pre-made resource types). If one is missing, this very page details how to create your own.
Create a Resource
To create a resource using an existing type, go to the Resources page and click "Add a resource/API".
Just like most objects in Windmill, Resources have a path that define their permissions - see ownership path prefix.
Each Resource has a Resource Type, that defines what fields that resource contains. Select one from the list and check the schema to see what fields are present.
Resources commonly need to access secrets or re-use
Variables, for example passwords or API
tokens. To insert a Variable into a Resource, use Insert variable (the $
sign button) and select a Variable. The name of a Variable will look like
$VAR:<NAME_OF_VAR>
. When resources are called from a Script, the Variable
reference will be replaced by its value.
It's a good practice to link a script template to Resources, so that users can easily get started with it. You can use markdown in the description field to add a link, for example:
[example script with this resource](/scripts/add?template=script/template/path)
Create a Resource Type
Windmill comes preloaded with some common Resource Types, such as databases, apps, SMTP, etc. You can see the full list on Windmill Hub. You can also add custom Resource Types by clicking "Add a resource type" on the Resources page.
Use the "Add Property" button to add a field to the resource type. You can specify constraints for the field (a type, making it mandatory, specifying a default, etc). You can also view the schema by toggling the "As JSON" option:
States
In Windmill, states are considered as resources, but they are excluded from the Workspace tab for clarity. They are displayed on the Resources menu, under a dedicated tab.
States are used by scripts to keep data persistent between runs of the same script by the same trigger (schedule or user).
A state is an object stored as a resource of the resource type state
which is meant to persist across distinct executions of the same script.
This is what enables Flows to watch for changes in most event watching scenarios. The pattern is as follows:
- Retrieve the last state or, if undefined, assume it is the first execution.
- Retrieve the current state in the external system you are watching, e.g. the list of users having starred your repo or the maximum ID of posts on Hacker News.
- Calculate the difference between the current state and the last internal state. This difference is what you will want to act upon.
- Set the new state as the current state so that you do not process the elements you just processed.
- Return the differences calculated previously so that you can process them in the next steps. You will likely want to forloop over the items and trigger one Flow per item. This is exactly the pattern used when your Flow is in the mode of "Watching changes regularly".
The convenience functions do this are:
TypeScript
getState()
which retrieves an object of any type (internally a simple Resource) at a path determined bygetStatePath
, which is unique to the user currently executing the Script, the Flow in which it is currently getting called in - if any - and the path of the Script.setState(value: any)
which sets the new state.
Please note it requires importing the wmill client library from Deno/Bun.
Python
get_state()
which retrieves an object of any type (internally a simple Resource) at a path determined byget_state_path
, which is unique to the user currently executing the Script, the Flow in which it is currently getting called in - if any - and the path of the Script.set_state(value: Any)
which sets the new state.
Please note it requires importing the wmill client library from Python.
Using Resources
There are 2 main ways resources are used within scripts:
Passing resources as parameters to scripts (prefered)
Provided you have the right permissions and the resource type exists in the workspace, you can access resources from scripts, flows and apps using the Windmill client. For example, to access the u/user/my_postgresql
resource of the posgtgresql
Resource Type we would create a script.
Typescript:
type Postgresql = object;
// OR one can fully type it
type Postgresql = {
host: string;
port: number;
user: string;
dbname: string;
sslmode: string;
password: string;
};
export async function main(postgres: Postgresql) {
// Use Resource...
}
Python:
postgresql = dict
def main(postgres: postgresql):
# Use Resource...
And then select the Resource in the arguments section on the right:
You can also edit the Resource or even create a new one right from the Code editor.
Fetching them from within a script by using the wmill client in the respective language
By clicking on + Resource
, you'll get to pick a resource from your workspace and be able to fetch it from within the script.
Typescript:
wmill.getResource('u/user/foo');
Python:
wmill.get_resource("u/user/foo")
Go:
wmill.GetResource("u/user/foo")
Bash:
curl -s -H "Authorization: Bearer $WM_TOKEN" \
"$BASE_INTERNAL_URL/api/w/$WM_WORKSPACE/resources/get/u/user/foo" \
| jq -r .value