Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dispenser"
version = "0.7.0"
version = "0.8.0"
edition = "2021"
license = "MIT"

Expand Down
2 changes: 1 addition & 1 deletion INSTALL.deb.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ wget ...


```sh
sudo apt install ./dispenser-0.7-0.x86_64.deb
sudo apt install ./dispenser-0.8.0-0.x86_64.deb
```

You can validate that it was successfully installed by switching to the
Expand Down
2 changes: 1 addition & 1 deletion INSTALL.redhat.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ wget ...


```sh
sudo dnf install ./dispenser-0.7-0.x86_64.rpm
sudo dnf install ./dispenser-0.8.0-0.x86_64.rpm
```

You can validate that it was successfully installed by switching to the
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Download the latest `.deb` or `.rpm` package from the [releases page](https://gi

```sh
# Download the .deb package
# wget https://github.com/ixpantia/dispenser/releases/download/v0.7.0/dispenser-0.7-0.x86_64.deb
# wget https://github.com/ixpantia/dispenser/releases/download/v0.8.0/dispenser-0.8.0-0.x86_64.deb

sudo apt install ./dispenser-0.7-0.x86_64.deb
sudo apt install ./dispenser-0.8.0-0.x86_64.deb
```

### RHEL / CentOS / Fedora
Expand All @@ -41,7 +41,7 @@ sudo apt install ./dispenser-0.7-0.x86_64.deb
# Download the .rpm package
# wget ...

sudo dnf install ./dispenser-0.7-0.x86_64.rpm
sudo dnf install ./dispenser-0.8.0-0.x86_64.rpm
```

The installation process will:
Expand Down
20 changes: 20 additions & 0 deletions SERVICE_CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,26 @@ cron = "0 3 * * *" # Every day at 3 AM

See [CRON.md](CRON.md) for more details on cron scheduling.

### `pull` (optional)

Controls when Dispenser should pull the Docker image from the registry. This is useful for ensuring that services (especially scheduled jobs) are always up-to-date with the latest image when they run, without necessarily triggering a redeployment on every image update if `watch` is `false`.

**Valid values:**
- `always` - Pull the image from the registry every time the container is started or recreated.
- `on-startup` - Pull the image only if the container does not exist. (default)

**Default:** `on-startup`

```toml
[dispenser]
# For a background scheduled job that should always run the latest image,
# but not necessarily restart if the image updates outside of its schedule.
watch = false
initialize = "on-trigger"
cron = "0 3 * * *" # Every day at 3 AM
pull = "always"
```

## Service Dependencies

The `[depends_on]` section defines dependencies between services.
Expand Down
2 changes: 1 addition & 1 deletion deb/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: dispenser
Version: 0.7
Version: VERSION_PLACEHOLDER
Maintainer: ixpantia S.A.
Architecture: amd64
Description: Continously Deploy services with Docker Compose
Expand Down
31 changes: 22 additions & 9 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
# justfile for dispenser project

DISPENSER_VERSION := "0.7"
DISPENSER_VERSION := shell('grep "^version" Cargo.toml | head -n1 | cut -d \" -f 2')
TARGET_BIN := "target/x86_64-unknown-linux-musl/release/dispenser"
USR_BIN_DEB := "deb/usr/local/bin/dispenser"
USR_BIN_RPM := "rpm/usr/local/bin/dispenser"

version:
echo "{{DISPENSER_VERSION}}"

build:
CARGO_TARGET_DIR="./target" cargo build --release --target "x86_64-unknown-linux-musl"

build-deb: build
mkdir -p deb/usr/local/bin/
rm -f {{USR_BIN_DEB}}
mv {{TARGET_BIN}} {{USR_BIN_DEB}}
dpkg-deb --build deb
rm -f dispenser.deb
mv deb.deb dispenser-{{DISPENSER_VERSION}}-0.x86_64.deb
rm -rf target/deb_stage
mkdir -p target/deb_stage
cp -R deb/* target/deb_stage/
mkdir -p target/deb_stage/usr/local/bin
cp {{TARGET_BIN}} target/deb_stage/usr/local/bin/dispenser
sed 's/VERSION_PLACEHOLDER/{{DISPENSER_VERSION}}/' deb/DEBIAN/control > target/deb_stage/DEBIAN/control
dpkg-deb --build target/deb_stage dispenser-{{DISPENSER_VERSION}}-0.x86_64.deb

build-rpm: build
rm -rf rpmstage rpmout
Expand All @@ -24,4 +27,14 @@ build-rpm: build
mkdir -p rpmout
cp {{TARGET_BIN}} rpmstage/usr/local/bin/dispenser
cp rpm/usr/lib/systemd/system/dispenser.service rpmstage/usr/lib/systemd/system/
rpmbuild --target=x86_64 --buildroot $(pwd)/rpmstage --define "_topdir $(pwd)/rpmout" -bb rpm/dispenser.spec --noclean
rpmbuild --target=x86_64 --buildroot $(pwd)/rpmstage --define "_topdir $(pwd)/rpmout" --define "version {{DISPENSER_VERSION}}" -bb rpm/dispenser.spec --noclean

# Usage: just bump 0.8.0
bump NEW_VERSION:
@echo "Bumping version to {{NEW_VERSION}}..."
# Update Cargo.toml
sed -i '' 's/^version = ".*"/version = "{{NEW_VERSION}}"/' Cargo.toml
# Update Documentation (URLs and filenames)
sed -i '' -E 's/v[0-9]+\.[0-9]+\.[0-9]+/v{{NEW_VERSION}}/g' README.md INSTALL*.md
sed -i '' -E 's/dispenser-[0-9]+\.[0-9]+/dispenser-{{NEW_VERSION}}/g' README.md INSTALL*.md
@echo "Done. Don't forget to commit and tag!"
2 changes: 1 addition & 1 deletion rpm/dispenser.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: dispenser
Version: 0.7
Version: %{version}
Release: 0
Summary: Continously Deploy services with Docker Compose
License: see /usr/share/doc/dispenser/copyright
Expand Down
7 changes: 6 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{process::ExitCode, sync::Arc};

use crate::service::{
file::EntrypointFile,
manager::{ServiceMangerConfig, ServicesManager},
vars::ServiceConfigError,
};
Expand Down Expand Up @@ -59,6 +58,12 @@ async fn main() -> ExitCode {
}
};

if let Err(e) = manager.validate_containers_not_present().await {
log::error!("{e}");
log::error!("It seems that some of the containers declared already exist. This prevents dispenser from properly managing the life-cycle of these containers. Please remove them and restart dispenser.");
std::process::exit(1);
}

// Wrap the manager in a Mutex so we can replace it on reload
let manager_holder = Arc::new(Mutex::new(manager));

Expand Down
37 changes: 24 additions & 13 deletions src/service/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{collections::HashMap, path::PathBuf};

use super::vars::{render_template, ServiceConfigError, ServiceVarsMaterialized};

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct EntrypointFile {
#[serde(rename = "service")]
pub services: Vec<EntrypointFileEntry>,
Expand All @@ -28,13 +28,13 @@ impl EntrypointFile {

// Render the template with variables
let rendered_config =
render_template(&config, &vars).map_err(|e| ServiceConfigError::Template((path, e)))?;
render_template(&config, vars).map_err(|e| ServiceConfigError::Template((path, e)))?;

// Parse the rendered config as TOML
Ok(toml::from_str(&rendered_config)?)
}
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct NetworkDeclarationEntry {
pub name: String,
#[serde(default = "default_network_driver")]
Expand All @@ -61,7 +61,7 @@ fn default_true() -> bool {
true
}

#[derive(Debug, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub enum NetworkDriver {
#[default]
#[serde(alias = "bridge")]
Expand All @@ -76,15 +76,15 @@ pub enum NetworkDriver {
None,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct EntrypointFileEntry {
/// Path to the directory where a service.toml file is found.
/// This toml file should be deserialized into a ServiceFile.
/// This path is relative to the location of EntrypointFile.
pub path: PathBuf,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ServiceFile {
pub service: ServiceEntry,
#[serde(default, rename = "port")]
Expand Down Expand Up @@ -119,7 +119,7 @@ pub enum Initialize {
OnTrigger,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum DependsOnCondition {
#[serde(
alias = "service-started",
Expand All @@ -135,20 +135,31 @@ pub enum DependsOnCondition {
ServiceCompleted,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub enum PullOptions {
#[serde(alias = "always")]
Always,
#[default]
#[serde(alias = "on-startup", alias = "on_startup", alias = "onstartup")]
OnStartup,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DispenserConfig {
pub watch: bool,
#[serde(default)]
pub initialize: Initialize,
pub cron: Option<Schedule>,
#[serde(default)]
pub pull: PullOptions,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Network {
pub name: String,
}

#[derive(Debug, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub enum Restart {
#[serde(alias = "always")]
Always,
Expand All @@ -165,21 +176,21 @@ pub enum Restart {
UnlessStopped,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct PortEntry {
pub host: u16,
pub container: u16,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct VolumeEntry {
pub source: String,
pub target: String,
#[serde(default)]
pub readonly: bool,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ServiceEntry {
pub name: String,
pub image: String,
Expand Down
Loading