Add DNS provider for United-Domains (#2731)

This commit is contained in:
Ludovic Fernandez 2025-11-27 20:40:55 +01:00 committed by GitHub
commit dc0a595a9f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 476 additions and 21 deletions

View file

@ -245,34 +245,34 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
<td><a href="https://go-acme.github.io/lego/dns/safedns/">UKFast SafeDNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/ultradns/">Ultradns</a></td>
<td><a href="https://go-acme.github.io/lego/dns/uniteddomains/">United-Domains</a></td>
<td><a href="https://go-acme.github.io/lego/dns/variomedia/">Variomedia</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vegadns/">VegaDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vercel/">Vercel</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/vercel/">Vercel</a></td>
<td><a href="https://go-acme.github.io/lego/dns/versio/">Versio.[nl|eu|uk]</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vinyldns/">VinylDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vkcloud/">VK Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/volcengine/">Volcano Engine/火山引擎</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/volcengine/">Volcano Engine/火山引擎</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vscale/">Vscale</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vultr/">Vultr</a></td>
<td><a href="https://go-acme.github.io/lego/dns/webnamesca/">webnames.ca</a></td>
<td><a href="https://go-acme.github.io/lego/dns/webnames/">webnames.ru</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/webnames/">webnames.ru</a></td>
<td><a href="https://go-acme.github.io/lego/dns/websupport/">Websupport</a></td>
<td><a href="https://go-acme.github.io/lego/dns/wedos/">WEDOS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/westcn/">West.cn/西部数码</a></td>
<td><a href="https://go-acme.github.io/lego/dns/yandex360/">Yandex 360</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/yandex360/">Yandex 360</a></td>
<td><a href="https://go-acme.github.io/lego/dns/yandexcloud/">Yandex Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/yandex/">Yandex PDD</a></td>
<td><a href="https://go-acme.github.io/lego/dns/zoneee/">Zone.ee</a></td>
<td><a href="https://go-acme.github.io/lego/dns/zoneedit/">ZoneEdit</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/zoneedit/">ZoneEdit</a></td>
<td><a href="https://go-acme.github.io/lego/dns/zonomi/">Zonomi</a></td>
<td></td>
<td></td>
<td></td>
</tr></table>
<!-- END DNS PROVIDERS LIST -->

View file

@ -161,6 +161,7 @@ func allDNSCodes() string {
"timewebcloud",
"transip",
"ultradns",
"uniteddomains",
"variomedia",
"vegadns",
"vercel",
@ -3383,6 +3384,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ultradns`)
case "uniteddomains":
// generated from: providers/dns/uniteddomains/uniteddomains.toml
ew.writeln(`Configuration for United-Domains.`)
ew.writeln(`Code: 'uniteddomains'`)
ew.writeln(`Since: 'v4.29.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "UNITEDDOMAINS_API_KEY": API key '<prefix>.<secret>' https://www.united-domains.de/help/faq-article/getting-started-with-the-united-domains-dns-api/`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "UNITEDDOMAINS_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "UNITEDDOMAINS_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "UNITEDDOMAINS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 900)`)
ew.writeln(` - "UNITEDDOMAINS_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/uniteddomains`)
case "variomedia":
// generated from: providers/dns/variomedia/variomedia.toml
ew.writeln(`Configuration for Variomedia.`)

67
docs/content/dns/zz_gen_uniteddomains.md generated Normal file
View file

@ -0,0 +1,67 @@
---
title: "United-Domains"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: uniteddomains
dnsprovider:
since: "v4.29.0"
code: "uniteddomains"
url: "https://www.united-domains.de/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/uniteddomains/uniteddomains.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [United-Domains](https://www.united-domains.de/).
<!--more-->
- Code: `uniteddomains`
- Since: v4.29.0
Here is an example bash command using the United-Domains provider:
```bash
UNITEDDOMAINS_API_KEY=xxxxxxxx \
lego --email you@example.com --dns uniteddomains -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `UNITEDDOMAINS_API_KEY` | API key `<prefix>.<secret>` https://www.united-domains.de/help/faq-article/getting-started-with-the-united-domains-dns-api/ |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `UNITEDDOMAINS_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `UNITEDDOMAINS_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `UNITEDDOMAINS_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 900) |
| `UNITEDDOMAINS_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 300) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://www.united-domains.de/dns-apidoc/)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/uniteddomains/uniteddomains.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -152,7 +152,7 @@ To display the documentation for a specific DNS provider, run:
$ lego dnshelp -c code
Supported DNS providers:
acme-dns, active24, alidns, aliesa, allinkl, anexia, arvancloud, auroradns, autodns, axelname, azion, azure, azuredns, baiducloud, beget, binarylane, bindman, bluecat, bookmyname, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudru, cloudxns, conoha, conohav3, constellix, corenetworks, cpanel, derak, desec, designate, digitalocean, directadmin, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dyndnsfree, dynu, easydns, edgecenter, edgedns, edgeone, efficientip, epik, exec, exoscale, f5xc, freemyip, gandi, gandiv5, gcloud, gcore, gigahostno, glesys, godaddy, googledomains, hetzner, hostingde, hostinger, hosttech, httpnet, httpreq, huaweicloud, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, ipv64, iwantmyname, joker, keyhelp, liara, lightsail, limacity, linode, liquidweb, loopia, luadns, mailinabox, manageengine, manual, metaname, metaregistrar, mijnhost, mittwald, myaddr, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nicru, nifcloud, njalla, nodion, ns1, octenium, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, rainyun, rcodezero, regfish, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, selectelv2, selfhostde, servercow, shellrent, simply, sonic, spaceship, stackpath, technitium, tencentcloud, timewebcloud, transip, ultradns, variomedia, vegadns, vercel, versio, vinyldns, vkcloud, volcengine, vscale, vultr, webnames, webnamesca, websupport, wedos, westcn, yandex, yandex360, yandexcloud, zoneedit, zoneee, zonomi
acme-dns, active24, alidns, aliesa, allinkl, anexia, arvancloud, auroradns, autodns, axelname, azion, azure, azuredns, baiducloud, beget, binarylane, bindman, bluecat, bookmyname, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudru, cloudxns, conoha, conohav3, constellix, corenetworks, cpanel, derak, desec, designate, digitalocean, directadmin, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dyndnsfree, dynu, easydns, edgecenter, edgedns, edgeone, efficientip, epik, exec, exoscale, f5xc, freemyip, gandi, gandiv5, gcloud, gcore, gigahostno, glesys, godaddy, googledomains, hetzner, hostingde, hostinger, hosttech, httpnet, httpreq, huaweicloud, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, ipv64, iwantmyname, joker, keyhelp, liara, lightsail, limacity, linode, liquidweb, loopia, luadns, mailinabox, manageengine, manual, metaname, metaregistrar, mijnhost, mittwald, myaddr, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nicru, nifcloud, njalla, nodion, ns1, octenium, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, rainyun, rcodezero, regfish, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, selectelv2, selfhostde, servercow, shellrent, simply, sonic, spaceship, stackpath, technitium, tencentcloud, timewebcloud, transip, ultradns, uniteddomains, variomedia, vegadns, vercel, versio, vinyldns, vkcloud, volcengine, vscale, vultr, webnames, webnamesca, websupport, wedos, westcn, yandex, yandex360, yandexcloud, zoneedit, zoneee, zonomi
More information: https://go-acme.github.io/lego/dns
"""

View file

@ -1,4 +1,4 @@
package internal
package ionos
import (
"bytes"
@ -14,8 +14,10 @@ import (
querystring "github.com/google/go-querystring/query"
)
// defaultBaseURL represents the API endpoint to call.
const defaultBaseURL = "https://api.hosting.ionos.com/dns"
const (
DefaultIonosBaseURL = "https://api.hosting.ionos.com/dns"
DefaultUnitedDomainsBaseURL = "https://dnsapi.united-domains.de/dns"
)
// APIKeyHeader API key header.
const APIKeyHeader = "X-Api-Key"
@ -30,7 +32,7 @@ type Client struct {
// NewClient creates a new Client.
func NewClient(apiKey string) (*Client, error) {
baseURL, err := url.Parse(defaultBaseURL)
baseURL, err := url.Parse(DefaultIonosBaseURL)
if err != nil {
return nil, err
}

View file

@ -1,4 +1,4 @@
package internal
package ionos
import (
"net/http"

View file

@ -1,4 +1,4 @@
package internal
package ionos
import (
"fmt"

View file

@ -14,7 +14,7 @@ import (
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/platform/config/env"
"github.com/go-acme/lego/v4/providers/dns/internal/clientdebug"
"github.com/go-acme/lego/v4/providers/dns/ionos/internal"
"github.com/go-acme/lego/v4/providers/dns/internal/ionos"
)
// Environment variables names.
@ -57,7 +57,7 @@ func NewDefaultConfig() *Config {
// DNSProvider implements the challenge.Provider interface.
type DNSProvider struct {
config *Config
client *internal.Client
client *ionos.Client
}
// NewDNSProvider returns a DNSProvider instance configured for Ionos.
@ -88,7 +88,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
return nil, fmt.Errorf("ionos: invalid TTL, TTL (%d) must be greater than %d", config.TTL, minTTL)
}
client, err := internal.NewClient(config.APIKey)
client, err := ionos.NewClient(config.APIKey)
if err != nil {
return nil, fmt.Errorf("ionos: %w", err)
}
@ -126,7 +126,7 @@ func (d *DNSProvider) Present(domain, _, keyAuth string) error {
return errors.New("ionos: no matching zone found for domain")
}
filter := &internal.RecordsFilter{
filter := &ionos.RecordsFilter{
Suffix: name,
RecordType: "TXT",
}
@ -136,7 +136,7 @@ func (d *DNSProvider) Present(domain, _, keyAuth string) error {
return fmt.Errorf("ionos: failed to get records (zone=%s): %w", zone.ID, err)
}
records = append(records, internal.Record{
records = append(records, ionos.Record{
Name: name,
Content: info.Value,
TTL: d.config.TTL,
@ -169,7 +169,7 @@ func (d *DNSProvider) CleanUp(domain, _, keyAuth string) error {
return errors.New("ionos: no matching zone found for domain")
}
filter := &internal.RecordsFilter{
filter := &ionos.RecordsFilter{
Suffix: name,
RecordType: "TXT",
}
@ -193,8 +193,8 @@ func (d *DNSProvider) CleanUp(domain, _, keyAuth string) error {
return fmt.Errorf("ionos: failed to remove record, record not found (zone=%s, domain=%s, fqdn=%s, value=%s)", zone.ID, domain, info.EffectiveFQDN, info.Value)
}
func findZone(zones []internal.Zone, domain string) *internal.Zone {
var result *internal.Zone
func findZone(zones []ionos.Zone, domain string) *ionos.Zone {
var result *ionos.Zone
for _, zone := range zones {
if zone.Name != "" && strings.HasSuffix(domain, zone.Name) {

View file

@ -0,0 +1,210 @@
// Package uniteddomains implements a DNS provider for solving the DNS-01 challenge using United-Domains.
package uniteddomains
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/platform/config/env"
"github.com/go-acme/lego/v4/providers/dns/internal/clientdebug"
"github.com/go-acme/lego/v4/providers/dns/internal/ionos"
)
// Environment variables names.
const (
envNamespace = "UNITEDDOMAINS_"
EnvAPIKey = envNamespace + "API_KEY"
EnvTTL = envNamespace + "TTL"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
)
const minTTL = 300
var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
// Config is used to configure the creation of the DNSProvider.
type Config struct {
APIKey string
PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int
HTTPClient *http.Client
}
// NewDefaultConfig returns a default configuration for the DNSProvider.
func NewDefaultConfig() *Config {
return &Config{
TTL: env.GetOrDefaultInt(EnvTTL, minTTL),
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 15*time.Minute),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
HTTPClient: &http.Client{
Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
},
}
}
// DNSProvider implements the challenge.Provider interface.
type DNSProvider struct {
config *Config
client *ionos.Client
}
// NewDNSProvider returns a DNSProvider instance configured for United-Domains.
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(EnvAPIKey)
if err != nil {
return nil, fmt.Errorf("uniteddomains: %w", err)
}
config := NewDefaultConfig()
config.APIKey = values[EnvAPIKey]
return NewDNSProviderConfig(config)
}
// NewDNSProviderConfig return a DNSProvider instance configured for United-Domains.
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("uniteddomains: the configuration of the DNS provider is nil")
}
if config.APIKey == "" {
return nil, errors.New("uniteddomains: credentials missing")
}
if config.TTL < minTTL {
return nil, fmt.Errorf("uniteddomains: invalid TTL, TTL (%d) must be greater than %d", config.TTL, minTTL)
}
client, err := ionos.NewClient(config.APIKey)
if err != nil {
return nil, fmt.Errorf("uniteddomains: %w", err)
}
client.BaseURL, _ = url.Parse(ionos.DefaultUnitedDomainsBaseURL)
if config.HTTPClient != nil {
client.HTTPClient = config.HTTPClient
}
client.HTTPClient = clientdebug.Wrap(client.HTTPClient)
return &DNSProvider{config: config, client: client}, nil
}
// Timeout returns the timeout and interval to use when checking for DNS propagation.
// Adjusting here to cope with spikes in propagation times.
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
// Present creates a TXT record using the specified parameters.
func (d *DNSProvider) Present(domain, _, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
ctx := context.Background()
zones, err := d.client.ListZones(ctx)
if err != nil {
return fmt.Errorf("uniteddomains: failed to get zones: %w", err)
}
name := dns01.UnFqdn(info.EffectiveFQDN)
zone := findZone(zones, name)
if zone == nil {
return errors.New("uniteddomains: no matching zone found for domain")
}
filter := &ionos.RecordsFilter{
Suffix: name,
RecordType: "TXT",
}
records, err := d.client.GetRecords(ctx, zone.ID, filter)
if err != nil {
return fmt.Errorf("uniteddomains: failed to get records (zone=%s): %w", zone.ID, err)
}
records = append(records, ionos.Record{
Name: name,
Content: info.Value,
TTL: d.config.TTL,
Type: "TXT",
})
err = d.client.ReplaceRecords(ctx, zone.ID, records)
if err != nil {
return fmt.Errorf("uniteddomains: failed to create/update records (zone=%s): %w", zone.ID, err)
}
return nil
}
// CleanUp removes the TXT record matching the specified parameters.
func (d *DNSProvider) CleanUp(domain, _, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
ctx := context.Background()
zones, err := d.client.ListZones(ctx)
if err != nil {
return fmt.Errorf("uniteddomains: failed to get zones: %w", err)
}
name := dns01.UnFqdn(info.EffectiveFQDN)
zone := findZone(zones, name)
if zone == nil {
return errors.New("uniteddomains: no matching zone found for domain")
}
filter := &ionos.RecordsFilter{
Suffix: name,
RecordType: "TXT",
}
records, err := d.client.GetRecords(ctx, zone.ID, filter)
if err != nil {
return fmt.Errorf("uniteddomains: failed to get records (zone=%s): %w", zone.ID, err)
}
for _, record := range records {
if record.Name == name && record.Content == strconv.Quote(info.Value) {
err = d.client.RemoveRecord(ctx, zone.ID, record.ID)
if err != nil {
return fmt.Errorf("uniteddomains: failed to remove record (zone=%s, record=%s): %w", zone.ID, record.ID, err)
}
return nil
}
}
return fmt.Errorf("uniteddomains: failed to remove record, record not found (zone=%s, domain=%s, fqdn=%s, value=%s)", zone.ID, domain, info.EffectiveFQDN, info.Value)
}
func findZone(zones []ionos.Zone, domain string) *ionos.Zone {
var result *ionos.Zone
for _, zone := range zones {
if zone.Name != "" && strings.HasSuffix(domain, zone.Name) {
if result == nil || len(zone.Name) > len(result.Name) {
result = &zone
}
}
}
return result
}

View file

@ -0,0 +1,22 @@
Name = "United-Domains"
Description = ''''''
URL = "https://www.united-domains.de/"
Code = "uniteddomains"
Since = "v4.29.0"
Example = '''
UNITEDDOMAINS_API_KEY=xxxxxxxx \
lego --email you@example.com --dns uniteddomains -d '*.example.com' -d example.com run
'''
[Configuration]
[Configuration.Credentials]
UNITEDDOMAINS_API_KEY = "API key `<prefix>.<secret>` https://www.united-domains.de/help/faq-article/getting-started-with-the-united-domains-dns-api/"
[Configuration.Additional]
UNITEDDOMAINS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)"
UNITEDDOMAINS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 900)"
UNITEDDOMAINS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)"
UNITEDDOMAINS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)"
[Links]
API = "https://www.united-domains.de/dns-apidoc/"

View file

@ -0,0 +1,130 @@
package uniteddomains
import (
"testing"
"github.com/go-acme/lego/v4/platform/tester"
"github.com/stretchr/testify/require"
)
const envDomain = envNamespace + "DOMAIN"
var envTest = tester.NewEnvTest(
EnvAPIKey).
WithDomain(envDomain)
func TestNewDNSProvider(t *testing.T) {
testCases := []struct {
desc string
envVars map[string]string
expected string
}{
{
desc: "success",
envVars: map[string]string{
EnvAPIKey: "123",
},
},
{
desc: "missing credentials",
envVars: map[string]string{
EnvAPIKey: "",
},
expected: "uniteddomains: some credentials information are missing: UNITEDDOMAINS_API_KEY",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
defer envTest.RestoreEnv()
envTest.ClearEnv()
envTest.Apply(test.envVars)
p, err := NewDNSProvider()
if test.expected == "" {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
require.NotNil(t, p.client)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestNewDNSProviderConfig(t *testing.T) {
testCases := []struct {
desc string
apiKey string
tll int
expected string
}{
{
desc: "success",
apiKey: "123",
tll: minTTL,
},
{
desc: "missing credentials",
tll: minTTL,
expected: "uniteddomains: credentials missing",
},
{
desc: "invalid TTL",
apiKey: "123",
tll: 30,
expected: "uniteddomains: invalid TTL, TTL (30) must be greater than 300",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
config := NewDefaultConfig()
config.APIKey = test.apiKey
config.TTL = test.tll
p, err := NewDNSProviderConfig(config)
if test.expected == "" {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
require.NotNil(t, p.client)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestLivePresent(t *testing.T) {
if !envTest.IsLiveTest() {
t.Skip("skipping live test")
}
envTest.RestoreEnv()
provider, err := NewDNSProvider()
require.NoError(t, err)
err = provider.Present(envTest.GetDomain(), "", "123d==")
require.NoError(t, err)
}
func TestLiveCleanUp(t *testing.T) {
if !envTest.IsLiveTest() {
t.Skip("skipping live test")
}
envTest.RestoreEnv()
provider, err := NewDNSProvider()
require.NoError(t, err)
err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
require.NoError(t, err)
}

View file

@ -155,6 +155,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/timewebcloud"
"github.com/go-acme/lego/v4/providers/dns/transip"
"github.com/go-acme/lego/v4/providers/dns/ultradns"
"github.com/go-acme/lego/v4/providers/dns/uniteddomains"
"github.com/go-acme/lego/v4/providers/dns/variomedia"
"github.com/go-acme/lego/v4/providers/dns/vegadns"
"github.com/go-acme/lego/v4/providers/dns/vercel"
@ -478,6 +479,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return transip.NewDNSProvider()
case "ultradns":
return ultradns.NewDNSProvider()
case "uniteddomains":
return uniteddomains.NewDNSProvider()
case "variomedia":
return variomedia.NewDNSProvider()
case "vegadns":