Compare commits
59 commits
1.1.1-rc.6
...
main
Author | SHA1 | Date | |
---|---|---|---|
10f6aa8455 | |||
af6dcad5df | |||
afb4dd8ff3 | |||
3f41b8958e | |||
7e7646a4eb | |||
40f617a2d6 | |||
65519933be | |||
2c83671c8e | |||
3626237d90 | |||
6a31ae0f9a | |||
04a1be9bcb | |||
49b8d8cc05 | |||
ffe1fbc7a4 | |||
3c4e55d126 | |||
8a1c52cd90 | |||
7b6bdc37c7 | |||
bff7057c45 | |||
9dfd21ce8d | |||
dec6834920 | |||
9d5c3fcc23 | |||
bbee00c9f9 | |||
46bf5dc50d | |||
ba34228cbd | |||
74cb65a658 | |||
973741f7bb | |||
1e578d1a6b | |||
fda3c6bab6 | |||
7b7b55de0d | |||
561bcbba26 | |||
6d0c792f52 | |||
3da5ac2a0c | |||
89192016fd | |||
6a4a2b6445 | |||
bccfc3d1f1 | |||
b6aade0ad3 | |||
83a0b37c4e | |||
61e45713e3 | |||
9ccd290ebc | |||
0c8414f0d0 | |||
50c9677b82 | |||
f8f6737ae6 | |||
9b47a6dbac | |||
cbab7703ef | |||
7b6cc44e17 | |||
30cf1afba8 | |||
c62dd2ff39 | |||
86dcdea7c6 | |||
d28bbd45d7 | |||
3fc17bcd4a | |||
3dec954747 | |||
45a7ab58d7 | |||
ceddb5454d | |||
812f93d2be | |||
b9419a5446 | |||
ffcaeb9d4b | |||
6ec4b1b48c | |||
6936fa87d4 | |||
db0df8f0f0 | |||
95268b5020 |
12 changed files with 174 additions and 123 deletions
|
@ -1,4 +1,4 @@
|
||||||
name: 'Build and Release Binary File'
|
name: 'Build and release binary file and packages'
|
||||||
author: 'Neshura'
|
author: 'Neshura'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
@ -63,7 +63,7 @@ jobs:
|
||||||
name: Bundle .deb package
|
name: Bundle .deb package
|
||||||
run: |
|
run: |
|
||||||
cargo deb
|
cargo deb
|
||||||
DEBIAN_REF=$(echo ${{ github.ref_name }} | tr - \~)
|
DEBIAN_REF=$(cat Cargo.toml | grep -E "(^|\|)version =" | cut -f2- -d= | tr -d \" | tr -d " " | tr - \~)
|
||||||
echo "DEBIAN_REF=$DEBIAN_REF" >> dist/build.env
|
echo "DEBIAN_REF=$DEBIAN_REF" >> dist/build.env
|
||||||
DEBIAN_REV=-$(cat Cargo.toml | grep -E "(^|\|)revision =" | cut -f2- -d= | tr -d \" | tr -d " ")
|
DEBIAN_REV=-$(cat Cargo.toml | grep -E "(^|\|)revision =" | cut -f2- -d= | tr -d \" | tr -d " ")
|
||||||
echo "DEBIAN_REV=$DEBIAN_REV" >> dist/build.env
|
echo "DEBIAN_REV=$DEBIAN_REV" >> dist/build.env
|
||||||
|
@ -76,7 +76,7 @@ jobs:
|
||||||
path: dist
|
path: dist
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
upload-release:
|
upload-generic-package:
|
||||||
needs: build
|
needs: build
|
||||||
if: success()
|
if: success()
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
@ -89,23 +89,55 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo 'curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
echo 'curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
||||||
--upload-file release_blobs/${{ github.event.repository.name }}-linux-amd64 \
|
--upload-file release_blobs/${{ github.event.repository.name }}-linux-amd64 \
|
||||||
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/generic/${{ github.event.repository.name }}/${{ github.ref_name }}/chellaris-rust-api-linux-amd64'
|
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/generic/${{ github.event.repository.name }}/${{ github.ref_name }}/${{ github.event.repository.name }}-linux-amd64'
|
||||||
curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
||||||
--upload-file release_blobs/${{ github.event.repository.name }}-linux-amd64 \
|
--upload-file release_blobs/${{ github.event.repository.name }}-linux-amd64 \
|
||||||
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/generic/${{ github.event.repository.name }}/${{ github.ref_name }}/chellaris-rust-api-linux-amd64
|
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/generic/${{ github.event.repository.name }}/${{ github.ref_name }}/${{ github.event.repository.name }}-linux-amd64
|
||||||
|
|
||||||
|
upload-debian-package:
|
||||||
|
needs: build
|
||||||
|
if: success()
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
-
|
-
|
||||||
name: Upload Debian Package
|
name: Downloading All Build Artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
-
|
||||||
|
name: Upload Debian Package to staging
|
||||||
run: |
|
run: |
|
||||||
source release_blobs/build.env
|
source release_blobs/build.env
|
||||||
echo 'curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
echo 'curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
||||||
|
--upload-file release_blobs/${{ github.event.repository.name }}_'"$DEBIAN_REF""$DEBIAN_REV"'_amd64.deb \
|
||||||
|
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/debian/pool/bookworm/staging/upload'
|
||||||
|
curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
||||||
--upload-file release_blobs/${{ github.event.repository.name }}_"$DEBIAN_REF""$DEBIAN_REV"_amd64.deb \
|
--upload-file release_blobs/${{ github.event.repository.name }}_"$DEBIAN_REF""$DEBIAN_REV"_amd64.deb \
|
||||||
|
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/debian/pool/bookworm/staging/upload
|
||||||
|
-
|
||||||
|
name: Upload Debian Package to main
|
||||||
|
if: (! contains(github.ref_name, '-rc'))
|
||||||
|
run: |
|
||||||
|
source release_blobs/build.env
|
||||||
|
echo 'curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
||||||
|
--upload-file release_blobs/${{ github.event.repository.name }}_'"$DEBIAN_REF""$DEBIAN_REV"'_amd64.deb \
|
||||||
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/debian/pool/bookworm/main/upload'
|
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/debian/pool/bookworm/main/upload'
|
||||||
curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
curl -v --user ${{ secrets.FORGEJO_USERNAME }}:${{ secrets.FORGEJO_TOKEN }} \
|
||||||
--upload-file release_blobs/${{ github.event.repository.name }}_"$DEBIAN_REF""$DEBIAN_REV"_amd64.deb \
|
--upload-file release_blobs/${{ github.event.repository.name }}_"$DEBIAN_REF""$DEBIAN_REV"_amd64.deb \
|
||||||
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/debian/pool/bookworm/main/upload
|
https://forgejo.neshweb.net/api/packages/${{ secrets.FORGEJO_USERNAME }}/debian/pool/bookworm/main/upload
|
||||||
|
|
||||||
|
create-release:
|
||||||
|
needs: build
|
||||||
|
if: success()
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Downloading All Build Artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
-
|
||||||
|
name: Filter out env files
|
||||||
|
run: rm release_blobs/build.env
|
||||||
-
|
-
|
||||||
name: Release New Version
|
name: Release New Version
|
||||||
uses: actions/forgejo-release@v1
|
uses: actions/forgejo-release@v2
|
||||||
with:
|
with:
|
||||||
direction: upload
|
direction: upload
|
||||||
url: https://forgejo.neshweb.net
|
url: https://forgejo.neshweb.net
|
||||||
|
|
67
.forgejo/workflows/pull-requests.yml
Normal file
67
.forgejo/workflows/pull-requests.yml
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
name: 'Build binary file and bundle packages'
|
||||||
|
author: 'Neshura'
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: docker
|
||||||
|
container: forgejo.neshweb.net/ci-docker-images/rust-node:latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Add Clippy
|
||||||
|
run: rustup component add clippy
|
||||||
|
-
|
||||||
|
name: Checking Out Repository Code
|
||||||
|
uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set Up Cargo Cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
target/
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
-
|
||||||
|
name: Run Clippy
|
||||||
|
run: cargo clippy
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs: test
|
||||||
|
if: success()
|
||||||
|
runs-on: docker
|
||||||
|
container: forgejo.neshweb.net/ci-docker-images/rust-node:latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checking Out Repository Code
|
||||||
|
uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Prepare build environment
|
||||||
|
run: mkdir dist
|
||||||
|
-
|
||||||
|
name: Compiling To Linux Target
|
||||||
|
run: |
|
||||||
|
cargo build -r
|
||||||
|
mv target/release/${{ github.event.repository.name }} dist/${{ github.event.repository.name }}-linux-amd64
|
||||||
|
-
|
||||||
|
name: Bundle .deb package
|
||||||
|
run: |
|
||||||
|
cargo deb
|
||||||
|
DEBIAN_REF=$(cat Cargo.toml | grep -E "(^|\|)version =" | cut -f2- -d= | tr -d \" | tr -d " " | tr - \~)
|
||||||
|
echo "DEBIAN_REF=$DEBIAN_REF" >> dist/build.env
|
||||||
|
DEBIAN_REV=-$(cat Cargo.toml | grep -E "(^|\|)revision =" | cut -f2- -d= | tr -d \" | tr -d " ")
|
||||||
|
echo "DEBIAN_REV=$DEBIAN_REV" >> dist/build.env
|
||||||
|
mv target/debian/${{ github.event.repository.name }}_"$DEBIAN_REF""$DEBIAN_REV"_amd64.deb dist/${{ github.event.repository.name }}_"$DEBIAN_REF""$DEBIAN_REV"_amd64.deb
|
||||||
|
-
|
||||||
|
name: Uploading Build Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: release_blobs
|
||||||
|
path: dist
|
||||||
|
if-no-files-found: error
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -114,7 +114,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloudflare-dns-updater"
|
name = "cloudflare-dns-updater"
|
||||||
version = "1.1.1-rc.6"
|
version = "1.1.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"confy",
|
"confy",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
authors = ["Neshura"]
|
authors = ["Neshura"]
|
||||||
name = "cloudflare-dns-updater"
|
name = "cloudflare-dns-updater"
|
||||||
version = "1.1.1-rc.6"
|
version = "1.1.9"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Application for automatically updating Cloudflare DNS records"
|
description = "Application for automatically updating Cloudflare DNS records"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
@ -10,12 +10,13 @@ license = "GPL-3.0-or-later"
|
||||||
extended-description = "Application for automatically updating Cloudflare DNS records"
|
extended-description = "Application for automatically updating Cloudflare DNS records"
|
||||||
maintainer-scripts = "debian/"
|
maintainer-scripts = "debian/"
|
||||||
revision = "1"
|
revision = "1"
|
||||||
|
depends = ["libc6", "libssl3", "systemd"]
|
||||||
assets = [
|
assets = [
|
||||||
[
|
[
|
||||||
"debian/cloudflare-dns-updater.service",
|
"target/release/cloudflare-dns-updater",
|
||||||
"/lib/systemd/user/cloudflare-dns-updater.service",
|
"/usr/local/bin/cloudflare-dns-updater",
|
||||||
"755",
|
"755",
|
||||||
],
|
]
|
||||||
]
|
]
|
||||||
systemd-units = { enable = false }
|
systemd-units = { enable = false }
|
||||||
|
|
||||||
|
|
14
README.md
14
README.md
|
@ -7,10 +7,10 @@
|
||||||
The application necessarily requires a valid Cloudflare API Token.
|
The application necessarily requires a valid Cloudflare API Token.
|
||||||
Further the application must be located in the same network as the configured zones.
|
Further the application must be located in the same network as the configured zones.
|
||||||
|
|
||||||
The actual configuration happens in three or more files:
|
The actual configuration happens in three or more files located in `~/.config/cloudflare-dns-updater/`:
|
||||||
`config.toml` contains general configuration parameters for the application
|
`config.toml` contains general configuration parameters for the application
|
||||||
`interfaces.toml` contains all IPv6 interfaces available/used by the zone config files.
|
`interfaces.toml` contains all IPv6 interfaces available/used by the zone config files.
|
||||||
`.toml` files in `zone.d` contain settings for individual zones.
|
`.toml` files in `zones.d` contain settings for individual zones.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ host_address = "::edcb:a098:7654:3210"
|
||||||
example-interface = "::0123:4567:890a:bcde" # static part of the IP, the rest will be dynamically generated using the host
|
example-interface = "::0123:4567:890a:bcde" # static part of the IP, the rest will be dynamically generated using the host
|
||||||
```
|
```
|
||||||
|
|
||||||
*zone.d/example.org.toml*
|
*zones.d/example.org.toml*
|
||||||
```toml
|
```toml
|
||||||
email = "owner@example.org" # Email of User owning the Zone
|
email = "owner@example.org" # Email of User owning the Zone
|
||||||
zone = "example.org" # Zone Name
|
zone = "example.org" # Zone Name
|
||||||
|
@ -42,4 +42,10 @@ interface = "example-interface" # Only required on type values 6 and 10
|
||||||
```
|
```
|
||||||
|
|
||||||
## Debian Repository
|
## Debian Repository
|
||||||
TODO!
|
|
||||||
|
Currently supported:
|
||||||
|
- Debian 12 'Bookworm'
|
||||||
|
|
||||||
|
Includes systemd system and user unit files
|
||||||
|
|
||||||
|
For more details see [the package registry](https://forgejo.neshweb.net/Neshura/-/packages/debian/cloudflare-dns-updater)
|
|
@ -5,6 +5,7 @@ After=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
|
User=%i
|
||||||
ExecStart=/usr/local/bin/cloudflare-dns-updater
|
ExecStart=/usr/local/bin/cloudflare-dns-updater
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=3
|
RestartSec=3
|
36
debian/postinst
vendored
36
debian/postinst
vendored
|
@ -1,36 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#DEBHELPER#
|
|
||||||
|
|
||||||
# Also enable User Service
|
|
||||||
|
|
||||||
# Automatically added by cargo-deb
|
|
||||||
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
|
||||||
if deb-systemd-helper --user debian-installed cloudflare-dns-updater.service; then
|
|
||||||
# This will only remove masks created by d-s-h on package removal.
|
|
||||||
deb-systemd-helper --user unmask cloudflare-dns-updater.service >/dev/null || true
|
|
||||||
|
|
||||||
if deb-systemd-helper --user --quiet was-enabled cloudflare-dns-updater.service; then
|
|
||||||
# Create new symlinks, if any.
|
|
||||||
deb-systemd-helper --user enable cloudflare-dns-updater.service >/dev/null || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update the statefile to add new symlinks (if any), which need to be cleaned
|
|
||||||
# up on purge. Also remove old symlinks.
|
|
||||||
deb-systemd-helper --user update-state cloudflare-dns-updater.service >/dev/null || true
|
|
||||||
fi
|
|
||||||
# End automatically added section
|
|
||||||
# Automatically added by cargo-deb
|
|
||||||
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
|
||||||
if [ -d /run/systemd/system ]; then
|
|
||||||
USER="$(who | head -1 | awk '{print $1;}')"
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) systemctl --user daemon-reload >/dev/null || true"
|
|
||||||
if [ -n "$2" ]; then
|
|
||||||
_dh_action=restart
|
|
||||||
else
|
|
||||||
_dh_action=start
|
|
||||||
fi
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) deb-systemd-invoke --user $_dh_action cloudflare-dns-updater.service >/dev/null || true"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# End automatically added section
|
|
27
debian/postrm
vendored
27
debian/postrm
vendored
|
@ -1,27 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#DEBHELPER#
|
|
||||||
|
|
||||||
# Also enable User Service
|
|
||||||
|
|
||||||
# Automatically added by cargo-deb
|
|
||||||
if [ -d /run/systemd/system ]; then
|
|
||||||
USER="$(who | head -1 | awk '{print $1;}')"
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) systemctl --user daemon-reload >/dev/null || true"
|
|
||||||
fi
|
|
||||||
# End automatically added section
|
|
||||||
# Automatically added by cargo-deb
|
|
||||||
if [ "$1" = "remove" ]; then
|
|
||||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
|
||||||
USER="$(who | head -1 | awk '{print $1;}')"
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) deb-systemd-helper --user mask cloudflare-dns-updater.service >/dev/null || true"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$1" = "purge" ]; then
|
|
||||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
|
||||||
USER="$(who | head -1 | awk '{print $1;}')"
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) deb-systemd-helper --user purge cloudflare-dns-updater.service >/dev/null || true"
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) deb-systemd-helper --user unmask cloudflare-dns-updater.service >/dev/null || true"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# End automatically added section
|
|
11
debian/prerm
vendored
11
debian/prerm
vendored
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#DEBHELPER#
|
|
||||||
|
|
||||||
# Also enable User Service
|
|
||||||
|
|
||||||
# Automatically added by cargo-deb
|
|
||||||
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
|
|
||||||
USER="$(who | head -1 | awk '{print $1;}')"
|
|
||||||
runuser -l $USER -c "XDG_RUNTIME_DIR=/run/user/$(id -u $USER) deb-systemd-invoke --user stop cloudflare-dns-updater.service >/dev/null || true"
|
|
||||||
fi
|
|
||||||
# End automatically added section
|
|
|
@ -64,7 +64,7 @@ impl CloudflareZone {
|
||||||
let entries = match response.json::<CloudflareApiResults>() {
|
let entries = match response.json::<CloudflareApiResults>() {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to parse API response. Error: {e}");
|
let err_msg = format!("Unable to parse API response: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -75,7 +75,7 @@ impl CloudflareZone {
|
||||||
|
|
||||||
Ok(entries.result)
|
Ok(entries.result)
|
||||||
} else {
|
} else {
|
||||||
let err_msg = format!("Unable to fetch Cloudflare Zone Entries for {}. Error: {}",self.name ,response.status());
|
let err_msg = format!("Unable to fetch Cloudflare Zone Entries for {}: {}",self.name ,response.status());
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -84,7 +84,7 @@ impl CloudflareZone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to access Cloudflare API. Error: {e}");
|
let err_msg = format!("Unable to access Cloudflare API: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -107,7 +107,7 @@ impl CloudflareZone {
|
||||||
self.validate_response(response)
|
self.validate_response(response)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to access Cloudflare API. Error: {e}");
|
let err_msg = format!("Unable to access Cloudflare API: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -133,7 +133,7 @@ impl CloudflareZone {
|
||||||
self.validate_response(response)
|
self.validate_response(response)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to access Cloudflare API. Error: {e}");
|
let err_msg = format!("Unable to access Cloudflare API: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -174,7 +174,7 @@ impl CloudflareZone {
|
||||||
self.validate_response(response)
|
self.validate_response(response)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to access Cloudflare API. Error: {e}");
|
let err_msg = format!("Unable to access Cloudflare API: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -200,7 +200,7 @@ impl CloudflareZone {
|
||||||
self.validate_response(response)
|
self.validate_response(response)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to access Cloudflare API. Error: {e}");
|
let err_msg = format!("Unable to access Cloudflare API: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -270,7 +270,7 @@ impl CloudflareZone {
|
||||||
match Url::parse(input) {
|
match Url::parse(input) {
|
||||||
Ok(url) => Ok(url),
|
Ok(url) => Ok(url),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to parse URL. Error: {}", e);
|
let err_msg = format!("Unable to parse URL: {}", e);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -293,7 +293,7 @@ impl CloudflareZone {
|
||||||
let data = match response.json::<CloudflareApiResult>() {
|
let data = match response.json::<CloudflareApiResult>() {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("Unable to parse API response. Error: {e}");
|
let err_msg = format!("Unable to parse API response: {e}");
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -305,7 +305,7 @@ impl CloudflareZone {
|
||||||
match data.success {
|
match data.success {
|
||||||
true => Ok(()),
|
true => Ok(()),
|
||||||
false => {
|
false => {
|
||||||
let err_msg = format!("Unexpected error while updating DNS record. Info: {:?}", data);
|
let err_msg = format!("Unexpected error while updating DNS record: {:?}", data);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
@ -314,7 +314,7 @@ impl CloudflareZone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let err_msg = format!("Unable to post/put Cloudflare DNS entry. Error: {}", response.status());
|
let err_msg = format!("Unable to post/put Cloudflare DNS entry: {}", response.status());
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl InterfaceConfig {
|
||||||
let interface_address = match self.interfaces.get(interface_name) {
|
let interface_address = match self.interfaces.get(interface_name) {
|
||||||
Some(address) => *address,
|
Some(address) => *address,
|
||||||
None => {
|
None => {
|
||||||
let err_msg = "Malformed IP in interfaces.toml";
|
let err_msg = format!("Malformed or missing IP in interfaces.toml for interface {}", interface_name);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => error!("[ERROR] {err_msg}"),
|
true => error!("[ERROR] {err_msg}"),
|
||||||
false => eprintln!("[ERROR] {err_msg}"),
|
false => eprintln!("[ERROR] {err_msg}"),
|
||||||
|
|
40
src/main.rs
40
src/main.rs
|
@ -24,8 +24,8 @@ struct Addresses {
|
||||||
impl Addresses {
|
impl Addresses {
|
||||||
fn new() -> Result<Self, Box<dyn Error>> {
|
fn new() -> Result<Self, Box<dyn Error>> {
|
||||||
let mut ret = Self {
|
let mut ret = Self {
|
||||||
ipv4_uri: "https://am.i.mullvad.net/ip".to_owned(),
|
ipv4_uri: "http://ip4only.me/api/".to_owned(),
|
||||||
ipv6_uri: "https://ipv6.am.i.mullvad.net/ip".to_owned(),
|
ipv6_uri: "http://ip6only.me/api/".to_owned(),
|
||||||
ipv4: Ipv4Addr::new(0, 0, 0, 0),
|
ipv4: Ipv4Addr::new(0, 0, 0, 0),
|
||||||
ipv6: Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
|
ipv6: Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
};
|
};
|
||||||
|
@ -61,6 +61,14 @@ impl Addresses {
|
||||||
match self.get_v4() {
|
match self.get_v4() {
|
||||||
Ok(ip) => {
|
Ok(ip) => {
|
||||||
if ip != self.ipv4 {
|
if ip != self.ipv4 {
|
||||||
|
if ip == Ipv4Addr::new(0,0,0,0) {
|
||||||
|
let warn_msg = "'0.0.0.0' detected as new IPv4, skipping changes".to_owned();
|
||||||
|
match connected_to_journal() {
|
||||||
|
true => warn!("[WARN] {warn_msg}"),
|
||||||
|
false => println!("[WARN] {warn_msg}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
let info_msg = format!("IPv4 changed from '{}' to '{}'", self.ipv4, ip);
|
let info_msg = format!("IPv4 changed from '{}' to '{}'", self.ipv4, ip);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => info!("[INFO] {info_msg}"),
|
true => info!("[INFO] {info_msg}"),
|
||||||
|
@ -69,11 +77,12 @@ impl Addresses {
|
||||||
self.ipv4 = ip;
|
self.ipv4 = ip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let warn_msg = format!("Unable to fetch IPv4 from '{}'. Error: {}", self.ipv4_uri, e);
|
let error_msg = format!("Unable to fetch IPv4 from '{}': {}", self.ipv4_uri, e);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => warn!("[WARN] {warn_msg}"),
|
true => error!("[ERROR] {error_msg}"),
|
||||||
false => println!("[WARN] {warn_msg}"),
|
false => eprintln!("[ERROR] {error_msg}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +90,14 @@ impl Addresses {
|
||||||
match self.get_v6() {
|
match self.get_v6() {
|
||||||
Ok(ip) => {
|
Ok(ip) => {
|
||||||
if ip != self.ipv6 {
|
if ip != self.ipv6 {
|
||||||
|
if ip == Ipv6Addr::new(0,0,0,0,0,0,0,0) {
|
||||||
|
let warn_msg = "'::' detected as new IPv6, skipping changes".to_owned();
|
||||||
|
match connected_to_journal() {
|
||||||
|
true => warn!("[WARN] {warn_msg}"),
|
||||||
|
false => println!("[WARN] {warn_msg}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
let info_msg = format!("IPv6 changed from '{}' to '{}'", self.ipv6, ip);
|
let info_msg = format!("IPv6 changed from '{}' to '{}'", self.ipv6, ip);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => info!("[INFO] {info_msg}"),
|
true => info!("[INFO] {info_msg}"),
|
||||||
|
@ -89,11 +106,12 @@ impl Addresses {
|
||||||
self.ipv6 = ip;
|
self.ipv6 = ip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let warn_msg = format!("Unable to fetch IPv6 from '{}'. Error: {}", self.ipv6_uri, e);
|
let error_msg = format!("Unable to fetch IPv6 from '{}': {}", self.ipv6_uri, e);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => warn!("[WARN] {warn_msg}"),
|
true => error!("[ERROR] {error_msg}"),
|
||||||
false => println!("[WARN] {warn_msg}"),
|
false => eprintln!("[ERROR] {error_msg}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +122,7 @@ impl Addresses {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
match res.status() {
|
match res.status() {
|
||||||
StatusCode::OK => {
|
StatusCode::OK => {
|
||||||
let ip_string = res.text().expect("Returned data should always contain text").trim_end().to_owned();
|
let ip_string = res.text().expect("Returned data should always contain text").trim_end().split(',').collect::<Vec<&str>>()[1].to_owned();
|
||||||
Ok(Ipv4Addr::from_str(ip_string.as_str()).expect("Returned IP should always be parseable"))
|
Ok(Ipv4Addr::from_str(ip_string.as_str()).expect("Returned IP should always be parseable"))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -127,7 +145,7 @@ impl Addresses {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
match res.status() {
|
match res.status() {
|
||||||
StatusCode::OK => {
|
StatusCode::OK => {
|
||||||
let ip_string = res.text().expect("Returned data should always contain text").trim_end().to_owned();
|
let ip_string: String = res.text().expect("Returned data should always contain text").trim_end().split(',').collect::<Vec<&str>>()[1].to_owned();
|
||||||
Ok(Ipv6Addr::from_str(ip_string.as_str()).expect("Returned IP should always be parseable"))
|
Ok(Ipv6Addr::from_str(ip_string.as_str()).expect("Returned IP should always be parseable"))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -638,7 +656,7 @@ fn main() {
|
||||||
if cf_zone.update(entry, r#type, &cf_entry.id, ipv6, ipv4).is_ok() {
|
if cf_zone.update(entry, r#type, &cf_entry.id, ipv6, ipv4).is_ok() {
|
||||||
let info_msg = format!("Updated {} DNS Record for entry '{}' in zone '{}'", r#type, entry.name, zone.name);
|
let info_msg = format!("Updated {} DNS Record for entry '{}' in zone '{}'", r#type, entry.name, zone.name);
|
||||||
match connected_to_journal() {
|
match connected_to_journal() {
|
||||||
true => warn!("[INFO] {info_msg}"),
|
true => info!("[INFO] {info_msg}"),
|
||||||
false => println!("[INFO] {info_msg}"),
|
false => println!("[INFO] {info_msg}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue