From 07d7645d787a81e3a6c5ee52b9ec3ccf65a4c2ea Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Thu, 27 Jun 2024 13:03:59 +0000 Subject: [PATCH] feat(config): read both owner and domain from domain - retro-compatible change: keep using host/owner if set - otherwise extract owner and eTLD+1 from domain field - documentation updated to only use the `domain` field --- README.md | 8 ++-- config.json | 4 +- docs/aliyun.md | 4 +- docs/allinkl.md | 6 +-- docs/changeip.md | 6 +-- docs/cloudflare.md | 4 +- docs/custom.md | 4 +- docs/dd24.md | 4 +- docs/ddnss.de.md | 4 +- docs/desec.md | 6 +-- docs/digitalocean.md | 4 +- docs/dnsomatic.md | 4 +- docs/dnspod.md | 4 +- docs/dondominio.md | 4 +- docs/dreamhost.md | 3 +- docs/duckdns.md | 4 +- docs/dyndns.md | 4 +- docs/dynu.md | 4 +- docs/dynv6.md | 4 +- docs/easydns.md | 4 +- docs/example.md | 4 +- docs/freedns.md | 6 +-- docs/gandi.md | 4 +- docs/gcp.md | 4 +- docs/godaddy.md | 4 +- docs/goip.md | 5 +-- docs/he.net.md | 4 +- docs/hetzner.md | 4 +- docs/infomaniak.md | 4 +- docs/inwx.md | 4 +- docs/ionos.md | 4 +- docs/linode.md | 4 +- docs/luadns.md | 4 +- docs/name.com.md | 4 +- docs/namecheap.md | 4 +- docs/netcup.md | 4 +- docs/njalla.md | 4 +- docs/noip.md | 4 +- docs/opendns.md | 4 +- docs/ovh.md | 4 +- docs/porkbun.md | 4 +- docs/route53.md | 4 +- docs/selfhost.de.md | 4 +- docs/servercow.md | 4 +- docs/spdyn.md | 4 +- docs/strato.md | 4 +- docs/variomedia.md | 4 +- docs/zoneedit.md | 4 +- go.mod | 2 +- internal/params/json.go | 72 ++++++++++++++++++++++++++---------- internal/params/json_test.go | 66 +++++++++++++++++++++++++++++++++ 51 files changed, 175 insertions(+), 169 deletions(-) create mode 100644 internal/params/json_test.go diff --git a/README.md b/README.md index cfd47b85a..00c3966f7 100644 --- a/README.md +++ b/README.md @@ -120,8 +120,7 @@ This readme and the [docs/](docs/) directory are **versioned** to match the prog "settings": [ { "provider": "namecheap", - "domain": "example.com", - "owner": "@", + "domain": "sub.example.com", "password": "e5322165c1d74692bfa6d807100c0310" } ] @@ -165,8 +164,7 @@ This readme and the [docs/](docs/) directory are **versioned** to match the prog "settings": [ { "provider": "namecheap", - "domain": "example.com", - "owner": "@", + "domain": "sub.example.com", "password": "e5322165c1d74692bfa6d807100c0310" } ] @@ -256,7 +254,7 @@ Check the documentation for your DNS provider: Note that: -- you can specify multiple hosts for the same domain using a comma separated list. For example with `"owner": "@,subdomain1,subdomain2",`. +- you can specify multiple owners/hosts for the same domain using a comma separated list. For example with `"domain": "example.com,sub.example.com,sub2.example.com",`. ### Environment variables diff --git a/config.json b/config.json index b4de97d65..d2c535157 100644 --- a/config.json +++ b/config.json @@ -3,7 +3,6 @@ { "provider": "namecheap", "domain": "example.com", - "owner": "@", "password": "e5322165c1d74692bfa6d807100c0310" }, { @@ -13,8 +12,7 @@ }, { "provider": "godaddy", - "domain": "example.org", - "owner": "subdomain", + "domain": "subdomain.example.org", "key": "aaaaaaaaaaaaaaaa", "secret": "aaaaaaaaaaaaaaaa" }, diff --git a/docs/aliyun.md b/docs/aliyun.md index 10a05a85e..c2adab60d 100644 --- a/docs/aliyun.md +++ b/docs/aliyun.md @@ -10,7 +10,6 @@ { "provider": "aliyun", "domain": "domain.com", - "owner": "@", "access_key_id": "your access_key_id", "access_secret": "your access_secret", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"access_key_id"` - `"access_secret"` diff --git a/docs/allinkl.md b/docs/allinkl.md index 1ae896716..c26daf85f 100644 --- a/docs/allinkl.md +++ b/docs/allinkl.md @@ -9,8 +9,7 @@ "settings": [ { "provider": "allinkl", - "domain": "domain.com", - "owner": "sub", + "domain": "sub.domain.com", "username": "dynXXXXXXX", "password": "password", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` username (usually starts with dyn followed by numbers) - `"password"` password in plain text diff --git a/docs/changeip.md b/docs/changeip.md index cee17b2ca..ec05cea01 100644 --- a/docs/changeip.md +++ b/docs/changeip.md @@ -9,8 +9,7 @@ "settings": [ { "provider": "changeip", - "domain": "domain.com", - "owner": "sub", + "domain": "sub.domain.com", "username": "dynXXXXXXX", "password": "password", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` - `"password"` diff --git a/docs/cloudflare.md b/docs/cloudflare.md index fc5429cb8..50c3a7782 100644 --- a/docs/cloudflare.md +++ b/docs/cloudflare.md @@ -11,7 +11,6 @@ "provider": "cloudflare", "zone_identifier": "some id", "domain": "domain.com", - "owner": "@", "ttl": 600, "token": "yourtoken", "ip_version": "ipv4", @@ -24,8 +23,7 @@ ### Compulsory parameters - `"zone_identifier"` is the Zone ID of your site, from the domain overview page written as *Zone ID* -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. See [this issue comment for context](https://github.com/qdm12/ddns-updater/issues/243#issuecomment-928313949). This is left as is for compatibility. - `"ttl"` integer value for record TTL in seconds (specify 1 for automatic) - One of the following ([how to find API keys](https://developers.cloudflare.com/fundamentals/api/get-started/)): diff --git a/docs/custom.md b/docs/custom.md index 2ed1b65fb..65753e13e 100644 --- a/docs/custom.md +++ b/docs/custom.md @@ -15,7 +15,6 @@ Feel free to open issues to extend its configuration options. { "provider": "custom", "domain": "example.com", - "owner": "@", "url": "https://example.com/update?domain=example.com&host=@&username=username&client_key=client_key", "ipv4key": "ipv4", "ipv6key": "ipv6", @@ -29,8 +28,7 @@ Feel free to open issues to extend its configuration options. ### Compulsory parameters -- `"domain"` is the domain name to update -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"url"` is the URL to update your records and should contain all the information EXCEPT the IP address to update - `"ipv4key"` is the URL query parameter name for the IPv4 address, for example `ipv4` will be added to the URL with `&ipv4=1.2.3.4`. - `"ipv6key"` is the URL query parameter name for the IPv6 address, for example `ipv6` will be added to the URL with `&ipv6=::aaff`. Even if you don't use IPv6, this must be set to something. diff --git a/docs/dd24.md b/docs/dd24.md index b4489bfa7..670455ffc 100644 --- a/docs/dd24.md +++ b/docs/dd24.md @@ -10,7 +10,6 @@ { "provider": "dd24", "domain": "domain.com", - "owner": "@", "password": "password", "ip_version": "ipv4", "ipv6_suffix": "" @@ -21,8 +20,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"password"` is your password ### Optional parameters diff --git a/docs/ddnss.de.md b/docs/ddnss.de.md index f535b500b..733af4119 100644 --- a/docs/ddnss.de.md +++ b/docs/ddnss.de.md @@ -11,7 +11,6 @@ "provider": "ddnss", "provider_ip": true, "domain": "domain.com", - "owner": "@", "username": "user", "password": "password", "dual_stack": false, @@ -24,8 +23,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` - `"password"` diff --git a/docs/desec.md b/docs/desec.md index 6a01e75ba..d3939535f 100644 --- a/docs/desec.md +++ b/docs/desec.md @@ -9,8 +9,7 @@ "settings": [ { "provider": "desec", - "domain": "dedyn.io", - "owner": "sub", + "domain": "sub.dedyn.io", "token": "token", "ip_version": "ipv4", "ipv6_suffix": "", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"token"` is your token that you can create [here](https://desec.io/tokens) ### Optional parameters diff --git a/docs/digitalocean.md b/docs/digitalocean.md index a995c492a..8789df939 100644 --- a/docs/digitalocean.md +++ b/docs/digitalocean.md @@ -10,7 +10,6 @@ { "provider": "digitalocean", "domain": "domain.com", - "owner": "@", "token": "yourtoken", "ip_version": "ipv4", "ipv6_suffix": "" @@ -21,8 +20,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"token"` is your token that you can create [here](https://cloud.digitalocean.com/settings/applications) ### Optional parameters diff --git a/docs/dnsomatic.md b/docs/dnsomatic.md index 671f9a249..56b8e03cf 100644 --- a/docs/dnsomatic.md +++ b/docs/dnsomatic.md @@ -10,7 +10,6 @@ { "provider": "dnsomatic", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "provider_ip": true, @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` - `"password"` - `"provider_ip"` diff --git a/docs/dnspod.md b/docs/dnspod.md index 2a53ec653..56f9f05b0 100644 --- a/docs/dnspod.md +++ b/docs/dnspod.md @@ -10,7 +10,6 @@ { "provider": "dnspod", "domain": "domain.com", - "owner": "@", "token": "yourtoken", "ip_version": "ipv4", "ipv6_suffix": "" @@ -21,8 +20,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"token"` ### Optional parameters diff --git a/docs/dondominio.md b/docs/dondominio.md index 2fa58c933..45714344b 100644 --- a/docs/dondominio.md +++ b/docs/dondominio.md @@ -10,7 +10,6 @@ { "provider": "dondominio", "domain": "domain.com", - "owner": "@", "name": "something", "username": "username", "key": "key", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"name"` is the name of the service/hosting - `"username"` - `"password"` diff --git a/docs/dreamhost.md b/docs/dreamhost.md index 2fdd0a985..4c2e035c7 100644 --- a/docs/dreamhost.md +++ b/docs/dreamhost.md @@ -10,7 +10,6 @@ { "provider": "dreamhost", "domain": "domain.com", - "owner": "@", "key": "key", "ip_version": "ipv4", "ipv6_suffix": "" @@ -26,7 +25,7 @@ ### Optional parameters -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`. - `"ipv6_suffix"` is the IPv6 interface identifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating. diff --git a/docs/duckdns.md b/docs/duckdns.md index 4a73ae5ff..7e9f71c5f 100644 --- a/docs/duckdns.md +++ b/docs/duckdns.md @@ -9,7 +9,7 @@ "settings": [ { "provider": "duckdns", - "owner": "sub", + "domain": "sub.duckdns.org", "token": "token", "ip_version": "ipv4", "ipv6_suffix": "", @@ -21,7 +21,7 @@ ### Compulsory parameters -- `"owner"` is the resource record owner and can be for example `"sub"` for the domain `sub.duckdns.org` +- `"domain"` is the domain to update. For example, for the owner/host `sub`, it would be `sub.duckdns.org`. The [eTLD+1](https://developer.mozilla.org/en-US/docs/Glossary/eTLD) must be `duckdns.org`. - `"token"` ### Optional parameters diff --git a/docs/dyndns.md b/docs/dyndns.md index ce86c9782..825273cb0 100644 --- a/docs/dyndns.md +++ b/docs/dyndns.md @@ -10,7 +10,6 @@ { "provider": "dyn", "domain": "domain.com", - "owner": "@", "username": "username", "client_key": "client_key", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` - `"client_key"` diff --git a/docs/dynu.md b/docs/dynu.md index 49b0e17e2..ab248d24a 100644 --- a/docs/dynu.md +++ b/docs/dynu.md @@ -10,7 +10,6 @@ { "provider": "dynu", "domain": "domain.com", - "owner": "@", "group": "group", "username": "username", "password": "password", @@ -24,8 +23,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` - `"password"` could be plain text or password in MD5 or SHA256 format (There's also an option for setting a password for IP Update only) diff --git a/docs/dynv6.md b/docs/dynv6.md index 4cc2fd983..f454378f9 100644 --- a/docs/dynv6.md +++ b/docs/dynv6.md @@ -10,7 +10,6 @@ { "provider": "dynv6", "domain": "domain.com", - "owner": "@", "token": "token", "ip_version": "ipv4", "ipv6_suffix": "", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"token"` that you can obtain [here](https://dynv6.com/keys#token) ### Optional parameters diff --git a/docs/easydns.md b/docs/easydns.md index 30409f356..323df5433 100644 --- a/docs/easydns.md +++ b/docs/easydns.md @@ -10,7 +10,6 @@ { "provider": "easydns", "domain": "domain.com", - "owner": "@", "username": "username", "token": "token", "ip_version": "ipv4", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` - `"token"` diff --git a/docs/example.md b/docs/example.md index de14e21a9..6eec0d187 100644 --- a/docs/example.md +++ b/docs/example.md @@ -12,7 +12,6 @@ { "provider": "example", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "ip_version": "ipv4", @@ -24,8 +23,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` - `"password"` diff --git a/docs/freedns.md b/docs/freedns.md index a301b9c35..11e4a4fd3 100644 --- a/docs/freedns.md +++ b/docs/freedns.md @@ -9,8 +9,7 @@ "settings": [ { "provider": "freedns", - "domain": "domain.com", - "owner": "sub", + "domain": "sub.domain.com", "token": "token", "ip_version": "ipv4", "ipv6_suffix": "" @@ -21,8 +20,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"token"` is the randomized update token you use to update your record ### Optional parameters diff --git a/docs/gandi.md b/docs/gandi.md index 8b8f599b2..c1207dc6c 100644 --- a/docs/gandi.md +++ b/docs/gandi.md @@ -12,7 +12,6 @@ This provider uses Gandi v5 API { "provider": "gandi", "domain": "domain.com", - "owner": "@", "personal_access_token": "token", "ttl": 3600, "ip_version": "ipv4", @@ -24,8 +23,7 @@ This provider uses Gandi v5 API ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"personal_access_token"` ### Optional parameters diff --git a/docs/gcp.md b/docs/gcp.md index b5d9aa03d..4a782cde2 100644 --- a/docs/gcp.md +++ b/docs/gcp.md @@ -17,7 +17,6 @@ // ... }, "domain": "domain.com", - "owner": "@", "ip_version": "ipv4", "ipv6_suffix": "" } @@ -30,8 +29,7 @@ - `"project"` is the id of your Google Cloud project - `"zone"` is the zone, that your DNS record is located in - `"credentials"` is the JSON credentials for your Google Cloud project. This is usually downloaded as a JSON file, which you can copy paste the content as the value of the `"credentials"` key. More information on how to get it is available [here](https://cloud.google.com/docs/authentication/getting-started). Please ensure your service account has all necessary permissions to create/update/list/get DNS records within your project. -- `"domain"` is the TLD of you DNS record (without a trailing dot) -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. ### Optional parameters diff --git a/docs/godaddy.md b/docs/godaddy.md index f3bf934fd..58f335a74 100644 --- a/docs/godaddy.md +++ b/docs/godaddy.md @@ -10,7 +10,6 @@ { "provider": "godaddy", "domain": "domain.com", - "owner": "@", "key": "key", "secret": "secret", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"key"` - `"secret"` diff --git a/docs/goip.md b/docs/goip.md index 996c4a303..2aea662ec 100644 --- a/docs/goip.md +++ b/docs/goip.md @@ -9,8 +9,7 @@ "settings": [ { "provider": "goip", - "domain": "goip.de", - "owner": "mysubdomain", + "domain": "mysubdomain.goip.de", "username": "username", "password": "password", "provider_ip": true, @@ -24,7 +23,7 @@ ### Compulsory parameters -- `"owner"` is the resource record owner and can be for example `"example"` for `example.goip.de`. +- `"domain"` is the domain to update. For example, for the owner/host `sub`, it would be `sub.goip.de`. The [eTLD+1](https://developer.mozilla.org/en-US/docs/Glossary/eTLD) must be `goip.de` or `goip.it`. - `"username"` is your goip.de username listed under "Routers" - `"password"` is your router account password diff --git a/docs/he.net.md b/docs/he.net.md index f0eee5f9a..b4e57c8e6 100644 --- a/docs/he.net.md +++ b/docs/he.net.md @@ -10,7 +10,6 @@ { "provider": "he", "domain": "domain.com", - "owner": "@", "password": "password", "provider_ip": true, "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` (untested) +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. (untested) - `"password"` ### Optional parameters diff --git a/docs/hetzner.md b/docs/hetzner.md index f5368eb8d..89e247d05 100644 --- a/docs/hetzner.md +++ b/docs/hetzner.md @@ -11,7 +11,6 @@ "provider": "hetzner", "zone_identifier": "some id", "domain": "domain.com", - "owner": "@", "ttl": 600, "token": "yourtoken", "ip_version": "ipv4", @@ -24,8 +23,7 @@ ### Compulsory parameters - `"zone_identifier"` is the Zone ID of your site, from the domain overview page written as *Zone ID* -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"ttl"` optional integer value corresponding to a number of seconds - One of the following ([how to find API keys](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token)): - API Token `"token"`, configured with DNS edit permissions for your DNS name's zone diff --git a/docs/infomaniak.md b/docs/infomaniak.md index d62af2728..0212aff10 100644 --- a/docs/infomaniak.md +++ b/docs/infomaniak.md @@ -10,7 +10,6 @@ { "provider": "infomaniak", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "ip_version": "ipv4", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` for dyndns (**not** your infomaniak admin username!) - `"password"` for dyndns (**not** your infomaniak admin password!) diff --git a/docs/inwx.md b/docs/inwx.md index 84a0ef4e7..4b06b50c9 100644 --- a/docs/inwx.md +++ b/docs/inwx.md @@ -10,7 +10,6 @@ { "provider": "inwx", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` - `"password"` diff --git a/docs/ionos.md b/docs/ionos.md index c4d9d286f..0af79dc5d 100644 --- a/docs/ionos.md +++ b/docs/ionos.md @@ -10,7 +10,6 @@ { "provider": "ionos", "domain": "domain.com", - "owner": "@", "api_key": "api_key", "ip_version": "ipv4", "ipv6_suffix": "" @@ -21,8 +20,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"api_key"` is your API key, obtained from [creating an API key](https://www.ionos.com/help/domains/configuring-your-ip-address/set-up-dynamic-dns-with-company-name/#c181598) ### Optional parameters diff --git a/docs/linode.md b/docs/linode.md index 5a791b15a..076502a2b 100644 --- a/docs/linode.md +++ b/docs/linode.md @@ -10,7 +10,6 @@ { "provider": "linode", "domain": "domain.com", - "owner": "@", "token": "token", "ip_version": "ipv4", "ipv6_suffix": "" @@ -21,8 +20,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"token"` ### Optional parameters diff --git a/docs/luadns.md b/docs/luadns.md index ee1a62133..e6f97dcc7 100644 --- a/docs/luadns.md +++ b/docs/luadns.md @@ -10,7 +10,6 @@ { "provider": "luadns", "domain": "domain.com", - "owner": "@", "email": "email", "token": "token", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"email"` - `"token"` diff --git a/docs/name.com.md b/docs/name.com.md index 5e14d8202..707a52a15 100644 --- a/docs/name.com.md +++ b/docs/name.com.md @@ -12,7 +12,6 @@ { "provider": "name.com", "domain": "domain.com", - "owner": "@", "username": "username", "token": "token", "ttl": 300, @@ -25,8 +24,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` is your account username - `"token"` which you can obtain from [www.name.com/account/settings/api](https://www.name.com/account/settings/api) diff --git a/docs/namecheap.md b/docs/namecheap.md index 52f3a734f..99c8f3e38 100644 --- a/docs/namecheap.md +++ b/docs/namecheap.md @@ -10,7 +10,6 @@ { "provider": "namecheap", "domain": "domain.com", - "owner": "@", "password": "password", "provider_ip": true } @@ -20,8 +19,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"password"` ### Optional parameters diff --git a/docs/netcup.md b/docs/netcup.md index 2a7b0bf4e..e4f8687af 100644 --- a/docs/netcup.md +++ b/docs/netcup.md @@ -14,7 +14,6 @@ Also keep in mind, that TTL, Expire, Retry and Refresh values of the given Domai { "provider": "netcup", "domain": "domain.com", - "owner": "@", "api_key": "xxxxx", "password": "yyyyy", "customer_number": "111111", @@ -27,8 +26,7 @@ Also keep in mind, that TTL, Expire, Retry and Refresh values of the given Domai ### Compulsory parameters -- `"domain"` is your domain -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` or `"@"` for the root of the domain. It cannot be the wildcard. +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"api_key"` is your api key (generated in the [customercontrolpanel](https://www.customercontrolpanel.de)) - `"password"` is your api password (generated in the [customercontrolpanel](https://www.customercontrolpanel.de)). Netcup only allows one ApiPassword. This is not the account password. This password is used for all api keys. - `"customer_number"` is your customer number (viewable in the [customercontrolpanel](https://www.customercontrolpanel.de) next to your name). As seen in the example above, provide the number as string value. diff --git a/docs/njalla.md b/docs/njalla.md index 19e0f53ac..1efb67209 100644 --- a/docs/njalla.md +++ b/docs/njalla.md @@ -10,7 +10,6 @@ { "provider": "njalla", "domain": "domain.com", - "owner": "@", "key": "key", "ip_version": "ipv4", "ipv6_suffix": "", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"key"` is the key for your record ### Optional parameters diff --git a/docs/noip.md b/docs/noip.md index 7cfdd79a0..9c84178a0 100644 --- a/docs/noip.md +++ b/docs/noip.md @@ -10,7 +10,6 @@ { "provider": "noip", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "ip_version": "ipv4", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` - `"password"` diff --git a/docs/opendns.md b/docs/opendns.md index 0d4dfe06b..96caa31ab 100644 --- a/docs/opendns.md +++ b/docs/opendns.md @@ -10,7 +10,6 @@ { "provider": "opendns", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "ip_version": "ipv4", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` - `"password"` diff --git a/docs/ovh.md b/docs/ovh.md index 5cb282b9e..d71da9d7c 100644 --- a/docs/ovh.md +++ b/docs/ovh.md @@ -10,7 +10,6 @@ { "provider": "ovh", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "ip_version": "ipv4", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). #### Using DynHost diff --git a/docs/porkbun.md b/docs/porkbun.md index 8f9e5ddd9..bfc7118fa 100644 --- a/docs/porkbun.md +++ b/docs/porkbun.md @@ -10,7 +10,6 @@ { "provider": "porkbun", "domain": "domain.com", - "owner": "@", "api_key": "sk1_7d119e3f656b00ae042980302e1425a04163c476efec1833q3cb0w54fc6f5022", "secret_api_key": "pk1_5299b57125c8f3cdf347d2fe0e713311ee3a1e11f11a14942b26472593e35368", "ip_version": "ipv4", @@ -22,8 +21,7 @@ ### Compulsory Parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"apikey"` - `"secretapikey"` - `"ttl"` optional integer value corresponding to a number of seconds diff --git a/docs/route53.md b/docs/route53.md index 76e36d49d..9b4be9443 100644 --- a/docs/route53.md +++ b/docs/route53.md @@ -10,7 +10,6 @@ { "provider": "route53", "domain": "domain.com", - "owner": "@", "ip_version": "ipv4", "ipv6_suffix": "", "access_key": "ffffffffffffffffffff", @@ -24,8 +23,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"access_key"` is the `AWS_ACCESS_KEY` - `"secret_key"` is the `AWS_SECRET_ACCESS_KEY` - `"zone_id"` is identification of your hosted zone diff --git a/docs/selfhost.de.md b/docs/selfhost.de.md index 71c2241b8..fa0b97bb7 100644 --- a/docs/selfhost.de.md +++ b/docs/selfhost.de.md @@ -10,7 +10,6 @@ { "provider": "selfhost.de", "domain": "domain.com", - "owner": "@", "username": "username", "password": "password", "provider_ip": true, @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"username"` is your DynDNS username - `"password"` is your DynDNS password diff --git a/docs/servercow.md b/docs/servercow.md index 32c9ae995..3b7da48c4 100644 --- a/docs/servercow.md +++ b/docs/servercow.md @@ -10,7 +10,6 @@ { "provider": "servercow", "domain": "domain.com", - "owner": "", "username": "servercow_username", "password": "servercow_password", "ttl": 600, @@ -24,8 +23,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` is the username for your DNS API User - `"password"` is the password for your DNS API User diff --git a/docs/spdyn.md b/docs/spdyn.md index 5563c4c18..c88c35eb0 100644 --- a/docs/spdyn.md +++ b/docs/spdyn.md @@ -10,7 +10,6 @@ { "provider": "spdyn", "domain": "domain.com", - "owner": "@", "user": "user", "password": "password", "token": "token", @@ -24,8 +23,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). #### Using user and password diff --git a/docs/strato.md b/docs/strato.md index 89b8ccb78..4478e7851 100644 --- a/docs/strato.md +++ b/docs/strato.md @@ -10,7 +10,6 @@ { "provider": "strato", "domain": "domain.com", - "owner": "@", "password": "password", "ip_version": "ipv4", "ipv6_suffix": "", @@ -22,8 +21,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"password"` is your dyndns password ### Optional parameters diff --git a/docs/variomedia.md b/docs/variomedia.md index 17930596a..a0bb7fa83 100644 --- a/docs/variomedia.md +++ b/docs/variomedia.md @@ -10,7 +10,6 @@ { "provider": "variomedia", "domain": "domain.com", - "owner": "@", "email": "email@domain.com", "password": "password", "ip_version": "ipv4", @@ -23,8 +22,7 @@ ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain) or `sub.example.com` (subdomain of `example.com`). - `"email"` - `"password"` is your DNS settings password, not your account password ⚠️ diff --git a/docs/zoneedit.md b/docs/zoneedit.md index 24d4823bd..256f3354f 100644 --- a/docs/zoneedit.md +++ b/docs/zoneedit.md @@ -16,7 +16,6 @@ set the environment variable as `PERIOD=11m` to check your public IP address and { "provider": "zoneedit", "domain": "domain.com", - "owner": "@", "username": "username", "token": "token", "ip_version": "ipv4", @@ -29,8 +28,7 @@ set the environment variable as `PERIOD=11m` to check your public IP address and ### Compulsory parameters -- `"domain"` -- `"owner"` is the resource record owner and can be `"@"` for the root domain, `"*"` for the wildcard, or for example `"sub"` for the subdomain `sub.domain.com` +- `"domain"` is the domain to update. It can be `example.com` (root domain), `sub.example.com` (subdomain of `example.com`) or `*.example.com` for the wildcard. - `"username"` - `"token"` diff --git a/go.mod b/go.mod index 1de9a387f..168bd6535 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/qdm12/log v0.1.0 github.com/stretchr/testify v1.9.0 golang.org/x/mod v0.18.0 + golang.org/x/net v0.26.0 golang.org/x/oauth2 v0.21.0 ) @@ -28,7 +29,6 @@ require ( github.com/mattn/go-isatty v0.0.17 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/net v0.26.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/tools v0.22.0 // indirect diff --git a/internal/params/json.go b/internal/params/json.go index 24927f840..28f38b4e7 100644 --- a/internal/params/json.go +++ b/internal/params/json.go @@ -12,16 +12,19 @@ import ( "github.com/qdm12/ddns-updater/internal/models" "github.com/qdm12/ddns-updater/internal/provider" - "github.com/qdm12/ddns-updater/internal/provider/constants" + "github.com/qdm12/ddns-updater/internal/provider/utils" "github.com/qdm12/ddns-updater/pkg/publicip/ipversion" + "golang.org/x/net/publicsuffix" ) type commonSettings struct { Provider string `json:"provider"` Domain string `json:"domain"` // Host is kept for retro-compatibility and is replaced by Owner. - Host string `json:"host,omitempty"` - Owner string `json:"owner"` + Host string `json:"host,omitempty"` + // Owner is kept for retro-compatibility and is determined from the + // Domain field. + Owner string `json:"owner,omitempty"` IPVersion string `json:"ip_version"` IPv6Suffix netip.Prefix `json:"ipv6_suffix,omitempty"` // Retro values for warnings @@ -155,25 +158,25 @@ func makeSettingsFromObject(common commonSettings, rawSettings json.RawMessage, common.Owner = common.Host } - providerName := models.Provider(common.Provider) - if providerName == constants.DuckDNS { // only owner(s), no domain - if common.Domain != "" { // retro compatibility - if common.Owner == "" { - common.Owner = strings.TrimSuffix(common.Domain, ".duckdns.org") - warnings = append(warnings, - fmt.Sprintf("DuckDNS record should have %q specified as owner instead of %q as domain", - common.Owner, common.Domain)) - } else { - warnings = append(warnings, - fmt.Sprintf("ignoring domain %q because owner %q is specified for DuckDNS record", - common.Domain, common.Owner)) - } - common.Domain = "" // duckdns enforces empty domains + var domain string + var owners []string + if common.Owner != "" { // retro compatibility + owners = strings.Split(common.Owner, ",") + domain = common.Domain // single domain only + domains := make([]string, len(owners)) + for i, owner := range owners { + domains[i] = utils.BuildURLQueryHostname(owner, common.Domain) + } + warnings = append(warnings, + fmt.Sprintf("you can specify the owner %q directly in the domain field as %q", + common.Owner, strings.Join(domains, ","))) + } else { // extract owner(s) from domain(s) + domain, owners, err = extractFromDomainField(common.Domain) + if err != nil { + return nil, nil, fmt.Errorf("extracting owners from domains: %w", err) } } - owners := strings.Split(common.Owner, ",") - if common.IPVersion == "" { common.IPVersion = ipversion.IP4or6.String() } @@ -193,10 +196,11 @@ func makeSettingsFromObject(common commonSettings, rawSettings json.RawMessage, ipv6Suffix, ipVersion)) } + providerName := models.Provider(common.Provider) providers = make([]provider.Provider, len(owners)) for i, owner := range owners { owner = strings.TrimSpace(owner) - providers[i], err = provider.New(providerName, rawSettings, common.Domain, + providers[i], err = provider.New(providerName, rawSettings, domain, owner, ipVersion, ipv6Suffix) if err != nil { return nil, warnings, err @@ -204,3 +208,31 @@ func makeSettingsFromObject(common commonSettings, rawSettings json.RawMessage, } return providers, warnings, nil } + +var ( + ErrMultipleDomainsSpecified = errors.New("multiple domains specified") +) + +func extractFromDomainField(domainField string) (domainRegistered string, + owners []string, err error) { + domains := strings.Split(domainField, ",") + owners = make([]string, len(domains)) + for i, domain := range domains { + newDomainRegistered, err := publicsuffix.EffectiveTLDPlusOne(domain) + switch { + case err != nil: + return "", nil, fmt.Errorf("extracting effective TLD+1: %w", err) + case domainRegistered == "": + domainRegistered = newDomainRegistered + case domainRegistered != newDomainRegistered: + return "", nil, fmt.Errorf("%w: %q and %q", + ErrMultipleDomainsSpecified, domainRegistered, newDomainRegistered) + } + if domain == domainRegistered { + owners[i] = "@" + continue + } + owners[i] = strings.TrimSuffix(domain, "."+domainRegistered) + } + return domainRegistered, owners, nil +} diff --git a/internal/params/json_test.go b/internal/params/json_test.go new file mode 100644 index 000000000..c4b8eb0aa --- /dev/null +++ b/internal/params/json_test.go @@ -0,0 +1,66 @@ +package params + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_extractFromDomainField(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + domainField string + domainRegistered string + owners []string + errWrapped error + errMessage string + }{ + "root_domain": { + domainField: "example.com", + domainRegistered: "example.com", + owners: []string{"@"}, + }, + "subdomain": { + domainField: "abc.example.com", + domainRegistered: "example.com", + owners: []string{"abc"}, + }, + "two_dots_tld": { + domainField: "abc.example.co.uk", + domainRegistered: "example.co.uk", + owners: []string{"abc"}, + }, + "wildcard": { + domainField: "*.example.com", + domainRegistered: "example.com", + owners: []string{"*"}, + }, + "multiple": { + domainField: "*.example.com,example.com", + domainRegistered: "example.com", + owners: []string{"*", "@"}, + }, + "different_domains": { + domainField: "*.example.com,abc.something.com", + errWrapped: ErrMultipleDomainsSpecified, + errMessage: "multiple domains specified: \"example.com\" and \"something.com\"", + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + domainRegistered, owners, err := extractFromDomainField(testCase.domainField) + + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) + } + assert.Equal(t, testCase.domainRegistered, domainRegistered) + assert.Equal(t, testCase.owners, owners) + }) + } +}