Skip to content

Commit 55b012b

Browse files
marri5317ldez
andauthoredFeb 24, 2025
Add DNS provider for Metaregistrar (#2455)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
1 parent 9d7e2a8 commit 55b012b

14 files changed

+718
-16
lines changed
 

‎README.md

+20-15
Original file line numberDiff line numberDiff line change
@@ -158,85 +158,90 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
158158
<td><a href="https://go-acme.github.io/lego/dns/manual/">Manual</a></td>
159159
<td><a href="https://go-acme.github.io/lego/dns/metaname/">Metaname</a></td>
160160
</tr><tr>
161+
<td><a href="https://go-acme.github.io/lego/dns/metaregistrar/">Metaregistrar</a></td>
161162
<td><a href="https://go-acme.github.io/lego/dns/mijnhost/">mijn.host</a></td>
162163
<td><a href="https://go-acme.github.io/lego/dns/mittwald/">Mittwald</a></td>
163164
<td><a href="https://go-acme.github.io/lego/dns/myaddr/">myaddr.{tools,dev,io}</a></td>
164-
<td><a href="https://go-acme.github.io/lego/dns/mydnsjp/">MyDNS.jp</a></td>
165165
</tr><tr>
166+
<td><a href="https://go-acme.github.io/lego/dns/mydnsjp/">MyDNS.jp</a></td>
166167
<td><a href="https://go-acme.github.io/lego/dns/mythicbeasts/">MythicBeasts</a></td>
167168
<td><a href="https://go-acme.github.io/lego/dns/namedotcom/">Name.com</a></td>
168169
<td><a href="https://go-acme.github.io/lego/dns/namecheap/">Namecheap</a></td>
169-
<td><a href="https://go-acme.github.io/lego/dns/namesilo/">Namesilo</a></td>
170170
</tr><tr>
171+
<td><a href="https://go-acme.github.io/lego/dns/namesilo/">Namesilo</a></td>
171172
<td><a href="https://go-acme.github.io/lego/dns/nearlyfreespeech/">NearlyFreeSpeech.NET</a></td>
172173
<td><a href="https://go-acme.github.io/lego/dns/netcup/">Netcup</a></td>
173174
<td><a href="https://go-acme.github.io/lego/dns/netlify/">Netlify</a></td>
174-
<td><a href="https://go-acme.github.io/lego/dns/nicmanager/">Nicmanager</a></td>
175175
</tr><tr>
176+
<td><a href="https://go-acme.github.io/lego/dns/nicmanager/">Nicmanager</a></td>
176177
<td><a href="https://go-acme.github.io/lego/dns/nifcloud/">NIFCloud</a></td>
177178
<td><a href="https://go-acme.github.io/lego/dns/njalla/">Njalla</a></td>
178179
<td><a href="https://go-acme.github.io/lego/dns/nodion/">Nodion</a></td>
179-
<td><a href="https://go-acme.github.io/lego/dns/ns1/">NS1</a></td>
180180
</tr><tr>
181+
<td><a href="https://go-acme.github.io/lego/dns/ns1/">NS1</a></td>
181182
<td><a href="https://go-acme.github.io/lego/dns/otc/">Open Telekom Cloud</a></td>
182183
<td><a href="https://go-acme.github.io/lego/dns/oraclecloud/">Oracle Cloud</a></td>
183184
<td><a href="https://go-acme.github.io/lego/dns/ovh/">OVH</a></td>
184-
<td><a href="https://go-acme.github.io/lego/dns/plesk/">plesk.com</a></td>
185185
</tr><tr>
186+
<td><a href="https://go-acme.github.io/lego/dns/plesk/">plesk.com</a></td>
186187
<td><a href="https://go-acme.github.io/lego/dns/porkbun/">Porkbun</a></td>
187188
<td><a href="https://go-acme.github.io/lego/dns/pdns/">PowerDNS</a></td>
188189
<td><a href="https://go-acme.github.io/lego/dns/rackspace/">Rackspace</a></td>
189-
<td><a href="https://go-acme.github.io/lego/dns/rainyun/">Rain Yun/雨云</a></td>
190190
</tr><tr>
191+
<td><a href="https://go-acme.github.io/lego/dns/rainyun/">Rain Yun/雨云</a></td>
191192
<td><a href="https://go-acme.github.io/lego/dns/rcodezero/">RcodeZero</a></td>
192193
<td><a href="https://go-acme.github.io/lego/dns/regru/">reg.ru</a></td>
193194
<td><a href="https://go-acme.github.io/lego/dns/regfish/">Regfish</a></td>
194-
<td><a href="https://go-acme.github.io/lego/dns/rfc2136/">RFC2136</a></td>
195195
</tr><tr>
196+
<td><a href="https://go-acme.github.io/lego/dns/rfc2136/">RFC2136</a></td>
196197
<td><a href="https://go-acme.github.io/lego/dns/rimuhosting/">RimuHosting</a></td>
197198
<td><a href="https://go-acme.github.io/lego/dns/sakuracloud/">Sakura Cloud</a></td>
198199
<td><a href="https://go-acme.github.io/lego/dns/scaleway/">Scaleway</a></td>
199-
<td><a href="https://go-acme.github.io/lego/dns/selectel/">Selectel</a></td>
200200
</tr><tr>
201+
<td><a href="https://go-acme.github.io/lego/dns/selectel/">Selectel</a></td>
201202
<td><a href="https://go-acme.github.io/lego/dns/selectelv2/">Selectel v2</a></td>
202203
<td><a href="https://go-acme.github.io/lego/dns/selfhostde/">SelfHost.(de|eu)</a></td>
203204
<td><a href="https://go-acme.github.io/lego/dns/servercow/">Servercow</a></td>
204-
<td><a href="https://go-acme.github.io/lego/dns/shellrent/">Shellrent</a></td>
205205
</tr><tr>
206+
<td><a href="https://go-acme.github.io/lego/dns/shellrent/">Shellrent</a></td>
206207
<td><a href="https://go-acme.github.io/lego/dns/simply/">Simply.com</a></td>
207208
<td><a href="https://go-acme.github.io/lego/dns/sonic/">Sonic</a></td>
208209
<td><a href="https://go-acme.github.io/lego/dns/spaceship/">Spaceship</a></td>
209-
<td><a href="https://go-acme.github.io/lego/dns/stackpath/">Stackpath</a></td>
210210
</tr><tr>
211+
<td><a href="https://go-acme.github.io/lego/dns/stackpath/">Stackpath</a></td>
211212
<td><a href="https://go-acme.github.io/lego/dns/technitium/">Technitium</a></td>
212213
<td><a href="https://go-acme.github.io/lego/dns/tencentcloud/">Tencent Cloud DNS</a></td>
213214
<td><a href="https://go-acme.github.io/lego/dns/timewebcloud/">Timeweb Cloud</a></td>
214-
<td><a href="https://go-acme.github.io/lego/dns/transip/">TransIP</a></td>
215215
</tr><tr>
216+
<td><a href="https://go-acme.github.io/lego/dns/transip/">TransIP</a></td>
216217
<td><a href="https://go-acme.github.io/lego/dns/safedns/">UKFast SafeDNS</a></td>
217218
<td><a href="https://go-acme.github.io/lego/dns/ultradns/">Ultradns</a></td>
218219
<td><a href="https://go-acme.github.io/lego/dns/variomedia/">Variomedia</a></td>
219-
<td><a href="https://go-acme.github.io/lego/dns/vegadns/">VegaDNS</a></td>
220220
</tr><tr>
221+
<td><a href="https://go-acme.github.io/lego/dns/vegadns/">VegaDNS</a></td>
221222
<td><a href="https://go-acme.github.io/lego/dns/vercel/">Vercel</a></td>
222223
<td><a href="https://go-acme.github.io/lego/dns/versio/">Versio.[nl|eu|uk]</a></td>
223224
<td><a href="https://go-acme.github.io/lego/dns/vinyldns/">VinylDNS</a></td>
224-
<td><a href="https://go-acme.github.io/lego/dns/vkcloud/">VK Cloud</a></td>
225225
</tr><tr>
226+
<td><a href="https://go-acme.github.io/lego/dns/vkcloud/">VK Cloud</a></td>
226227
<td><a href="https://go-acme.github.io/lego/dns/volcengine/">Volcano Engine/火山引擎</a></td>
227228
<td><a href="https://go-acme.github.io/lego/dns/vscale/">Vscale</a></td>
228229
<td><a href="https://go-acme.github.io/lego/dns/vultr/">Vultr</a></td>
229-
<td><a href="https://go-acme.github.io/lego/dns/webnames/">Webnames</a></td>
230230
</tr><tr>
231+
<td><a href="https://go-acme.github.io/lego/dns/webnames/">Webnames</a></td>
231232
<td><a href="https://go-acme.github.io/lego/dns/websupport/">Websupport</a></td>
232233
<td><a href="https://go-acme.github.io/lego/dns/wedos/">WEDOS</a></td>
233234
<td><a href="https://go-acme.github.io/lego/dns/westcn/">West.cn/西部数码</a></td>
234-
<td><a href="https://go-acme.github.io/lego/dns/yandex360/">Yandex 360</a></td>
235235
</tr><tr>
236+
<td><a href="https://go-acme.github.io/lego/dns/yandex360/">Yandex 360</a></td>
236237
<td><a href="https://go-acme.github.io/lego/dns/yandexcloud/">Yandex Cloud</a></td>
237238
<td><a href="https://go-acme.github.io/lego/dns/yandex/">Yandex PDD</a></td>
238239
<td><a href="https://go-acme.github.io/lego/dns/zoneee/">Zone.ee</a></td>
240+
</tr><tr>
239241
<td><a href="https://go-acme.github.io/lego/dns/zonomi/">Zonomi</a></td>
242+
<td></td>
243+
<td></td>
244+
<td></td>
240245
</tr></table>
241246

242247
<!-- END DNS PROVIDERS LIST -->

‎cmd/zz_gen_cmd_dnshelp.go

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/content/dns/zz_gen_metaregistrar.md

+67
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎docs/data/zz_cli_help.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ To display the documentation for a specific DNS provider, run:
149149
$ lego dnshelp -c code
150150
151151
Supported DNS providers:
152-
acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, azuredns, bindman, bluecat, bookmyname, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudru, cloudxns, conoha, constellix, corenetworks, cpanel, derak, desec, designate, digitalocean, directadmin, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, efficientip, epik, exec, exoscale, freemyip, gandi, gandiv5, gcloud, gcore, glesys, godaddy, googledomains, hetzner, hostingde, hosttech, httpnet, httpreq, huaweicloud, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, ipv64, iwantmyname, joker, liara, lightsail, limacity, linode, liquidweb, loopia, luadns, mailinabox, manageengine, manual, metaname, mijnhost, mittwald, myaddr, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nifcloud, njalla, nodion, ns1, 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, websupport, wedos, westcn, yandex, yandex360, yandexcloud, zoneee, zonomi
152+
acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, azuredns, bindman, bluecat, bookmyname, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudru, cloudxns, conoha, constellix, corenetworks, cpanel, derak, desec, designate, digitalocean, directadmin, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, efficientip, epik, exec, exoscale, freemyip, gandi, gandiv5, gcloud, gcore, glesys, godaddy, googledomains, hetzner, hostingde, hosttech, httpnet, httpreq, huaweicloud, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, ipv64, iwantmyname, joker, liara, lightsail, limacity, linode, liquidweb, loopia, luadns, mailinabox, manageengine, manual, metaname, metaregistrar, mijnhost, mittwald, myaddr, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nifcloud, njalla, nodion, ns1, 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, websupport, wedos, westcn, yandex, yandex360, yandexcloud, zoneee, zonomi
153153
154154
More information: https://go-acme.github.io/lego/dns
155155
"""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package internal
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"errors"
8+
"fmt"
9+
"io"
10+
"net/http"
11+
"net/url"
12+
"time"
13+
14+
"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
15+
)
16+
17+
const defaultBaseURL = "https://api.metaregistrar.com"
18+
19+
// Client is a client to interact with the Metaregistrar API.
20+
type Client struct {
21+
token string
22+
23+
baseURL *url.URL
24+
HTTPClient *http.Client
25+
}
26+
27+
// NewClient creates a new Client.
28+
func NewClient(token string) (*Client, error) {
29+
if token == "" {
30+
return nil, errors.New("token missing")
31+
}
32+
33+
baseURL, _ := url.Parse(defaultBaseURL)
34+
35+
return &Client{
36+
token: token,
37+
baseURL: baseURL,
38+
HTTPClient: &http.Client{Timeout: 10 * time.Second},
39+
}, nil
40+
}
41+
42+
// UpdateDNSZone updates the DNS zone for a domain.
43+
// To add or remove a TXT record we make a PATCH request.
44+
// https://metaregistrar.dev/docu/metaapi/requests/patch_Update_dns_zone.html
45+
func (c Client) UpdateDNSZone(ctx context.Context, domain string, updateRequest DNSZoneUpdateRequest) (*DNSZoneUpdateResponse, error) {
46+
endpoint := c.baseURL.JoinPath("dnszone", domain)
47+
48+
req, err := newJSONRequest(ctx, http.MethodPatch, endpoint, updateRequest)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
result := &DNSZoneUpdateResponse{}
54+
55+
err = c.do(req, result)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
return result, nil
61+
}
62+
63+
func (c Client) do(req *http.Request, result any) error {
64+
req.Header.Add("token", c.token)
65+
66+
resp, err := c.HTTPClient.Do(req)
67+
if err != nil {
68+
return errutils.NewHTTPDoError(req, err)
69+
}
70+
71+
defer func() { _ = resp.Body.Close() }()
72+
73+
if resp.StatusCode != http.StatusOK {
74+
return parseError(req, resp)
75+
}
76+
77+
if result == nil {
78+
return nil
79+
}
80+
81+
raw, err := io.ReadAll(resp.Body)
82+
if err != nil {
83+
return errutils.NewReadResponseError(req, resp.StatusCode, err)
84+
}
85+
86+
err = json.Unmarshal(raw, result)
87+
if err != nil {
88+
return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err)
89+
}
90+
91+
return nil
92+
}
93+
94+
func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
95+
buf := new(bytes.Buffer)
96+
97+
if payload != nil {
98+
err := json.NewEncoder(buf).Encode(payload)
99+
if err != nil {
100+
return nil, fmt.Errorf("failed to create request JSON body: %w", err)
101+
}
102+
}
103+
104+
req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), buf)
105+
if err != nil {
106+
return nil, fmt.Errorf("unable to create request: %w", err)
107+
}
108+
109+
req.Header.Set("Accept", "application/json")
110+
111+
if payload != nil {
112+
req.Header.Set("Content-Type", "application/json")
113+
}
114+
115+
return req, nil
116+
}
117+
118+
func parseError(req *http.Request, resp *http.Response) error {
119+
raw, _ := io.ReadAll(resp.Body)
120+
121+
var errAPI APIError
122+
err := json.Unmarshal(raw, &errAPI)
123+
if err != nil {
124+
return errutils.NewUnexpectedStatusCodeError(req, resp.StatusCode, raw)
125+
}
126+
127+
return &errAPI
128+
}

0 commit comments

Comments
 (0)