1 Commits

Author SHA1 Message Date
75e527737c feat: introduce logger to config
All checks were successful
CI / test (pull_request) Successful in 37s
2024-12-27 17:09:57 +01:00
12 changed files with 66 additions and 253 deletions

View File

@@ -4,14 +4,6 @@ on:
push: push:
branches: branches:
- main - main
paths:
- "go.mod"
- "go.sum"
- "**/*.go"
- "config.example.yaml"
- "Dockerfile"
- "Makefile"
workflow_dispatch:
env: env:
DOCKER_REGISTRY: gitea.t000-n.de DOCKER_REGISTRY: gitea.t000-n.de
@@ -22,14 +14,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 uses: actions/checkout@v4
- name: Setup go - name: Setup go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version-file: go.mod
check-latest: true check-latest: true
- name: Create cache key - name: Create cache key
uses: https://gitea.com/actions/go-hashfiles@264ae76b7e50173ce71ed7da4b48e5e517f3f9ec # v0.0.1 uses: https://gitea.com/actions/go-hashfiles@v0.0.1
id: hash-go id: hash-go
with: with:
patterns: | patterns: |
@@ -37,7 +29,7 @@ jobs:
go.sum go.sum
- name: cache go - name: cache go
id: cache-go id: cache-go
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5 uses: actions/cache@v4
with: with:
path: | path: |
/go_path /go_path
@@ -52,90 +44,41 @@ jobs:
build_and_push: build_and_push:
name: Build and push name: Build and push
strategy:
matrix:
arch: [amd64, arm64]
needs: needs:
- test - test
runs-on: runs-on: ubuntu-latest
- ubuntu-latest
- linux_${{ matrix.arch }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 uses: docker/setup-buildx-action@v2
- name: Login to Registry - name: Login to Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 uses: docker/login-action@v2
with: with:
registry: ${{ env.DOCKER_REGISTRY }} registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ secrets.REGISTRY_USER }} username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }} password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Get Metadata - name: Get Metadata
id: meta id: meta
run: | run: |
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}' | tr '[:upper:]' '[:lower:]') >> $GITHUB_OUTPUT echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}' | tr '[:upper:]' '[:lower:]') >> $GITHUB_OUTPUT
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
- name: Build and push - name: Build and push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 uses: docker/build-push-action@v4
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
platforms: linux/${{ matrix.arch }} platforms: |
linux/amd64
linux/arm64
push: true push: true
provenance: false
build-args: GOARCH=${{ matrix.arch }}
tags: | tags: |
${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-${{ matrix.arch }} ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:latest
create_tag:
name: Create tag
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.new-tag }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
fetch-depth: 0
- uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@0.1.20
id: tag
with:
token: ${{ secrets.GITEA_TOKEN }}
prerelease: ${{ github.event_name == 'workflow_dispatch' }}
- run: |
git tag ${{ steps.tag.outputs.new-tag }}
git push origin ${{ steps.tag.outputs.new-tag }}
- name: Set output
run: |
echo "tag=${{ steps.tag.outputs.new-tag }}" >> $GITHUB_OUTPUT
create_manifest:
name: Create manifest
needs:
- build_and_push
- create_tag
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Get Metadata
id: meta
run: |
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}' | tr '[:upper:]' '[:lower:]') >> $GITHUB_OUTPUT
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
- name: Login to Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Create manifest
run: |
docker manifest create ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ needs.create_tag.outputs.tag }} \
${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-amd64 \
${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-arm64
docker manifest push ${{ env.DOCKER_REGISTRY }}/t.behrendt/${{ steps.meta.outputs.REPO_NAME }}:${{ needs.create_tag.outputs.tag }}

View File

@@ -13,14 +13,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 uses: actions/checkout@v4
- name: Setup go - name: Setup go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version-file: go.mod
check-latest: true check-latest: true
- name: Create cache key - name: Create cache key
uses: https://gitea.com/actions/go-hashfiles@264ae76b7e50173ce71ed7da4b48e5e517f3f9ec # v0.0.1 uses: https://gitea.com/actions/go-hashfiles@v0.0.1
id: hash-go id: hash-go
with: with:
patterns: | patterns: |
@@ -28,7 +28,7 @@ jobs:
go.sum go.sum
- name: cache go - name: cache go
id: cache-go id: cache-go
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5 uses: actions/cache@v4
with: with:
path: | path: |
/go_path /go_path

View File

@@ -1,14 +1,13 @@
FROM golang:1.25-alpine@sha256:26111811bc967321e7b6f852e914d14bede324cd1accb7f81811929a6a57fea9 as build FROM golang:1.23-alpine
ARG GOARCH=amd64
WORKDIR /app WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${GOARCH} \
go build -trimpath -ldflags="-s -w" -o main .
FROM gcr.io/distroless/static-debian12@sha256:4b2a093ef4649bccd586625090a3c668b254cfe180dee54f4c94f3e9bd7e381e COPY go.mod go.sum ./
COPY --from=build /app/main /
CMD ["/main"] RUN go mod download
COPY . .
RUN go build -o main .
CMD ["./main"]

View File

@@ -38,7 +38,6 @@ domains:
- www - www
check_interval: 0 0 0/6 * * * * check_interval: 0 0 0/6 * * * *
mode: Scheduled mode: Scheduled
log_level: info
``` ```
The config file is expected to be in the same directory as the binary and called `config.yaml`. For the OCR image, the root directory is `/app`. The config file is expected to be in the same directory as the binary and called `config.yaml`. For the OCR image, the root directory is `/app`.

View File

@@ -21,4 +21,3 @@ domains:
- www - www
check_interval: 0 0 0/6 * * * * check_interval: 0 0 0/6 * * * *
mode: Scheduled mode: Scheduled
log_level: info

5
go.mod
View File

@@ -1,16 +1,15 @@
module realdnydns module realdnydns
go 1.25.0 go 1.23
require ( require (
github.com/go-co-op/gocron v1.37.0 github.com/go-co-op/gocron v1.37.0
github.com/go-co-op/gocron/v2 v2.19.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/stretchr/testify v1.11.1 // indirect github.com/stretchr/testify v1.8.4 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
) )

7
go.sum
View File

@@ -4,8 +4,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
github.com/go-co-op/gocron/v2 v2.18.0/go.mod h1:Zii6he+Zfgy5W9B+JKk/KwejFOW0kZTFvHtwIpR4aBI=
github.com/go-co-op/gocron/v2 v2.19.0/go.mod h1:5lEiCKk1oVJV39Zg7/YG10OnaVrDAV5GGR6O0663k6U=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -32,9 +30,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=

48
main.go
View File

@@ -25,7 +25,8 @@ func main() {
configClient := config.Config{} configClient := config.Config{}
err := configClient.Load("config.yaml") err := configClient.Load("config.yaml")
if err != nil { if err != nil {
logger.Error("Failed to load config file", slog.String("error", err.Error())) logger.Error("Failed to load config file",
slog.String("error", err.Error()))
panic(err) panic(err)
} }
@@ -38,64 +39,39 @@ func main() {
var externalIpProvider externalIpProvider.ExternalIpProvider var externalIpProvider externalIpProvider.ExternalIpProvider
switch configClient.ExternalIPProvider.Type { switch configClient.ExternalIPProvider.Type {
case "plain": case "plain":
logger.Info("Using plain external IP provider", slog.String("external_ip_provider", "plain"))
var plainConfig plainExternalIpProvider.PlainExternalIpProviderConfig var plainConfig plainExternalIpProvider.PlainExternalIpProviderConfig
err := configClient.ExternalIPProvider.ProviderConfig.Decode(&plainConfig) err := configClient.ExternalIPProvider.ProviderConfig.Decode(&plainConfig)
if err != nil { if err != nil {
logger.Error("Failed to create config",
slog.String("external_ip_provider", "plain"),
slog.String("error", err.Error()),
)
panic(err) panic(err)
} }
externalIpProvider, err = plainExternalIpProvider.New(plainConfig) externalIpProvider, err = plainExternalIpProvider.New(plainConfig)
if err != nil { if err != nil {
logger.Error("Failed to create plain external IP provider",
slog.String("external_ip_provider", "plain"),
slog.String("error", err.Error()),
)
panic(err) panic(err)
} }
default: default:
logger.Error("Unknown external IP provider", slog.String("external_ip_provider", configClient.ExternalIPProvider.Type))
panic(fmt.Errorf("unknown external IP provider: %s", configClient.ExternalIPProvider.Type)) panic(fmt.Errorf("unknown external IP provider: %s", configClient.ExternalIPProvider.Type))
} }
var dnsProvider dnsProvider.DNSProvider var dnsProvider dnsProvider.DNSProvider
switch configClient.DNSProvider.Type { switch configClient.DNSProvider.Type {
case "ionos": case "ionos":
logger.Info("Using IONOS DNS provider", slog.String("dns_provider", "ionos"))
var ionosConfig ionos.IONOSConfig var ionosConfig ionos.IONOSConfig
err := configClient.DNSProvider.ProviderConfig.Decode(&ionosConfig) err := configClient.DNSProvider.ProviderConfig.Decode(&ionosConfig)
if err != nil { if err != nil {
logger.Error("Failed to create IONOS DNS provider",
slog.String("dns_provider", "ionos"),
slog.String("error", err.Error()),
)
panic(err) panic(err)
} }
dnsProvider, err = ionos.NewIonos(&ionosConfig) dnsProvider, err = ionos.NewIonos(&ionosConfig)
if err != nil { if err != nil {
logger.Error("Failed to create IONOS DNS provider",
slog.String("dns_provider", "ionos"),
slog.String("error", err.Error()),
)
panic(err) panic(err)
} }
default: default:
logger.Error("Unknown DNS provider", slog.String("dns_provider", configClient.DNSProvider.Type))
panic(fmt.Errorf("unknown DNS provider: %s", configClient.DNSProvider.Type)) panic(fmt.Errorf("unknown DNS provider: %s", configClient.DNSProvider.Type))
} }
var notificationProvider notificationProvider.NotificationProvider var notificationProvider notificationProvider.NotificationProvider
switch configClient.NotificationProvider.Type { switch configClient.NotificationProvider.Type {
case "gotify": case "gotify":
logger.Info("Using Gotify notification provider", slog.String("notification_provider", "gotify"))
var gotifyConfig gotify.NotificationProviderImplGotifyConfig var gotifyConfig gotify.NotificationProviderImplGotifyConfig
err := configClient.NotificationProvider.ProviderConfig.Decode(&gotifyConfig) err := configClient.NotificationProvider.ProviderConfig.Decode(&gotifyConfig)
if err != nil { if err != nil {
@@ -104,39 +80,29 @@ func main() {
notificationProvider, err = gotify.New(gotifyConfig) notificationProvider, err = gotify.New(gotifyConfig)
if err != nil { if err != nil {
logger.Error("Failed to create Gotify notification provider",
slog.String("notification_provider", "gotify"),
slog.String("error", err.Error()),
)
panic(err) panic(err)
} }
default: default:
logger.Info("Using console notification provider", slog.String("notification_provider", "console"))
notificationProvider = notificationProviderConsole.New() notificationProvider = notificationProviderConsole.New()
} }
rdd := realDynDns.New(externalIpProvider, dnsProvider, notificationProvider, configClient.Domains, logger.With(slog.String("service", "realDynDns"))) rdd := realDynDns.New(externalIpProvider, dnsProvider, notificationProvider, configClient.Domains)
switch configClient.Mode { switch configClient.Mode {
case config.ScheduledMode: case config.ScheduledMode:
logger.Info("Running in scheduled mode", slog.String("interval", configClient.CheckInterval))
schedule, job, err := rdd.RunWithSchedule(configClient.CheckInterval) schedule, job, err := rdd.RunWithSchedule(configClient.CheckInterval)
if err != nil { if err != nil {
logger.Error("Failed to create scheduler", slog.String("error", err.Error()))
panic(err) panic(err)
} }
logger.Info("Next run:", slog.String("time", job.NextRun().String())) fmt.Println("Starting scheduler")
fmt.Println("Next run:", job.NextRun())
schedule.StartBlocking() schedule.StartBlocking()
case config.RunOnceMode: case config.RunOnceMode:
logger.Info("Running in run once mode") numberOfChanges, err := rdd.RunOnce()
_, err := rdd.RunOnce()
if err != nil { if err != nil {
logger.Error("Failed to run once", slog.String("error", err.Error()))
panic(err) panic(err)
} }
fmt.Println("Number of changes:", numberOfChanges)
} }
} }

View File

@@ -2,7 +2,6 @@ package externalIpProvider
import ( import (
"errors" "errors"
"io"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
@@ -41,15 +40,12 @@ func (p *ExternalIpProviderImplPlain) GetExternalIp() (net.IP, error) {
} }
if res.StatusCode != 200 { if res.StatusCode != 200 {
res.Body.Close()
return nil, errors.New("unexpected status code") return nil, errors.New("unexpected status code")
} }
responseBody, err := io.ReadAll(res.Body) responseBody := make([]byte, res.ContentLength)
res.Body.Close() res.Body.Read(responseBody)
if err != nil { defer res.Body.Close()
return nil, err
}
parsedIp := net.ParseIP(string(responseBody)) parsedIp := net.ParseIP(string(responseBody))
if parsedIp == nil { if parsedIp == nil {

View File

@@ -2,8 +2,6 @@ package realDynDns
import ( import (
"fmt" "fmt"
"log/slog"
"sync"
"time" "time"
"realdnydns/pkg/config" "realdnydns/pkg/config"
@@ -19,7 +17,6 @@ type ChangeDetector struct {
dnsProvider dnsProvider.DNSProvider dnsProvider dnsProvider.DNSProvider
notificationProvider notificationProvider.NotificationProvider notificationProvider notificationProvider.NotificationProvider
domains []config.DomainConfig domains []config.DomainConfig
logger *slog.Logger
} }
func New( func New(
@@ -27,14 +24,12 @@ func New(
dnsProvider dnsProvider.DNSProvider, dnsProvider dnsProvider.DNSProvider,
notificationProvider notificationProvider.NotificationProvider, notificationProvider notificationProvider.NotificationProvider,
domains []config.DomainConfig, domains []config.DomainConfig,
logger *slog.Logger,
) ChangeDetector { ) ChangeDetector {
return ChangeDetector{ return ChangeDetector{
externalIpProvider: externalIpProvider, externalIpProvider: externalIpProvider,
dnsProvider: dnsProvider, dnsProvider: dnsProvider,
notificationProvider: notificationProvider, notificationProvider: notificationProvider,
domains: domains, domains: domains,
logger: logger,
} }
} }
@@ -63,90 +58,37 @@ func (c *ChangeDetector) RunOnce() (int, error) {
} }
func (c *ChangeDetector) detectAndApplyChanges() (int, error) { func (c *ChangeDetector) detectAndApplyChanges() (int, error) {
c.logger.Info("Detecting and applying changes")
externalIp, err := c.externalIpProvider.GetExternalIp() externalIp, err := c.externalIpProvider.GetExternalIp()
if err != nil { if err != nil {
c.logger.Error("Failed to retrieve external IP", slog.String("error", err.Error()))
return 0, err return 0, err
} }
var wg sync.WaitGroup var numberUpdated int
numberUpdatedChannel := make(chan int)
for _, domain := range c.domains { for _, domain := range c.domains {
for _, subdomain := range domain.Subdomains { for _, subdomain := range domain.Subdomains {
wg.Add(1)
go func(domain config.DomainConfig, subdomain string) {
defer wg.Done()
c.logger.Info("Checking record",
slog.String("tld", domain.TLD),
slog.String("subdomain", subdomain),
)
currentRecord, err := c.dnsProvider.GetRecord(domain.TLD, subdomain) currentRecord, err := c.dnsProvider.GetRecord(domain.TLD, subdomain)
if err != nil { if err != nil {
c.logger.Error("Failed to retrieve record", return numberUpdated, err
slog.String("error", err.Error()),
slog.String("tld", domain.TLD),
slog.String("subdomain", subdomain),
)
return
} }
if currentRecord.IP != externalIp.String() { if currentRecord.IP != externalIp.String() {
c.logger.Info("Record has changed",
slog.String("tld", domain.TLD),
slog.String("subdomain", subdomain),
slog.String("current_ip", currentRecord.IP),
slog.String("external_ip", externalIp.String()),
)
err = c.notificationProvider.SendNotification( err = c.notificationProvider.SendNotification(
fmt.Sprintf("Update %s.%s", subdomain, domain.TLD), fmt.Sprintf("Update %s.%s", subdomain, domain.TLD),
fmt.Sprintf("The IP of %s has changed from %s to %s", domain.TLD, currentRecord.IP, externalIp.String()), fmt.Sprintf("The IP of %s has changed from %s to %s", domain.TLD, currentRecord.IP, externalIp.String()),
) )
if err != nil { if err != nil {
c.logger.Warn("Failed to send notification", return numberUpdated, err
slog.String("error", err.Error()),
)
return
} }
c.logger.Info("Updating record",
slog.String("tld", domain.TLD),
slog.String("subdomain", subdomain),
slog.String("current_ip", currentRecord.IP),
slog.String("external_ip", externalIp.String()),
)
_, err = c.dnsProvider.UpdateRecord(domain.TLD, subdomain, externalIp, currentRecord.TTL, currentRecord.Prio, currentRecord.Disabled) _, err = c.dnsProvider.UpdateRecord(domain.TLD, subdomain, externalIp, currentRecord.TTL, currentRecord.Prio, currentRecord.Disabled)
numberUpdated++
if err != nil { if err != nil {
c.logger.Error("Failed to update record", return numberUpdated, err
slog.String("error", err.Error()),
slog.String("tld", domain.TLD),
slog.String("subdomain", subdomain),
)
return
} }
numberUpdatedChannel <- 1
} }
}(domain, subdomain)
} }
} }
go func() {
wg.Wait()
close(numberUpdatedChannel)
}()
numberUpdated := 0
for v := range numberUpdatedChannel {
numberUpdated += v
}
c.logger.Info("Run completed", slog.Int("number_of_changes", numberUpdated))
return numberUpdated, nil return numberUpdated, nil
} }

View File

@@ -1,7 +1,6 @@
package realDynDns package realDynDns
import ( import (
"log/slog"
"net" "net"
"realdnydns/model/common" "realdnydns/model/common"
"realdnydns/pkg/config" "realdnydns/pkg/config"
@@ -73,9 +72,7 @@ func testDetectAndApplyChangesWithChanges() func(t *testing.T) {
"@", "@",
}, },
}, },
}, })
slog.Default(),
)
numberUpdated, err := changeDetector.RunOnce() numberUpdated, err := changeDetector.RunOnce()
if err != nil { if err != nil {
@@ -104,9 +101,7 @@ func testDetectAndApplyChangesWithoutChanges() func(t *testing.T) {
"@", "@",
}, },
}, },
}, })
slog.Default(),
)
numberUpdated, err := changeDetector.RunOnce() numberUpdated, err := changeDetector.RunOnce()
if err != nil { if err != nil {

View File

@@ -1,22 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>t.behrendt/renovate-configs:common",
"local>t.behrendt/renovate-configs:action"
],
"packageRules": [
{
"matchPackageNames": [
"golang",
"gomod",
"go"
],
"groupName": "go version",
"matchUpdateTypes": [
"major",
"minor",
"patch"
]
}
]
}