Skip to content

Commit e11063d

Browse files
feat!: Adds custom dispenser configuration format
* feat: Adds dispenser specific format * Fixes issue with volume mounting * Adds resource constraints * Adds delay * Adds network declaration in dispenser.toml * Adds support for full config validation * Adds missing fields from service
1 parent 7dc021d commit e11063d

39 files changed

+4030
-1195
lines changed

CLI.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# CLI Reference
2+
3+
This document describes all available command-line options for Dispenser.
4+
5+
## Usage
6+
7+
```sh
8+
dispenser [OPTIONS]
9+
```
10+
11+
## Options
12+
13+
### `-c, --config <PATH>`
14+
15+
Specify the path to the configuration file.
16+
17+
**Default:** `dispenser.toml`
18+
19+
**Example:**
20+
```sh
21+
dispenser --config /etc/dispenser/my-config.toml
22+
```
23+
24+
### `-t, --test`
25+
26+
Test the configuration file and exit. This validates your configuration files (including variable substitution) to ensure there are no syntax errors or missing variables.
27+
28+
**Example:**
29+
```sh
30+
dispenser --test
31+
```
32+
33+
**Output on success:**
34+
```
35+
Dispenser config is ok.
36+
```
37+
38+
**Output on error:**
39+
```
40+
---------------------------------- <string> -----------------------------------
41+
2 |
42+
3 | [service]
43+
4 | name = "nginx"
44+
5 > image = "${missing}/nginx:latest"
45+
i ^^^^^^^^^^ undefined value
46+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47+
No referenced variables
48+
-------------------------------------------------------------------------------
49+
```
50+
51+
### `-p, --pid-file <PATH>`
52+
53+
Specify the path to the PID file. This file is used to track the running Dispenser process and is required for sending signals with the `--signal` flag.
54+
55+
**Default:** `dispenser.pid`
56+
57+
**Example:**
58+
```sh
59+
dispenser --pid-file /var/run/dispenser.pid
60+
```
61+
62+
### `-s, --signal <SIGNAL>`
63+
64+
Send a signal to the running Dispenser instance. This command relies on the PID file, so you should run it from the same directory where Dispenser is running (typically `/opt/dispenser` for the default installation).
65+
66+
**Valid signals:**
67+
- `reload` - Reload the `dispenser.toml` configuration without restarting the process
68+
- `stop` - Gracefully stop the Dispenser daemon
69+
70+
**Examples:**
71+
```sh
72+
# Reload configuration
73+
dispenser --signal reload
74+
75+
# Stop the daemon
76+
dispenser --signal stop
77+
```
78+
79+
### `-h, --help`
80+
81+
Display help information about available options.
82+
83+
**Example:**
84+
```sh
85+
dispenser --help
86+
```
87+
88+
### `-V, --version`
89+
90+
Display the current version of Dispenser.
91+
92+
**Example:**
93+
```sh
94+
dispenser --version
95+
```
96+
97+
## Common Usage Patterns
98+
99+
### Running in Foreground (for testing)
100+
101+
```sh
102+
dispenser --config ./dispenser.toml
103+
```
104+
105+
### Validating Configuration Before Deployment
106+
107+
```sh
108+
dispenser --test && echo "Configuration is valid!"
109+
```
110+
111+
### Reloading Configuration After Changes
112+
113+
```sh
114+
# After editing dispenser.toml
115+
dispenser --signal reload
116+
```
117+
118+
### Using Custom Paths
119+
120+
```sh
121+
dispenser --config /etc/dispenser/production.toml --pid-file /var/run/dispenser-prod.pid
122+
```
123+
124+
## Systemd Integration
125+
126+
When Dispenser is installed via the `.deb` or `.rpm` package, it runs as a systemd service. You can manage it using standard systemd commands:
127+
128+
```sh
129+
# Start the service
130+
sudo systemctl start dispenser
131+
132+
# Stop the service
133+
sudo systemctl stop dispenser
134+
135+
# Restart the service
136+
sudo systemctl restart dispenser
137+
138+
# Check service status
139+
sudo systemctl status dispenser
140+
141+
# View logs
142+
sudo journalctl -u dispenser -f
143+
```
144+
145+
The systemd service automatically uses the configuration at `/opt/dispenser/dispenser.toml` and runs as the `dispenser` user.

CRON.md

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,110 @@
11
# Using Cron for Scheduled Deployments
22

3-
Dispenser provides a `cron` feature to schedule deployments or restarts of your services at specific intervals. This is useful for tasks that need to run periodically, such as batch jobs, or for ensuring services are restarted regularly for maintenance.
3+
Dispenser supports cron scheduling to deploy or restart services at specific intervals. This is useful for batch jobs, backups, ETL processes, or periodic maintenance restarts.
44

5-
## How it Works
5+
## Configuration
66

7-
You can add a `cron` attribute to any `[[instance]]` block in your `dispenser.toml` configuration file. The value of this attribute is a cron expression that defines the schedule for the deployment.
7+
Add a `cron` field to the `[dispenser]` section in your `service.toml`:
88

9-
When a `cron` schedule is defined for an instance, Dispenser will trigger a redeployment of the corresponding Docker Compose service according to the schedule. This is equivalent to running `docker-compose up -d --force-recreate` for the service.
9+
```toml
10+
[dispenser]
11+
watch = false
12+
initialize = "on-trigger"
13+
cron = "0 0 2 * * *" # Every day at 2 AM
14+
```
1015

11-
The cron scheduler uses a 6-field format that includes seconds:
16+
### Cron Expression Format
17+
18+
Dispenser uses a 6-field format (with seconds):
1219

1320
```
1421
┌───────────── second (0 - 59)
1522
│ ┌───────────── minute (0 - 59)
1623
│ │ ┌───────────── hour (0 - 23)
17-
│ │ │ ┌───────────── day of the month (1 - 31)
24+
│ │ │ ┌───────────── day of month (1 - 31)
1825
│ │ │ │ ┌───────────── month (1 - 12)
19-
│ │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
20-
│ │ │ │ │ │
26+
│ │ │ │ │ ┌───────────── day of week (0 - 6, Sunday = 0)
2127
│ │ │ │ │ │
2228
* * * * * *
2329
```
2430

25-
You can use online tools like [crontab.guru](https://crontab.guru/) to help generate the correct cron expression. Note that many online tools generate 5-field expressions, so you may need to add the seconds field (`*` or `0`) at the beginning.
31+
**Common expressions:**
32+
- `0 0 2 * * *` - Daily at 2 AM
33+
- `0 0 */6 * * *` - Every 6 hours
34+
- `0 30 9 * * 1-5` - Weekdays at 9:30 AM
35+
- `0 0 0 1 * *` - First day of each month
36+
- `*/10 * * * * *` - Every 10 seconds
37+
38+
Use [crontab.guru](https://crontab.guru/) for help (add `0` for seconds field).
39+
40+
## Examples
41+
42+
### Scheduled Backup Job
43+
44+
```toml
45+
[service]
46+
name = "backup-job"
47+
image = "my-backup:latest"
2648

27-
## Use Cases
49+
[[volume]]
50+
source = "./backups"
51+
target = "/backups"
2852

29-
### Scheduled-Only Deployments
53+
restart = "no"
3054

31-
You can use `cron` without an `images` attribute. This is ideal for services that run on a schedule such as ETLs or batch processing tasks, and do not have a corresponding image to monitor for updates.
55+
[dispenser]
56+
watch = false
57+
initialize = "on-trigger"
58+
cron = "0 0 2 * * *" # Daily at 2 AM
59+
```
3260

33-
**Example:**
34-
The following configuration will run the `hello-world` service every 10 seconds. Since there is no image to watch, the deployment is only triggered by the cron schedule.
61+
### ETL Job Every Hour
3562

3663
```toml
37-
# dispenser.toml
64+
[service]
65+
name = "etl-processor"
66+
image = "my-etl:latest"
67+
command = ["python", "process.py"]
3868

39-
[[instance]]
40-
path = "hello-world"
41-
cron = "*/10 * * * * *"
69+
restart = "no"
70+
71+
[dispenser]
72+
watch = false
73+
initialize = "on-trigger"
74+
cron = "0 0 * * * *" # Every hour
4275
```
4376

44-
The `docker-compose.yaml` for this service might look like this. It is important to set `restart: no` to prevent the container from restarting automatically after its task is complete. It will wait for the next scheduled run from Dispenser.
77+
### Periodic Restart with Image Watching
78+
79+
```toml
80+
[service]
81+
name = "worker"
82+
image = "my-worker:latest"
4583

46-
```yaml
47-
# hello-world/docker-compose.yaml
84+
restart = "always"
4885

49-
version: "3.8"
50-
services:
51-
hello-world:
52-
image: hello-world
53-
restart: no
86+
[dispenser]
87+
watch = true
88+
initialize = "immediately"
89+
cron = "0 0 4 * * *" # Restart daily at 4 AM
5490
```
5591

56-
### Scheduled Restarts with Image Monitoring
92+
This configuration will:
93+
- Deploy when a new image is detected
94+
- Also restart daily at 4 AM (even if no new image)
5795

58-
You can use `cron` in combination with image monitoring. In this case, Dispenser will deploy a new version of your service under two conditions:
59-
1. A new Docker image is detected in the registry.
60-
2. The `cron` schedule is met.
96+
## Options
6197

62-
This is useful for services that should be restarted periodically, even if no new image is available.
98+
### `initialize`
6399

64-
**Example:**
65-
The following configuration watches the `nginx:latest` image and also restarts the service every minute.
100+
- `immediately` (default) - Start when Dispenser starts
101+
- `on-trigger` - Only start when cron fires or image updates
66102

67-
```toml
68-
# dispenser.toml
103+
### `watch`
69104

70-
[[instance]]
71-
path = "nginx"
72-
# Will restart the service every minute or when the nginx image gets updated
73-
cron = "0 */1 * * * *"
74-
images = [{ registry = "docker.io", name = "nginx", tag = "latest" }]
75-
```
105+
- `true` - Monitor registry for image updates
106+
- `false` - Only run on cron schedule
107+
108+
### `restart`
76109

77-
By using the `cron` feature, you can extend Dispenser's capabilities beyond continuous deployment to include scheduled task orchestration. You can find more examples in the `example` directory of the project.
110+
Use `restart = "no"` for one-time jobs to prevent automatic restarts between scheduled runs.

Cargo.lock

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "dispenser"
3-
version = "0.6.0"
3+
version = "0.7.0"
44
edition = "2021"
55
license = "MIT"
66

@@ -10,6 +10,7 @@ chrono = "0.4.42"
1010
clap = { version = "4.5.18", features = ["derive"] }
1111
cron = { version = "0.15.0", features = ["serde"] }
1212
env_logger = "0.11.5"
13+
futures = "0.3.31"
1314
futures-util = "0.3.31"
1415
google-cloud-secretmanager-v1 = "1.2.0"
1516
log = "0.4.22"

0 commit comments

Comments
 (0)