diff --git a/commands/types/dnscontrol.d.ts b/commands/types/dnscontrol.d.ts index 0ce2883c0b..6e4527622d 100644 --- a/commands/types/dnscontrol.d.ts +++ b/commands/types/dnscontrol.d.ts @@ -344,13 +344,9 @@ declare const AUTODNSSEC_OFF: DomainModifier; * * [`AUTODNSSEC_OFF`](AUTODNSSEC_OFF.md) tells the provider to **disable** AutoDNSSEC. * - * AutoDNSSEC is a feature where a DNS provider can automatically manage - * DNSSEC for a domain. Not all providers support this. + * AutoDNSSEC is a feature where a DNS provider can automatically manage DNSSEC for a domain. Not all providers support this. * - * At this time, `AUTODNSSEC_ON` takes no parameters. There is no ability - * to tune what the DNS provider sets, no algorithm choice. We simply - * ask that they follow their defaults when enabling a no-fuss DNSSEC - * data model. + * At this time, `AUTODNSSEC_ON` takes no parameters. There is no ability to tune what the DNS provider sets, no algorithm choice. We simply ask that they follow their defaults when enabling a no-fuss DNSSEC data model. * * NOTE: No parenthesis should follow these keywords. That is, the * correct syntax is `AUTODNSSEC_ON` not `AUTODNSSEC_ON()` @@ -367,8 +363,7 @@ declare const AUTODNSSEC_OFF: DomainModifier; * ); * ``` * - * If neither `AUTODNSSEC_ON` or `AUTODNSSEC_OFF` is specified for a - * domain no changes will be requested. + * If neither `AUTODNSSEC_ON` or `AUTODNSSEC_OFF` is specified for a domain no changes will be requested. * * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/autodnssec_on */ @@ -568,12 +563,9 @@ declare function CAA_BUILDER(opts: { label?: string; iodef: string; iodef_critic * generate "Dynamic Single Redirects" for a limited number of use cases. See * [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md) for details. * - * `CF_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page - * Rules) to generate a HTTP 301 permanent redirect. + * `CF_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page Rules) to generate a HTTP 301 permanent redirect. * - * If _any_ `CF_REDIRECT` or [`CF_TEMP_REDIRECT`](CF_TEMP_REDIRECT.md) functions are used then - * `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. - * Page Rule types other than "Forwarding URL" will be left alone. + * If _any_ `CF_REDIRECT` or [`CF_TEMP_REDIRECT`](CF_TEMP_REDIRECT.md) functions are used then `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. Page Rule types other than "Forwarding URL" will be left alone. * * WARNING: Cloudflare does not currently fully document the Page Rules API and * this interface is not extensively tested. Take precautions such as making @@ -581,10 +573,7 @@ declare function CAA_BUILDER(opts: { label?: string; iodef: string; iodef_critic * `dnscontrol push`. This is especially true when mixing Page Rules that are * managed by DNSControl and those that aren't. * - * HTTP 301 redirects are cached by browsers forever, usually ignoring any TTLs or - * other cache invalidation techniques. It should be used with great care. We - * suggest using a `CF_TEMP_REDIRECT` initially, then changing to a `CF_REDIRECT` - * only after sufficient time has elapsed to prove this is what you really want. + * HTTP 301 redirects are cached by browsers forever, usually ignoring any TTLs or other cache invalidation techniques. It should be used with great care. We suggest using a `CF_TEMP_REDIRECT` initially, then changing to a `CF_REDIRECT` only after sufficient time has elapsed to prove this is what you really want. * * This example redirects the bare (aka apex, or naked) domain to www: * @@ -599,11 +588,9 @@ declare function CAA_BUILDER(opts: { label?: string; iodef: string; iodef_critic declare function CF_REDIRECT(source: string, destination: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `CF_SINGLE_REDIRECT` is a [Cloudflare](../../provider/cloudflareapi.md)-specific feature for creating HTTP redirects. 301, 302, 303, 307, 308 are supported. - * Typically one uses 302 (temporary) or 301 (permanent). + * `CF_SINGLE_REDIRECT` is a [Cloudflare](../../provider/cloudflareapi.md)-specific feature for creating HTTP redirects. 301, 302, 303, 307, 308 are supported. Typically one uses 302 (temporary) or 301 (permanent). * - * This feature manages dynamic "Single Redirects". (Single Redirects can be - * static or dynamic but DNSControl only maintains dynamic redirects). + * This feature manages dynamic "Single Redirects". (Single Redirects can be static or dynamic but DNSControl only maintains dynamic redirects). * * DNSControl will delete any "single redirects" it doesn't recognize (i.e. ones created via the web UI) so please be careful. * @@ -624,19 +611,11 @@ declare function CF_REDIRECT(source: string, destination: string, ...modifiers: * * when: What Cloudflare sometimes calls the "rule expression". * * then: The replacement expression. * - * DNSControl does not currently choose the order of the rules. New rules are - * added to the end of the list. Use Cloudflare's dashboard to re-order the rule, - * DNSControl should not change them. (In the future we hope to add a feature - * where the order the rules appear in dnsconfig.js is maintained in the - * dashboard.) + * DNSControl does not currently choose the order of the rules. New rules are added to the end of the list. Use Cloudflare's dashboard to re-order the rule, DNSControl should not change them. (In the future we hope to add a feature where the order the rules appear in dnsconfig.js is maintained in the dashboard.) * * ## `CF_REDIRECT` and `CF_TEMP_REDIRECT` * - * `CF_REDIRECT` and `CF_TEMP_REDIRECT` used to manage Cloudflare Page Rules. - * However that feature is going away. To help with the migration, DNSControl now - * translates those commands into CF_SINGLE_REDIRECT equivalents. The conversion - * process is a transpiler that only understands certain formats. Please submit - * a Github issue if you find something it can't handle. + * `CF_REDIRECT` and `CF_TEMP_REDIRECT` used to manage Cloudflare Page Rules. However that feature is going away. To help with the migration, DNSControl now translates those commands into CF_SINGLE_REDIRECT equivalents. The conversion process is a transpiler that only understands certain formats. Please submit a Github issue if you find something it can't handle. * * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/service-provider-specific/cloudflare-dns/cf_single_redirect */ @@ -648,12 +627,9 @@ declare function CF_SINGLE_REDIRECT(name: string, code: number, when: string, th * generate "Dynamic Single Redirects" for a limited number of use cases. See * [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md) for details. * - * `CF_TEMP_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page - * Rules) to generate a HTTP 302 temporary redirect. + * `CF_TEMP_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page Rules) to generate a HTTP 302 temporary redirect. * - * If _any_ [`CF_REDIRECT`](CF_REDIRECT.md) or `CF_TEMP_REDIRECT functions are used then - * `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. - * Page Rule types other than "Forwarding URL" will be left alone. + * If _any_ [`CF_REDIRECT`](CF_REDIRECT.md) or `CF_TEMP_REDIRECT functions are used then `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. Page Rule types other than "Forwarding URL" will be left alone. * * WARNING: Cloudflare does not currently fully document the Page Rules API and * this interface is not extensively tested. Take precautions such as making @@ -675,13 +651,9 @@ declare function CF_SINGLE_REDIRECT(name: string, code: number, when: string, th declare function CF_TEMP_REDIRECT(source: string, destination: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `CF_WORKER_ROUTE` uses the [Cloudflare Workers](https://developers.cloudflare.com/workers/) - * API to manage [worker routes](https://developers.cloudflare.com/workers/platform/routes) - * for a given domain. + * `CF_WORKER_ROUTE` uses the [Cloudflare Workers](https://developers.cloudflare.com/workers/) API to manage [worker routes](https://developers.cloudflare.com/workers/platform/routes) for a given domain. * - * If _any_ `CF_WORKER_ROUTE` function is used then `dnscontrol` will manage _all_ - * Worker Routes for the domain. To be clear: this means it will delete existing routes that - * were created outside of DNSControl. + * If _any_ `CF_WORKER_ROUTE` function is used then `dnscontrol` will manage _all_ Worker Routes for the domain. To be clear: this means it will delete existing routes that were created outside of DNSControl. * * WARNING: This interface is not extensively tested. Take precautions such as making * backups and manually verifying `dnscontrol preview` output before running @@ -726,16 +698,13 @@ declare function CLOUDNS_WR(name: string, target: string, ...modifiers: RecordMo declare function CNAME(name: string, target: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `D` adds a new Domain for DNSControl to manage. The first two arguments are required: the domain name (fully qualified `example.com` without a trailing dot), and the - * name of the registrar (as previously declared with [NewRegistrar](NewRegistrar.md)). Any number of additional arguments may be included to add DNS Providers with [DNSProvider](NewDnsProvider.md), - * add records with [A](../domain-modifiers/A.md), [CNAME](../domain-modifiers/CNAME.md), and so forth, or add metadata. + * `D` adds a new Domain for DNSControl to manage. The first two arguments are required: the domain name (fully qualified `example.com` without a trailing dot), and the name of the registrar (as previously declared with [NewRegistrar](NewRegistrar.md)). Any number of additional arguments may be included to add DNS Providers with [DNSProvider](NewDnsProvider.md), add records with [A](../domain-modifiers/A.md), [CNAME](../domain-modifiers/CNAME.md), and so forth, or add metadata. * * Modifier arguments are processed according to type as follows: * * - A function argument will be called with the domain object as it's only argument. Most of the [built-in modifier functions](https://docs.dnscontrol.org/language-reference/domain-modifiers) return such functions. * - An object argument will be merged into the domain's metadata collection. - * - An array argument will have all of it's members evaluated recursively. This allows you to combine multiple common records or modifiers into a variable that can - * be used like a macro in multiple domains. + * - An array argument will have all of it's members evaluated recursively. This allows you to combine multiple common records or modifiers into a variable that can be used like a macro in multiple domains. * * ```javascript * // simple domain @@ -768,14 +737,9 @@ declare function CNAME(name: string, target: string, ...modifiers: RecordModifie * * # `no_ns` * - * To prevent DNSControl from accidentally deleting your nameservers (at the - * parent domain), registrar updates are disabled if the list of nameservers for a - * zone (as computed from `dnsconfig.js`) is empty. + * To prevent DNSControl from accidentally deleting your nameservers (at the parent domain), registrar updates are disabled if the list of nameservers for a zone (as computed from `dnsconfig.js`) is empty. * - * This can happen when a provider doesn't give any control over the apex NS - * records, there are no default nameservers, there are no `NAMESERVER()` - * statements, and the provider returns an empty list of nameservers (such as - * Gandi and Vercel). + * This can happen when a provider doesn't give any control over the apex NS records, there are no default nameservers, there are no `NAMESERVER()` statements, and the provider returns an empty list of nameservers (such as Gandi and Vercel). * * In this situation, you will see an error message such as: * @@ -797,13 +761,9 @@ declare function CNAME(name: string, target: string, ...modifiers: RecordModifie * * # Split Horizon DNS * - * DNSControl supports Split Horizon DNS. Simply - * define the domain two or more times, each with - * their own unique parameters. + * DNSControl supports Split Horizon DNS. Simply define the domain two or more times, each with their own unique parameters. * - * To differentiate the different domains, specify the domains as - * `domain.tld!tag`, such as `example.com!inside` and - * `example.com!outside`. + * To differentiate the different domains, specify the domains as `domain.tld!tag`, such as `example.com!inside` and `example.com!outside`. * * ```javascript * var REG_NONE = NewRegistrar("none"); @@ -823,17 +783,9 @@ declare function CNAME(name: string, target: string, ...modifiers: RecordModifie * ); * ``` * - * A domain name without a `!` is assigned a tag that is the empty - * string. For example, `example.com` and `example.com!` are equivalent. - * However, we strongly recommend against using the empty tag, as it - * risks creating confusion. In other words, if you have `domain.tld` - * and `domain.tld!external` you now require humans to remember that - * `domain.tld` is the external one. I mean... the internal one. You - * may have noticed this mistake, but will your coworkers? Will you in - * six months? You get the idea. + * A domain name without a `!` is assigned a tag that is the empty string. For example, `example.com` and `example.com!` are equivalent. However, we strongly recommend against using the empty tag, as it risks creating confusion. In other words, if you have `domain.tld` and `domain.tld!external` you now require humans to remember that `domain.tld` is the external one. I mean... the internal one. You may have noticed this mistake, but will your coworkers? Will you in six months? You get the idea. * - * DNSControl command line flag `--domains` matches the full name (with the "!"). If you - * define domains `example.com!john`, `example.com!paul`, and `example.com!george` then: + * DNSControl command line flag `--domains` matches the full name (with the "!"). If you define domains `example.com!john`, `example.com!paul`, and `example.com!george` then: * * * `--domains=example.com` will not match any of the three. * * `--domains='example.com!george'` will only match george. @@ -900,12 +852,9 @@ declare function DEFAULTS(...modifiers: DomainModifier[]): void; declare function DHCID(name: string, digest: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `DISABLE_IGNORE_SAFETY_CHECK` disables the safety check. Normally it is an - * error to insert records that match an `IGNORE` pattern. This disables that - * safety check for the entire domain. + * `DISABLE_IGNORE_SAFETY_CHECK` disables the safety check. Normally it is an error to insert records that match an `IGNORE` pattern. This disables that safety check for the entire domain. * - * It replaces the per-record `IGNORE_NAME_DISABLE_SAFETY_CHECK` which is - * deprecated as of DNSControl v4.0.0.0. + * It replaces the per-record `IGNORE_NAME_DISABLE_SAFETY_CHECK` which is deprecated as of DNSControl v4.0.0.0. * * See [`IGNORE`](../domain-modifiers/IGNORE.md) for more information. * @@ -1138,16 +1087,9 @@ declare function DNAME(name: string, target: string, ...modifiers: RecordModifie declare function DNSKEY(name: string, flags: number, protocol: number, algorithm: number, publicKey: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `DOMAIN_ELSEWHERE()` is a helper macro that lets you easily indicate that - * a domain's zones are managed elsewhere. That is, it permits you easily delegate - * a domain to a hard-coded list of DNS servers. + * `DOMAIN_ELSEWHERE()` is a helper macro that lets you easily indicate that a domain's zones are managed elsewhere. That is, it permits you easily delegate a domain to a hard-coded list of DNS servers. * - * `DOMAIN_ELSEWHERE` is useful when you control a domain's registrar but not the - * DNS servers. For example, suppose you own a domain but the DNS servers are run - * by someone else, perhaps a SaaS product you've subscribed to or a DNS server - * that is run by your brother-in-law who doesn't trust you with the API keys that - * would let you maintain the domain using DNSControl. You need an easy way to - * point (delegate) the domain at a specific list of DNS servers. + * `DOMAIN_ELSEWHERE` is useful when you control a domain's registrar but not the DNS servers. For example, suppose you own a domain but the DNS servers are run by someone else, perhaps a SaaS product you've subscribed to or a DNS server that is run by your brother-in-law who doesn't trust you with the API keys that would let you maintain the domain using DNSControl. You need an easy way to point (delegate) the domain at a specific list of DNS servers. * * For example these two statements are equivalent: * @@ -1171,19 +1113,11 @@ declare function DNSKEY(name: string, flags: number, protocol: number, algorithm declare function DOMAIN_ELSEWHERE(name: string, registrar: string, nameserver_names: string[]): void; /** - * `DOMAIN_ELSEWHERE_AUTO()` is similar to `DOMAIN_ELSEWHERE()` but instead of - * a hardcoded list of nameservers, a DnsProvider() is queried. + * `DOMAIN_ELSEWHERE_AUTO()` is similar to `DOMAIN_ELSEWHERE()` but instead of a hardcoded list of nameservers, a DnsProvider() is queried. * - * `DOMAIN_ELSEWHERE_AUTO` is useful when you control a domain's registrar but the - * DNS zones are managed by another system. Luckily you have enough access to that - * other system that you can query it to determine the zone's nameservers. + * `DOMAIN_ELSEWHERE_AUTO` is useful when you control a domain's registrar but the DNS zones are managed by another system. Luckily you have enough access to that other system that you can query it to determine the zone's nameservers. * - * For example, suppose you own a domain but the DNS servers for it are in Azure. - * Further suppose that something in Azure maintains the zones (automatic or - * human). Azure picks the nameservers for the domains automatically, and that - * list may change occasionally. `DOMAIN_ELSEWHERE_AUTO` allows you to easily - * query Azure to determine the domain's delegations so that you do not need to - * hard-code them in your dnsconfig.js file. + * For example, suppose you own a domain but the DNS servers for it are in Azure. Further suppose that something in Azure maintains the zones (automatic or human). Azure picks the nameservers for the domains automatically, and that list may change occasionally. `DOMAIN_ELSEWHERE_AUTO` allows you to easily query Azure to determine the domain's delegations so that you do not need to hard-code them in your dnsconfig.js file. * * For example these two statements are equivalent: * @@ -1226,30 +1160,15 @@ declare function DOMAIN_ELSEWHERE_AUTO(name: string, domain: string, registrar: declare function DS(name: string, keytag: number, algorithm: number, digesttype: number, digest: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `D_EXTEND` adds records (and metadata) to a domain previously defined - * by [`D()`](D.md). It can also be used to add subdomain records (and metadata) - * to a previously defined domain. + * `D_EXTEND` adds records (and metadata) to a domain previously defined by [`D()`](D.md). It can also be used to add subdomain records (and metadata) to a previously defined domain. * - * The first argument is a domain name. If it exactly matches a - * previously defined domain, `D_EXTEND()` behaves the same as [`D()`](D.md), - * simply adding records as if they had been specified in the original - * [`D()`](D.md). + * The first argument is a domain name. If it exactly matches a previously defined domain, `D_EXTEND()` behaves the same as [`D()`](D.md), simply adding records as if they had been specified in the original [`D()`](D.md). * - * If the domain name does not match an existing domain, but could be a - * (non-delegated) subdomain of an existing domain, the new records (and - * metadata) are added with the subdomain part appended to all record - * names (labels), and targets (as appropriate). See the examples below. + * If the domain name does not match an existing domain, but could be a (non-delegated) subdomain of an existing domain, the new records (and metadata) are added with the subdomain part appended to all record names (labels), and targets (as appropriate). See the examples below. * - * Matching the domain name to previously-defined domains is done using a - * `longest match` algorithm. If `domain.tld` and `sub.domain.tld` are - * defined as separate domains via separate [`D()`](D.md) statements, then - * `D_EXTEND("sub.sub.domain.tld", ...)` would match `sub.domain.tld`, - * not `domain.tld`. + * Matching the domain name to previously-defined domains is done using a `longest match` algorithm. If `domain.tld` and `sub.domain.tld` are defined as separate domains via separate [`D()`](D.md) statements, then `D_EXTEND("sub.sub.domain.tld", ...)` would match `sub.domain.tld`, not `domain.tld`. * - * Some operators only act on an apex domain (e.g. - * [`CF_SINGLE_REDIRECT`](../domain-modifiers/CF_SINGLE_REDIRECT.md), - * [`CF_REDIRECT`](../domain-modifiers/CF_REDIRECT.md), and [`CF_TEMP_REDIRECT`](../domain-modifiers/CF_TEMP_REDIRECT.md)). Using them - * in a `D_EXTEND` subdomain may not be what you expect. + * Some operators only act on an apex domain (e.g. [`CF_SINGLE_REDIRECT`](../domain-modifiers/CF_SINGLE_REDIRECT.md), [`CF_REDIRECT`](../domain-modifiers/CF_REDIRECT.md), and [`CF_TEMP_REDIRECT`](../domain-modifiers/CF_TEMP_REDIRECT.md)). Using them in a `D_EXTEND` subdomain may not be what you expect. * * ```javascript * D("domain.tld", REG_MY_PROVIDER, DnsProvider(DNS), @@ -1296,14 +1215,7 @@ declare function DS(name: string, keytag: number, algorithm: number, digesttype: * #12: CREATE CNAME i.sub.domain.tld j.sub.domain.tld. * ``` * - * ProTips: `D_EXTEND()` permits you to create very complex and - * sophisticated configurations, but you shouldn't. Be nice to the next - * person that edits the file, who may not be as expert as yourself. - * Enhance readability by putting any `D_EXTEND()` statements immediately - * after the original [`D()`](D.md), like in above example. Avoid the temptation - * to obscure the addition of records to existing domains with randomly - * placed `D_EXTEND()` statements. Don't build up a domain using loops of - * `D_EXTEND()` statements. You'll be glad you didn't. + * ProTips: `D_EXTEND()` permits you to create very complex and sophisticated configurations, but you shouldn't. Be nice to the next person that edits the file, who may not be as expert as yourself. Enhance readability by putting any `D_EXTEND()` statements immediately after the original [`D()`](D.md), like in above example. Avoid the temptation to obscure the addition of records to existing domains with randomly placed `D_EXTEND()` statements. Don't build up a domain using loops of `D_EXTEND()` statements. You'll be glad you didn't. * * @see https://docs.dnscontrol.org/language-reference/top-level-functions/d_extend */ @@ -1331,8 +1243,7 @@ declare function D_EXTEND(name: string, ...modifiers: DomainModifier[]): void; declare function DefaultTTL(ttl: Duration): DomainModifier; /** - * DnsProvider indicates that the specified provider should be used to manage - * records for this domain. The name must match the name used with [NewDnsProvider](../top-level-functions/NewDnsProvider.md). + * DnsProvider indicates that the specified provider should be used to manage records for this domain. The name must match the name used with [NewDnsProvider](../top-level-functions/NewDnsProvider.md). * * The nsCount parameter determines how the nameservers will be managed from this provider. * @@ -1340,15 +1251,11 @@ declare function DefaultTTL(ttl: Duration): DomainModifier; * * Using `0` for nsCount means "do not fetch nameservers from this domain, or give them to the registrar". * - * Using a different number, ie: `DnsProvider("name",2)`, means "fetch all nameservers from this provider, - * but limit it to this many. + * Using a different number, ie: `DnsProvider("name",2)`, means "fetch all nameservers from this provider, but limit it to this many. * * See [this page](../../advanced-features/nameservers.md) for a detailed explanation of how DNSControl handles nameservers and NS records. * - * If a domain (`D()`) does not include any `DnsProvider()` functions, - * the DNS records will not be modified. In fact, if you want to control - * the Registrar for a domain but not the DNS records themselves, simply - * do not include a `DnsProvider()` function for that `D()`. + * If a domain (`D()`) does not include any `DnsProvider()` functions, the DNS records will not be modified. In fact, if you want to control the Registrar for a domain but not the DNS records themselves, simply do not include a `DnsProvider()` function for that `D()`. * * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/dnsprovider */ @@ -1470,27 +1377,15 @@ declare const HEDNS_DYNAMIC_ON: RecordModifier; declare function HTTPS(name: string, priority: number, target: string, params: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `IGNORE()` makes it possible for DNSControl to share management of a domain - * with an external system. The parameters of `IGNORE()` indicate which records - * are managed elsewhere and should not be modified or deleted. + * `IGNORE()` makes it possible for DNSControl to share management of a domain with an external system. The parameters of `IGNORE()` indicate which records are managed elsewhere and should not be modified or deleted. * - * Use case: Suppose a domain is managed by both DNSControl and a third-party - * system. This creates a problem because DNSControl will try to delete records - * inserted by the other system. The other system may get confused and re-insert - * those records. The two systems will get into an endless update cycle where - * each will revert changes made by the other in an endless loop. + * Use case: Suppose a domain is managed by both DNSControl and a third-party system. This creates a problem because DNSControl will try to delete records inserted by the other system. The other system may get confused and re-insert those records. The two systems will get into an endless update cycle where each will revert changes made by the other in an endless loop. * - * To solve this problem simply include `IGNORE()` statements that identify which - * records are managed elsewhere. DNSControl will not modify or delete those - * records. + * To solve this problem simply include `IGNORE()` statements that identify which records are managed elsewhere. DNSControl will not modify or delete those records. * - * Technically `IGNORE_NAME` is a promise that DNSControl will not modify or - * delete existing records that match particular patterns. It is like - * [`NO_PURGE`](../domain-modifiers/NO_PURGE.md) that matches only specific records. + * Technically `IGNORE_NAME` is a promise that DNSControl will not modify or delete existing records that match particular patterns. It is like [`NO_PURGE`](../domain-modifiers/NO_PURGE.md) that matches only specific records. * - * Including a record that is ignored is considered an error and may have - * undefined behavior. This safety check can be disabled using the - * [`DISABLE_IGNORE_SAFETY_CHECK`](../domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md) feature. + * Including a record that is ignored is considered an error and may have undefined behavior. This safety check can be disabled using the [`DISABLE_IGNORE_SAFETY_CHECK`](../domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md) feature. * * ## Syntax * @@ -1512,9 +1407,7 @@ declare function HTTPS(name: string, priority: number, target: string, params: s * * ## Globs * - * The `labelSpec` and `targetSpec` parameters supports glob patterns in the style - * of the [gobwas/glob](https://github.com/gobwas/glob) library. All of the - * following patterns will work: + * The `labelSpec` and `targetSpec` parameters supports glob patterns in the style of the [gobwas/glob](https://github.com/gobwas/glob) library. All of the following patterns will work: * * * `IGNORE("*.foo")` will ignore all records in the style of `bar.foo`, but will not ignore records using a double subdomain, such as `foo.bar.foo`. * * `IGNORE("**.foo")` will ignore all subdomains of `foo`, including double subdomains. @@ -1576,9 +1469,7 @@ declare function HTTPS(name: string, priority: number, target: string, params: s * * Here are some examples that illustrate how matching works. * - * All the examples assume the following DNS records are the "existing" records - * that a third-party is maintaining. (Don't be confused by the fact that we're - * using DNSControl notation for the records. Pretend some other system inserted them.) + * All the examples assume the following DNS records are the "existing" records that a third-party is maintaining. (Don't be confused by the fact that we're using DNSControl notation for the records. Pretend some other system inserted them.) * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), @@ -1729,8 +1620,7 @@ declare function HTTPS(name: string, priority: number, target: string, params: s * * ## Conflict handling * - * It is considered as an error for a `dnsconfig.js` to both ignore and insert the - * same record in a domain. This is done as a safety mechanism. + * It is considered as an error for a `dnsconfig.js` to both ignore and insert the same record in a domain. This is done as a safety mechanism. * * This will generate an error: * @@ -1742,8 +1632,7 @@ declare function HTTPS(name: string, priority: number, target: string, params: s * ... * ``` * - * To disable this safety check, add the `DISABLE_IGNORE_SAFETY_CHECK` statement - * to the `D()`. + * To disable this safety check, add the `DISABLE_IGNORE_SAFETY_CHECK` statement to the `D()`. * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), @@ -1757,9 +1646,7 @@ declare function HTTPS(name: string, priority: number, target: string, params: s * FYI: Previously DNSControl permitted disabling this check on * a per-record basis using `IGNORE_NAME_DISABLE_SAFETY_CHECK`: * - * The `IGNORE_NAME_DISABLE_SAFETY_CHECK` feature does not exist in the diff2 - * world and its use will result in a validation error. Use the above example - * instead. + * The `IGNORE_NAME_DISABLE_SAFETY_CHECK` feature does not exist in the diff2 world and its use will result in a validation error. Use the above example instead. * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), @@ -1783,26 +1670,19 @@ declare function HTTPS(name: string, priority: number, target: string, params: s declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: string): DomainModifier; /** - * `IGNORE_EXTERNAL_DNS` makes DNSControl automatically detect and ignore DNS records - * managed by Kubernetes external-dns. + * `IGNORE_EXTERNAL_DNS` makes DNSControl automatically detect and ignore DNS records managed by Kubernetes external-dns. * * ## Background * - * [External-dns](https://github.com/kubernetes-sigs/external-dns) is a popular - * Kubernetes controller that synchronizes exposed Kubernetes Services and Ingresses - * with DNS providers. It creates DNS records automatically based on annotations on - * your Kubernetes resources. + * [External-dns](https://github.com/kubernetes-sigs/external-dns) is a popular Kubernetes controller that synchronizes exposed Kubernetes Services and Ingresses with DNS providers. It creates DNS records automatically based on annotations on your Kubernetes resources. * - * External-dns uses TXT records to track ownership of the DNS records it manages. - * These TXT records contain metadata in this format: + * External-dns uses TXT records to track ownership of the DNS records it manages. These TXT records contain metadata in this format: * * ``` * "heritage=external-dns,external-dns/owner=,external-dns/resource=" * ``` * - * When you have both DNSControl and external-dns managing the same DNS zone, conflicts - * can occur. DNSControl will try to delete records created by external-dns, and - * external-dns will recreate them, leading to an endless update cycle. + * When you have both DNSControl and external-dns managing the same DNS zone, conflicts can occur. DNSControl will try to delete records created by external-dns, and external-dns will recreate them, leading to an endless update cycle. * * ## How it works * @@ -1821,8 +1701,7 @@ declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: strin * - `srv-` for SRV records * - `txt-` for TXT records (when external-dns manages TXT records) * - * For example, if external-dns creates an A record at `myapp.example.com`, it will - * also create a TXT record at `a-myapp.example.com` containing the heritage information. + * For example, if external-dns creates an A record at `myapp.example.com`, it will also create a TXT record at `a-myapp.example.com` containing the heritage information. * * ## Usage * @@ -1841,9 +1720,7 @@ declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: strin * * ## Custom Prefix Support * - * If your external-dns is configured with a custom `--txt-prefix` (as documented in the - * [external-dns TXT registry docs](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md#prefixes-and-suffixes)), - * pass that prefix to `IGNORE_EXTERNAL_DNS()`: + * If your external-dns is configured with a custom `--txt-prefix` (as documented in the [external-dns TXT registry docs](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md#prefixes-and-suffixes)), pass that prefix to `IGNORE_EXTERNAL_DNS()`: * * ```javascript * // If external-dns is configured with --txt-prefix="extdns-" @@ -1886,27 +1763,21 @@ declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: strin * * ### One per domain * - * Only one `IGNORE_EXTERNAL_DNS()` should be used per domain. If you call it multiple - * times, the last prefix wins. If you have multiple external-dns instances with - * different prefixes managing the same zone, use `IGNORE()` patterns for additional - * prefixes. + * Only one `IGNORE_EXTERNAL_DNS()` should be used per domain. If you call it multiple times, the last prefix wins. If you have multiple external-dns instances with different prefixes managing the same zone, use `IGNORE()` patterns for additional prefixes. * * ### TXT Registry Format * - * This feature relies on external-dns's [TXT registry](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md), - * which is the default registry type. The TXT record content format is well-documented: + * This feature relies on external-dns's [TXT registry](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md), which is the default registry type. The TXT record content format is well-documented: * * ``` * "heritage=external-dns,external-dns/owner=,external-dns/resource=" * ``` * - * This feature detects the `heritage=external-dns` marker in TXT records to identify - * external-dns managed records. + * This feature detects the `heritage=external-dns` marker in TXT records to identify external-dns managed records. * * ### Custom Prefix Support * - * This feature supports custom prefixes configured via external-dns's `--txt-prefix` flag. - * If you're using a custom prefix, pass it to `IGNORE_EXTERNAL_DNS()`: + * This feature supports custom prefixes configured via external-dns's `--txt-prefix` flag. If you're using a custom prefix, pass it to `IGNORE_EXTERNAL_DNS()`: * * ```javascript * // If external-dns uses --txt-prefix="extdns-" @@ -1926,8 +1797,7 @@ declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: strin * * #### Period Format for Apex Domains * - * If you need external-dns to manage apex (root) domain records, the external-dns - * documentation recommends using a prefix with `%{record_type}` followed by a period: + * If you need external-dns to manage apex (root) domain records, the external-dns documentation recommends using a prefix with `%{record_type}` followed by a period: * * ```yaml * # external-dns deployment args @@ -1935,8 +1805,7 @@ declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: strin * - --txt-prefix=extdns-%{record_type}. * ``` * - * This creates TXT records like `extdns-a.www` for the `www` A record, and `extdns-a` - * for the apex A record. DNSControl's `IGNORE_EXTERNAL_DNS` supports both formats: + * This creates TXT records like `extdns-a.www` for the `www` A record, and `extdns-a` for the apex A record. DNSControl's `IGNORE_EXTERNAL_DNS` supports both formats: * * - Hyphen format: `extdns-a-www` (from `--txt-prefix=extdns-` with default `%{record_type}-`) * - Period format: `extdns-a.www` (from `--txt-prefix=extdns-%{record_type}.`) @@ -1957,10 +1826,7 @@ declare function IGNORE(labelSpec: string, typeSpec?: string, targetSpec?: strin * * ### Legacy TXT Format * - * External-dns versions prior to v0.16 created TXT records without the record type - * prefix (e.g., `myapp.example.com` instead of `a-myapp.example.com`). This legacy - * format is supported but may match more records than intended since the record type - * cannot be determined. + * External-dns versions prior to v0.16 created TXT records without the record type prefix (e.g., `myapp.example.com` instead of `a-myapp.example.com`). This legacy format is supported but may match more records than intended since the record type cannot be determined. * * ## See also * @@ -2068,10 +1934,7 @@ declare function IP(ip: string): number; * A use case for LOC is suggested in the RFC: * * > Some uses for the LOC RR have already been suggested, including the - * USENET backbone flow maps, a "visual traceroute" application showing - * the geographical path of an IP packet, and network management - * applications that could use LOC RRs to generate a map of hosts and - * routers being managed. + * USENET backbone flow maps, a "visual traceroute" application showing the geographical path of an IP packet, and network management applications that could use LOC RRs to generate a map of hosts and routers being managed. * * There is the UK based [https://find.me.uk](https://find.me.uk/) whereby you can do: * @@ -2082,15 +1945,9 @@ declare function IP(ip: string): number; * There are some behaviours that you should be aware of, however: * * > If omitted, minutes and seconds default to zero, size defaults to 1m, - * horizontal precision defaults to 10000m, and vertical precision - * defaults to 10m. These defaults are chosen to represent typical - * ZIP/postal code area sizes, since it is often easy to find - * approximate geographical location by ZIP/postal code. + * horizontal precision defaults to 10000m, and vertical precision defaults to 10m. These defaults are chosen to represent typical ZIP/postal code area sizes, since it is often easy to find approximate geographical location by ZIP/postal code. * - * Alas, the world does not revolve around US ZIP codes, but here we are. Internally, - * the LOC record type will supply defaults where values were absent on DNS import. - * One must supply the `LOC()` js helper all parameters. If that seems like too - * much work, see also helper functions: + * Alas, the world does not revolve around US ZIP codes, but here we are. Internally, the LOC record type will supply defaults where values were absent on DNS import. One must supply the `LOC()` js helper all parameters. If that seems like too much work, see also helper functions: * * * [`LOC_BUILDER_DD({})`](LOC_BUILDER_DD.md) - build a `LOC` by supplying only **d**ecimal **d**egrees. * * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E @@ -2103,9 +1960,7 @@ declare function IP(ip: string): number; * * `degrees,minutes,seconds,[NnSs],deg,min,sec,[EeWw],altitude,size,horizontal_precision,vertical_precision` * - * where: - * altitude: [-100000.00 .. 42849672.95] BY .01 (altitude in meters) - * size, horizontal_precision, vertical_precision: [0 .. 90000000.00] (size/precision in meters) + * where: altitude: [-100000.00 .. 42849672.95] BY .01 (altitude in meters) size, horizontal_precision, vertical_precision: [0 .. 90000000.00] (size/precision in meters) * * values outside of the above ranges are gated to within the ranges. * @@ -2583,15 +2438,11 @@ declare function MIKROTIK_NXDOMAIN(name: string, ...modifiers: RecordModifier[]) declare function MX(name: string, priority: number, target: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `NAMESERVER()` instructs DNSControl to inform the domain's registrar where to find this zone. - * For some registrars this will also add NS records to the zone itself. + * `NAMESERVER()` instructs DNSControl to inform the domain's registrar where to find this zone. For some registrars this will also add NS records to the zone itself. * - * This takes exactly one argument: the name of the nameserver. It must end with - * a "." if it is a FQDN, just like all targets. + * This takes exactly one argument: the name of the nameserver. It must end with a "." if it is a FQDN, just like all targets. * - * This is different than the [`NS()`](NS.md) function, which inserts NS records - * in the current zone and accepts a label. [`NS()`](NS.md) is for downward - * delegations. `NAMESERVER()` is for informing upstream delegations. + * This is different than the [`NS()`](NS.md) function, which inserts NS records in the current zone and accepts a label. [`NS()`](NS.md) is for downward delegations. `NAMESERVER()` is for informing upstream delegations. * * For more information, refer to [this page](../../advanced-features/nameservers.md). * @@ -2613,43 +2464,25 @@ declare function MX(name: string, priority: number, target: string, ...modifiers * * # The difference between NS() and NAMESERVER() * - * Nameservers are one of the least - * understood parts of DNS, so a little extra explanation is required. + * Nameservers are one of the least understood parts of DNS, so a little extra explanation is required. * - * * [`NS()`](NS.md) adds an NS record to a zone, just like [`A()`](A.md) adds an A - * record to the zone. This is generally used to delegate a subzone. + * * [`NS()`](NS.md) adds an NS record to a zone, just like [`A()`](A.md) adds an A record to the zone. This is generally used to delegate a subzone. * * * The `NAMESERVER()` directive speaks to the Registrar about how the parent should delegate the zone. * - * Since the parent zone could be completely unrelated to the current - * zone, changes made by `NAMESERVER()` have to be done by an API call to - * the registrar, who then figures out what to do. For example, if I - * use `NAMESERVER()` in the zone `stackoverflow.com`, DNSControl talks to - * the registrar who does the hard work of talking to the people that - * control `.com`. If the domain was `gmeet.io`, the registrar does - * the right thing to talk to the people that control `.io`. + * Since the parent zone could be completely unrelated to the current zone, changes made by `NAMESERVER()` have to be done by an API call to the registrar, who then figures out what to do. For example, if I use `NAMESERVER()` in the zone `stackoverflow.com`, DNSControl talks to the registrar who does the hard work of talking to the people that control `.com`. If the domain was `gmeet.io`, the registrar does the right thing to talk to the people that control `.io`. * - * (A better name might have been `PARENTNAMESERVER()` but we didn't - * think of that at the time.) + * (A better name might have been `PARENTNAMESERVER()` but we didn't think of that at the time.) * - * Each registrar handles delegations differently. Most use - * the `NAMESERVER()` targets to update the delegation, adding - * `NS` records to the parent zone as required. - * Some providers restrict the names to hosts they control. - * Others may require you to add the `NS` records to the parent domain - * manually. + * Each registrar handles delegations differently. Most use the `NAMESERVER()` targets to update the delegation, adding `NS` records to the parent zone as required. Some providers restrict the names to hosts they control. Others may require you to add the `NS` records to the parent domain manually. * * # How to prevent changing the parent NS records? * - * If dnsconfig.js has zero `NAMESERVER()` commands for a domain, it will - * use the API to remove all non-default nameservers. + * If dnsconfig.js has zero `NAMESERVER()` commands for a domain, it will use the API to remove all non-default nameservers. * - * If `dnsconfig.js` has 1 or more `NAMESERVER()` commands for a domain, it - * will use the API to add those nameservers (unless, of course, - * they already exist). + * If `dnsconfig.js` has 1 or more `NAMESERVER()` commands for a domain, it will use the API to add those nameservers (unless, of course, they already exist). * - * So how do you tell DNSControl not to make any changes at all? Use the - * special Registrar called "NONE". It makes no changes. + * So how do you tell DNSControl not to make any changes at all? Use the special Registrar called "NONE". It makes no changes. * * It looks like this: * @@ -2888,28 +2721,17 @@ declare function NAMESERVER_TTL(ttl: Duration): DomainModifier; declare function NAPTR(subdomain: string, order: number, preference: number, terminalflag: string, service: string, regexp: string, target: string): DomainModifier; /** - * `NO_PURGE` indicates that existing records should not be deleted from a domain. - * Records will be added and updated, but not removed. + * `NO_PURGE` indicates that existing records should not be deleted from a domain. Records will be added and updated, but not removed. * - * Suppose a domain is managed by both DNSControl and a third-party system. This - * creates a problem because DNSControl will try to delete records inserted by the - * other system. + * Suppose a domain is managed by both DNSControl and a third-party system. This creates a problem because DNSControl will try to delete records inserted by the other system. * - * By setting `NO_PURGE` on a domain, this tells DNSControl not to delete the - * records found in the domain. + * By setting `NO_PURGE` on a domain, this tells DNSControl not to delete the records found in the domain. * * It is similar to [`IGNORE`](IGNORE.md) but more general. * - * The original reason for `NO_PURGE` was that a legacy system was adopting - * DNSControl. Previously the domain was managed via Microsoft DNS Server's GUI. - * ActiveDirectory was in use, so various records were being inserted behind the - * scenes. It was decided to use DNSControl to simply insert a few records. The - * `NO_PURGE` setting instructed DNSControl not to delete the existing records. + * The original reason for `NO_PURGE` was that a legacy system was adopting DNSControl. Previously the domain was managed via Microsoft DNS Server's GUI. ActiveDirectory was in use, so various records were being inserted behind the scenes. It was decided to use DNSControl to simply insert a few records. The `NO_PURGE` setting instructed DNSControl not to delete the existing records. * - * In this example DNSControl will insert "foo.example.com" into the zone, but - * otherwise leave the zone alone. Changes to "foo"'s IP address will update the - * record. Removing the A("foo", ...) record from DNSControl will leave the record - * in place. + * In this example DNSControl will insert "foo.example.com" into the zone, but otherwise leave the zone alone. Changes to "foo"'s IP address will update the record. Removing the A("foo", ...) record from DNSControl will leave the record in place. * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), NO_PURGE, @@ -2917,20 +2739,13 @@ declare function NAPTR(subdomain: string, order: number, preference: number, ter * ); * ``` * - * The main caveat of `NO_PURGE` is that intentionally deleting records becomes - * more difficult. Suppose a `NO_PURGE` zone has an record such as A("ken", - * "1.2.3.4"). Removing the record from `dnsconfig.js` will not delete "ken" from - * the domain. DNSControl has no way of knowing the record was deleted from the - * file The DNS record must be removed manually. Users of `NO_PURGE` are prone - * to finding themselves with an accumulation of orphaned DNS records. That's easy - * to fix for a small zone but can be a big mess for large zones. + * The main caveat of `NO_PURGE` is that intentionally deleting records becomes more difficult. Suppose a `NO_PURGE` zone has an record such as A("ken", "1.2.3.4"). Removing the record from `dnsconfig.js` will not delete "ken" from the domain. DNSControl has no way of knowing the record was deleted from the file The DNS record must be removed manually. Users of `NO_PURGE` are prone to finding themselves with an accumulation of orphaned DNS records. That's easy to fix for a small zone but can be a big mess for large zones. * * ## Support * * Prior to DNSControl v4.0.0, not all providers supported `NO_PURGE`. * - * With introduction of `diff2` algorithm (enabled by default in v4.0.0), - * `NO_PURGE` works with all providers. + * With introduction of `diff2` algorithm (enabled by default in v4.0.0), `NO_PURGE` works with all providers. * * ## See also * @@ -3041,15 +2856,11 @@ declare function NewDnsProvider(name: string, meta?: object): string; declare function NewRegistrar(name: string, type?: string, meta?: object): string; /** - * `OPENPGPKEY` adds an [OpenPGP public key - * record](https://datatracker.ietf.org/doc/html/rfc7929) to the domain. + * `OPENPGPKEY` adds an [OpenPGP public key record](https://datatracker.ietf.org/doc/html/rfc7929) to the domain. * - * So far, no transformation is applied to the parameters. The data will be - * passed to the DNS server as-is. DNSControl supports both hex-encoded and - * base64-encoded input for the public key portion of the record. + * So far, no transformation is applied to the parameters. The data will be passed to the DNS server as-is. DNSControl supports both hex-encoded and base64-encoded input for the public key portion of the record. * - * There are multiple ways to generate the appropriately-formatted record - * values: + * There are multiple ways to generate the appropriately-formatted record values: * * 1. By using `gpg --export-options=export-dane`: * @@ -3123,9 +2934,7 @@ declare function NewRegistrar(name: string, type?: string, meta?: object): strin * ``` * {% endcode %} * - * 3. By using the [`hash-slinger` - * package](https://github.com/letoams/hash-slinger/) (which is - * available in most Linux distro package repositories): + * 3. By using the [`hash-slinger` package](https://github.com/letoams/hash-slinger/) (which is available in most Linux distro package repositories): * * {% code title="Shell Transcript" %} * ```shell-session @@ -3194,53 +3003,25 @@ declare function PORKBUN_URLFWD(name: string, target: string, ...modifiers: Reco /** * `PTR` adds a [PTR Resource record](https://www.rfc-editor.org/rfc/rfc1035) to the domain. * - * The name is normally a relative label for the domain, or a FQDN that ends with `.`. If magic mode is enabled (see below) it can also be an IP address, which will be replaced by the proper string automatically, thus - * saving the user from having to reverse the IP address manually. + * The name is normally a relative label for the domain, or a FQDN that ends with `.`. If magic mode is enabled (see below) it can also be an IP address, which will be replaced by the proper string automatically, thus saving the user from having to reverse the IP address manually. * * Target should be a string representing the FQDN of a host. Like all FQDNs in DNSControl, it must end with a `.`. * * # Magic Mode * - * PTR records are complex and typos are common. Therefore DNSControl - * enables features to save labor and - * prevent typos. This magic is only - * enabled when the domain ends with `in-addr.arpa.` or `ipv6.arpa.`. - * - * *Automatic IP-to-reverse:* If the name is a valid IP address, DNSControl will replace it with - * a string that is appropriate for the domain. That is, if the domain - * ends with `in-addr.arpa` (no `.`) and name is a valid IPv4 address, the name - * will be replaced with the correct string to make a reverse lookup for that address. - * IPv6 is properly handled too. - * - * *Extra Validation:* DNSControl considers it an error to include a name that - * is inappropriate for the domain. For example - * `PTR("1.2.3.4", "f.co.")` is valid for the domain `D("3.2.1.in-addr.arpa",` - * but DNSControl will generate an error if the domain is `D("9.9.9.in-addr.arpa",`. - * This is because `1.2.3.4` is contained in `1.2.3.0/24` but not `9.9.9.0/24`. - * This validation works for IPv6, IPv4, and - * RFC2317 "Classless in-addr.arpa delegation" domains. - * - * *Automatic truncation:* DNSControl will automatically truncate FQDNs - * as needed. - * If the name is a FQDN ending with `.`, DNSControl will verify that the - * name is contained within the CIDR block implied by domain. For example - * if name is `4.3.2.1.in-addr.arpa.` (note the trailing `.`) - * and the domain is `2.1.in-addr.arpa` (no trailing `.`) - * then the name will be replaced with `4.3`. Note that the output - * of `REV("1.2.3.4")` is `4.3.2.1.in-addr.arpa.`, which means the following - * are all equivalent: + * PTR records are complex and typos are common. Therefore DNSControl enables features to save labor and prevent typos. This magic is only enabled when the domain ends with `in-addr.arpa.` or `ipv6.arpa.`. + * + * *Automatic IP-to-reverse:* If the name is a valid IP address, DNSControl will replace it with a string that is appropriate for the domain. That is, if the domain ends with `in-addr.arpa` (no `.`) and name is a valid IPv4 address, the name will be replaced with the correct string to make a reverse lookup for that address. IPv6 is properly handled too. + * + * *Extra Validation:* DNSControl considers it an error to include a name that is inappropriate for the domain. For example `PTR("1.2.3.4", "f.co.")` is valid for the domain `D("3.2.1.in-addr.arpa",` but DNSControl will generate an error if the domain is `D("9.9.9.in-addr.arpa",`. This is because `1.2.3.4` is contained in `1.2.3.0/24` but not `9.9.9.0/24`. This validation works for IPv6, IPv4, and RFC2317 "Classless in-addr.arpa delegation" domains. + * + * *Automatic truncation:* DNSControl will automatically truncate FQDNs as needed. If the name is a FQDN ending with `.`, DNSControl will verify that the name is contained within the CIDR block implied by domain. For example if name is `4.3.2.1.in-addr.arpa.` (note the trailing `.`) and the domain is `2.1.in-addr.arpa` (no trailing `.`) then the name will be replaced with `4.3`. Note that the output of `REV("1.2.3.4")` is `4.3.2.1.in-addr.arpa.`, which means the following are all equivalent: * * * `PTR(REV("1.2.3.4", ...` * * `PTR("4.3.2.1.in-addr.arpa.", ...` * * `PTR("4.3", ...` // Assuming the domain is `2.1.in-addr.arpa` * - * All magic is RFC2317-aware. We use the first format listed in the - * RFC for both [`REV()`](../top-level-functions/REV.md) and `PTR()`. The format is - * `FIRST/MASK.C.B.A.in-addr.arpa` where `FIRST` is the first IP address - * of the zone, `MASK` is the netmask of the zone (25-31 inclusive), - * and A, B, C are the first 3 octets of the IP address. For example - * `172.20.18.130/27` is located in a zone named - * `128/27.18.20.172.in-addr.arpa` + * All magic is RFC2317-aware. We use the first format listed in the RFC for both [`REV()`](../top-level-functions/REV.md) and `PTR()`. The format is `FIRST/MASK.C.B.A.in-addr.arpa` where `FIRST` is the first IP address of the zone, `MASK` is the netmask of the zone (25-31 inclusive), and A, B, C are the first 3 octets of the IP address. For example `172.20.18.130/27` is located in a zone named `128/27.18.20.172.in-addr.arpa` * * ```javascript * D(REV("1.2.3.0/24"), REGISTRAR, DnsProvider(BIND), @@ -3269,10 +3050,7 @@ declare function PORKBUN_URLFWD(name: string, target: string, ...modifiers: Reco * * # Automatic forward and reverse lookups * - * DNSControl does not automatically generate forward and reverse lookups. However - * it is possible to write a macro that does this by using the - * [`D_EXTEND()`](../top-level-functions/D_EXTEND.md) - * function to insert `A` and `PTR` records into previously-defined domains. + * DNSControl does not automatically generate forward and reverse lookups. However it is possible to write a macro that does this by using the [`D_EXTEND()`](../top-level-functions/D_EXTEND.md) function to insert `A` and `PTR` records into previously-defined domains. * * ```javascript * function FORWARD_AND_REVERSE(ipaddr, fqdn) { @@ -3300,11 +3078,9 @@ declare function PORKBUN_URLFWD(name: string, target: string, ...modifiers: Reco declare function PTR(name: string, target: string, ...modifiers: RecordModifier[]): DomainModifier; /** - * `PURGE` is the default setting for all domains. Therefore `PURGE` is - * a no-op. It is included for completeness only. + * `PURGE` is the default setting for all domains. Therefore `PURGE` is a no-op. It is included for completeness only. * - * A domain with a mixture of `NO_PURGE` and `PURGE` parameters will abide - * by the last one. + * A domain with a mixture of `NO_PURGE` and `PURGE` parameters will abide by the last one. * * These three examples all are equivalent. * @@ -3401,9 +3177,7 @@ declare function R53_EVALUATE_TARGET_HEALTH(enabled: boolean): RecordModifier; declare function R53_ZONE(zone_id: string): DomainModifier & RecordModifier; /** - * `REV` returns the reverse lookup domain for an IP network. For - * example `REV("1.2.3.0/24")` returns `3.2.1.in-addr.arpa.` and - * `REV("2001:db8:302::/48")` returns `2.0.3.0.8.b.d.0.1.0.0.2.ip6.arpa.`. + * `REV` returns the reverse lookup domain for an IP network. For example `REV("1.2.3.0/24")` returns `3.2.1.in-addr.arpa.` and `REV("2001:db8:302::/48")` returns `2.0.3.0.8.b.d.0.1.0.0.2.ip6.arpa.`. * * `REV()` is commonly used with the [`D()`](D.md) functions to create reverse DNS lookup zones. * @@ -3419,26 +3193,19 @@ declare function R53_ZONE(zone_id: string): DomainModifier & RecordModifier; * * The latter is easier to type and less error-prone. * - * If the address does not include a "/" then `REV()` assumes /32 for IPv4 addresses - * and /128 for IPv6 addresses. + * If the address does not include a "/" then `REV()` assumes /32 for IPv4 addresses and /128 for IPv6 addresses. * * # RFC compliance * - * `REV()` implements both RFC 2317 and the newer RFC 4183. The `REVCOMPAT()` - * function selects which mode is used. If `REVCOMPAT()` is not called, a default - * is selected for you. The default will change to RFC 4183 in DNSControl v5.0. + * `REV()` implements both RFC 2317 and the newer RFC 4183. The `REVCOMPAT()` function selects which mode is used. If `REVCOMPAT()` is not called, a default is selected for you. The default will change to RFC 4183 in DNSControl v5.0. * * See [`REVCOMPAT()`](REVCOMPAT.md) for details. * * # Host bits * - * v4.x: - * The host bits (the ones outside the netmask) must be zeros. They are not zeroed - * out automatically. Thus, `REV("1.2.3.4/24")` is an error. + * v4.x: The host bits (the ones outside the netmask) must be zeros. They are not zeroed out automatically. Thus, `REV("1.2.3.4/24")` is an error. * - * v5.0 and later: - * The host bits (the ones outside the netmask) are ignored. Thus - * `REV("1.2.3.4/24")` and `REV("1.2.3.0/24")` are equivalent. + * v5.0 and later: The host bits (the ones outside the netmask) are ignored. Thus `REV("1.2.3.4/24")` and `REV("1.2.3.0/24")` are equivalent. * * # Examples * @@ -3463,9 +3230,7 @@ declare function R53_ZONE(zone_id: string): DomainModifier & RecordModifier; * * # Automatic forward and reverse record generation * - * DNSControl does not automatically generate forward and reverse lookups. However - * it is possible to write a macro that does this. See - * [`PTR()`](../domain-modifiers/PTR.md) for an example. + * DNSControl does not automatically generate forward and reverse lookups. However it is possible to write a macro that does this. See [`PTR()`](../domain-modifiers/PTR.md) for an example. * * @see https://docs.dnscontrol.org/language-reference/top-level-functions/rev */ @@ -3481,20 +3246,15 @@ declare function REV(address: string): string; * REVCOMPAT("rfc4183"); // RFC 4183: Adopt the newer standard. * ``` * - * `REVCOMPAT()` is global for all of `dnsconfig.js`. It must appear before any - * use of `REV()`; If not, behavior is undefined. + * `REVCOMPAT()` is global for all of `dnsconfig.js`. It must appear before any use of `REV()`; If not, behavior is undefined. * * # RFC 4183 vs RFC 2317 * - * RFC 2317 and RFC 4183 are two different ways to implement reverse lookups for - * CIDR blocks that are not on 8-bit boundaries (/24, /16, /8). + * RFC 2317 and RFC 4183 are two different ways to implement reverse lookups for CIDR blocks that are not on 8-bit boundaries (/24, /16, /8). * - * Originally DNSControl implemented the older standard, which only specifies what - * to do for /8, /16, /24 - /32. Using `REV()` for /9-17 and /17-23 CIDRs was an - * error. + * Originally DNSControl implemented the older standard, which only specifies what to do for /8, /16, /24 - /32. Using `REV()` for /9-17 and /17-23 CIDRs was an error. * - * v4 defaults to RFC 2317. In v5.0 the default will change to RFC 4183. - * `REVCOMPAT()` is provided for those that wish to retain the old behavior. + * v4 defaults to RFC 2317. In v5.0 the default will change to RFC 4183. `REVCOMPAT()` is provided for those that wish to retain the old behavior. * * For more information, see [Opinion #9](../../advanced-features/opinions.md#opinion-9-rfc-4183-is-better-than-rfc-2317). * @@ -3583,9 +3343,7 @@ declare function SMIMEA(name: string, usage: number, selector: number, type: num declare function SOA(name: string, ns: string, mbox: string, refresh: number, retry: number, expire: number, minttl: number, ...modifiers: RecordModifier[]): DomainModifier; /** - * DNSControl can optimize the SPF settings on a domain by flattening - * (inlining) includes and removing duplicates. DNSControl also makes - * it easier to document your SPF configuration. + * DNSControl can optimize the SPF settings on a domain by flattening (inlining) includes and removing duplicates. DNSControl also makes it easier to document your SPF configuration. * * WARNING: Flattening SPF includes is risky. Only flatten an SPF * setting if it is absolutely needed to bring the number of "lookups" @@ -3648,8 +3406,7 @@ declare function SOA(name: string, ns: string, mbox: string, refresh: number, re * * ## Syntax * - * When you want to specify SPF settings for a domain, use the - * `SPF_BUILDER()` function. + * When you want to specify SPF settings for a domain, use the `SPF_BUILDER()` function. * * ```javascript * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), @@ -3686,8 +3443,7 @@ declare function SOA(name: string, ns: string, mbox: string, refresh: number, re * * `parts:` The individual parts of the SPF settings. * * `flatten:` Which includes should be inlined. For safety purposes the flattening is done on an opt-in basis. If `"*"` is listed, all includes will be flattened... this might create more problems than is solves due to length limitations. * - * [multi-string]: https://tools.ietf.org/html/rfc4408#section-3.1.3 - * [record-size]: https://tools.ietf.org/html/rfc4408#section-3.1.4 + * [multi-string]: https://tools.ietf.org/html/rfc4408#section-3.1.3 [record-size]: https://tools.ietf.org/html/rfc4408#section-3.1.4 * * `SPF_BUILDER()` returns multiple `TXT()` records: * @@ -3698,32 +3454,21 @@ declare function SOA(name: string, ns: string, mbox: string, refresh: number, re * * `TXT("_rawspf", "v=spf1 .... ~all")` * * This is the unaltered SPF configuration. This is purely for debugging purposes and is not used by any email or anti-spam system. It is only generated if flattening is requested. * - * We recommend first using this without any flattening. Make sure - * `dnscontrol preview` works as expected. Once that is done, add the - * flattening required to reduce the number of lookups to 10 or less. + * We recommend first using this without any flattening. Make sure `dnscontrol preview` works as expected. Once that is done, add the flattening required to reduce the number of lookups to 10 or less. * - * To count the number of lookups, you can use our interactive SPF - * debugger at [https://dnscontrol.github.io/dnscontrol/flattener/index.html](https://dnscontrol.github.io/dnscontrol/flattener/index.html) + * To count the number of lookups, you can use our interactive SPF debugger at [https://dnscontrol.github.io/dnscontrol/flattener/index.html](https://dnscontrol.github.io/dnscontrol/flattener/index.html) * * # The first in a chain is special * - * When generating the chain of SPF - * records, each one is max length 255. For the first item in - * the chain, the max is 255 - "overhead1". Setting this to 255 or - * higher has undefined behavior. + * When generating the chain of SPF records, each one is max length 255. For the first item in the chain, the max is 255 - "overhead1". Setting this to 255 or higher has undefined behavior. * * Why is this useful? * - * Some sites desire having all DNS queries fit in a single packet so - * that UDP, not TCP, can be used to satisfy all requests. That means all - * responses have to be relatively small. + * Some sites desire having all DNS queries fit in a single packet so that UDP, not TCP, can be used to satisfy all requests. That means all responses have to be relatively small. * - * When an SPF system does a "TXT" lookup, it gets SPF and non-SPF - * records. This makes the first link in the chain extra large. + * When an SPF system does a "TXT" lookup, it gets SPF and non-SPF records. This makes the first link in the chain extra large. * - * The bottom line is that if you want the TXT records to fit in a UDP - * packet, keep increasing the value of `overhead1` until the packet - * is no longer truncated. + * The bottom line is that if you want the TXT records to fit in a UDP packet, keep increasing the value of `overhead1` until the packet is no longer truncated. * * Example: * @@ -3739,30 +3484,17 @@ declare function SOA(name: string, ns: string, mbox: string, refresh: number, re * 582 * ``` * - * Since 582 is bigger than 255, it might not be possible to achieve the - * goal. Any value larger than 255 will disable all flattening. Try - * 170, then 180, 190 until you get the desired results. + * Since 582 is bigger than 255, it might not be possible to achieve the goal. Any value larger than 255 will disable all flattening. Try 170, then 180, 190 until you get the desired results. * - * A validator such as - * [https://www.kitterman.com/spf/validate.html](https://www.kitterman.com/spf/validate.html) - * will tell you if the queries are being truncated and TCP was required - * to get the entire record. (Sadly it caches heavily.) + * A validator such as [https://www.kitterman.com/spf/validate.html](https://www.kitterman.com/spf/validate.html) will tell you if the queries are being truncated and TCP was required to get the entire record. (Sadly it caches heavily.) * * ## Notes about the `spfcache.json` * - * DNSControl will optionally keep a cache of the DNS lookups performed during - * optimization. In the event that a DNS server is down, the cache will be used. - * This makes it possible to do `dnscontrol - * push` even if your or third-party DNS servers are down. + * DNSControl will optionally keep a cache of the DNS lookups performed during optimization. In the event that a DNS server is down, the cache will be used. This makes it possible to do `dnscontrol push` even if your or third-party DNS servers are down. * - * To enable this feature, create an (empty) file called `spfcache.json` in the - * current directory. To disable this feature, delete the file. There are no - * command-line flags related to this feature. + * To enable this feature, create an (empty) file called `spfcache.json` in the current directory. To disable this feature, delete the file. There are no command-line flags related to this feature. * - * The `spfcache.json` stored the cached DNS lookups. If it needs - * to be updated, the new file contents will be written to a file called - * `spfcache.updated.json` and instructions such as the ones below - * will be output telling you exactly what to do: + * The `spfcache.json` stored the cached DNS lookups. If it needs to be updated, the new file contents will be written to a file called `spfcache.updated.json` and instructions such as the ones below will be output telling you exactly what to do: * * ```shell * dnscontrol preview @@ -3773,70 +3505,41 @@ declare function SOA(name: string, ns: string, mbox: string, refresh: number, re * $ git commit spfcache.json * ``` * - * In this case, you are being asked to replace `spfcache.json` with - * the newly generated data in `spfcache.updated.json`. + * In this case, you are being asked to replace `spfcache.json` with the newly generated data in `spfcache.updated.json`. * - * The instructions are hardcoded strings. The filenames will - * not change. - * The instructions assume you use git. If you use something - * else, please do the appropriate equivalent command. + * The instructions are hardcoded strings. The filenames will not change. The instructions assume you use git. If you use something else, please do the appropriate equivalent command. * * ## Caveats * - * 1. DNSControl 'gives up' if it sees SPF records it can't understand. - * This includes: syntax errors, features that our spflib doesn't know - * about, overly complex SPF settings, and anything else that we we - * didn't feel like implementing. + * 1. DNSControl 'gives up' if it sees SPF records it can't understand. This includes: syntax errors, features that our spflib doesn't know about, overly complex SPF settings, and anything else that we we didn't feel like implementing. * - * 2. The TXT record that is generated may exceed DNS limits. dnscontrol - * will not generate a single TXT record that exceeds DNS limits, but - * it ignores the fact that there may be other TXT records on the same - * label. For example, suppose it generates a TXT record on the bare - * domain (stackoverflow.com) that is 250 bytes long. That's fine and - * doesn't require a continuation record. However if there is another - * TXT record (not an SPF record, perhaps a TXT record used to verify - * domain ownership), the total packet size of all the TXT records - * could exceed 512 bytes, and will require EDNS or a TCP request. + * 2. The TXT record that is generated may exceed DNS limits. dnscontrol will not generate a single TXT record that exceeds DNS limits, but it ignores the fact that there may be other TXT records on the same label. For example, suppose it generates a TXT record on the bare domain (stackoverflow.com) that is 250 bytes long. That's fine and doesn't require a continuation record. However if there is another TXT record (not an SPF record, perhaps a TXT record used to verify domain ownership), the total packet size of all the TXT records could exceed 512 bytes, and will require EDNS or a TCP request. * - * 3. DNSControl does not warn if the number of lookups exceeds 10. - * We hope to implement this some day. + * 3. DNSControl does not warn if the number of lookups exceeds 10. We hope to implement this some day. * - * 4. The `redirect=` directive is only partially implemented. We only - * handle the case where redirect is the last item in the SPF record. - * In which case, it is equivalent to `include:`. + * 4. The `redirect=` directive is only partially implemented. We only handle the case where redirect is the last item in the SPF record. In which case, it is equivalent to `include:`. * * ## Advanced Technique: Interactive SPF Debugger * - * DNSControl includes an experimental system for viewing - * SPF settings: + * DNSControl includes an experimental system for viewing SPF settings: * * [https://dnscontrol.github.io/dnscontrol/flattener/index.html](https://dnscontrol.github.io/dnscontrol/flattener/index.html) * - * You can also run this locally (it is self-contained) by opening - * `dnscontrol/docs/flattener/index.html` in your browser. + * You can also run this locally (it is self-contained) by opening `dnscontrol/docs/flattener/index.html` in your browser. * - * You can use this to determine the minimal number of domains you - * need to flatten to have fewer than 10 lookups. + * You can use this to determine the minimal number of domains you need to flatten to have fewer than 10 lookups. * * The output is as follows: * - * 1. The top part lists the domain as it current is configured, how - * many lookups it requires, and includes a checkbox for each item - * that could be flattened. + * 1. The top part lists the domain as it current is configured, how many lookups it requires, and includes a checkbox for each item that could be flattened. * - * 2. Fully flattened: This section shows the SPF configuration if you - * fully flatten it. i.e. This is what it would look like if all the - * checkboxes were checked. Note that this result is likely to be - * longer than 255 bytes, the limit for a single TXT string. + * 2. Fully flattened: This section shows the SPF configuration if you fully flatten it. i.e. This is what it would look like if all the checkboxes were checked. Note that this result is likely to be longer than 255 bytes, the limit for a single TXT string. * - * 3. Fully flattened split: This takes the "fully flattened" result - * and splits it into multiple DNS records. To continue to the next - * record an include is added. + * 3. Fully flattened split: This takes the "fully flattened" result and splits it into multiple DNS records. To continue to the next record an include is added. * * ## Advanced Technique: Define once, use many * - * In some situations we define an SPF setting once and want to reuse - * it on many domains. Here's how to do this: + * In some situations we define an SPF setting once and want to reuse it on many domains. Here's how to do this: * * ```javascript * var SPF_MYSETTINGS = SPF_BUILDER({ @@ -3988,15 +3691,11 @@ declare function TLSA(name: string, usage: number, selector: number, type: numbe declare function TTL(ttl: Duration): RecordModifier; /** - * `TXT` adds a [Text record](https://www.rfc-editor.org/rfc/rfc1035) to a domain. The name should be the relative - * label for the record. Use `@` for the domain apex. + * `TXT` adds a [Text record](https://www.rfc-editor.org/rfc/rfc1035) to a domain. The name should be the relative label for the record. Use `@` for the domain apex. * - * The contents is either a single or multiple strings. To - * specify multiple strings, specify them as an array. + * The contents is either a single or multiple strings. To specify multiple strings, specify them as an array. * - * Each string is a JavaScript string (quoted using single or double - * quotes). The (somewhat complex) quoting rules of the DNS protocol - * will be done for you. + * Each string is a JavaScript string (quoted using single or double quotes). The (somewhat complex) quoting rules of the DNS protocol will be done for you. * * Modifiers can be any number of [record modifiers](https://docs.dnscontrol.org/language-reference/record-modifiers) or JSON objects, which will be merged into the record's metadata. * @@ -4016,74 +3715,37 @@ declare function TTL(ttl: Duration): RecordModifier; * * ### Long strings * - * Strings that are longer than 255 octets (bytes) will be quietly - * split into 255-octets chunks or the provider may report an error - * if it does not handle multiple strings. + * Strings that are longer than 255 octets (bytes) will be quietly split into 255-octets chunks or the provider may report an error if it does not handle multiple strings. * * ### TXT record edge cases * - * Most providers do not support the full possibilities of what a `TXT` - * record can store. DNSControl can not handle all the edge cases - * and incompatibles that providers have introduced. Instead, it - * stores the string(s) that you provide and passes them to the provider - * verbatim. The provider may opt to accept the data, fix it, or - * reject it. This happens early in the processing, long before - * the DNSControl talks to the provider's API. + * Most providers do not support the full possibilities of what a `TXT` record can store. DNSControl can not handle all the edge cases and incompatibles that providers have introduced. Instead, it stores the string(s) that you provide and passes them to the provider verbatim. The provider may opt to accept the data, fix it, or reject it. This happens early in the processing, long before the DNSControl talks to the provider's API. * - * The RFCs specify that a `TXT` record stores one or more strings, - * each is up to 255 octets (bytes) long. We call these individual - * strings *chunks*. Each chunk may be zero to 255 octets long. - * There is no limit to the number of chunks in a `TXT` record, - * other than IP packet length restrictions. The contents of each chunk - * may be octets of value from 0x00 to 0xff. + * The RFCs specify that a `TXT` record stores one or more strings, each is up to 255 octets (bytes) long. We call these individual strings *chunks*. Each chunk may be zero to 255 octets long. There is no limit to the number of chunks in a `TXT` record, other than IP packet length restrictions. The contents of each chunk may be octets of value from 0x00 to 0xff. * - * In reality DNS Service Providers (DSPs) place many restrictions on `TXT` - * records. + * In reality DNS Service Providers (DSPs) place many restrictions on `TXT` records. * - * Some DSPs only support a single string of 255 octets or fewer. - * Multiple strings, or any one string being longer than 255 octets will - * result in an error. One provider limits the string to 254 octets, - * which makes me think they're code has an off-by-one error. + * Some DSPs only support a single string of 255 octets or fewer. Multiple strings, or any one string being longer than 255 octets will result in an error. One provider limits the string to 254 octets, which makes me think they're code has an off-by-one error. * - * Some DSPs only support one string, but it may be of any length. - * Behind the scenes the provider splits it into 255-octet chunks - * (except the last one, of course). + * Some DSPs only support one string, but it may be of any length. Behind the scenes the provider splits it into 255-octet chunks (except the last one, of course). * - * Some DSPs support multiple strings, but API requests must be 512-bytes - * or fewer, and with quoting, escaping, and other encoding mishegoss - * you can't be sure what will be permitted until you actually try it. + * Some DSPs support multiple strings, but API requests must be 512-bytes or fewer, and with quoting, escaping, and other encoding mishegoss you can't be sure what will be permitted until you actually try it. * - * Regardless of the quantity and length of strings, some providers ban - * double quotes, back-ticks, or other chars. + * Regardless of the quantity and length of strings, some providers ban double quotes, back-ticks, or other chars. * * ### Testing the support of a provider * * #### How can you tell if a provider will support a particular `TXT()` record? * - * Include the `TXT()` record in a [`D()`](../top-level-functions/D.md) as usual, along - * with the `DnsProvider()` for that provider. Run `dnscontrol check` to - * see if any errors are produced. The check command does not talk to - * the provider's API, thus permitting you to do this without having an - * account at that provider. + * Include the `TXT()` record in a [`D()`](../top-level-functions/D.md) as usual, along with the `DnsProvider()` for that provider. Run `dnscontrol check` to see if any errors are produced. The check command does not talk to the provider's API, thus permitting you to do this without having an account at that provider. * * #### What if the provider rejects a string that is supported? * - * Suppose I can create the TXT record using the DSP's web portal but - * DNSControl rejects the string? - * - * It is possible that the provider code in DNSControl rejects strings - * that the DSP accepts. This is because the test is done in code, not - * by querying the provider's API. It is possible that the code was - * written to work around a bug (such as rejecting a string with a - * back-tick) but now that bug has been fixed. - * - * All such checks are in `providers/${providername}/auditrecords.go`. - * You can try removing the check that you feel is in error and see if - * the provider's API accepts the record. You can do this by running the - * integration tests, or by simply adding that record to an existing - * `dnsconfig.js` and seeing if `dnscontrol push` is able to push that - * record into production. (Be careful if you are testing this on a - * domain used in production.) + * Suppose I can create the TXT record using the DSP's web portal but DNSControl rejects the string? + * + * It is possible that the provider code in DNSControl rejects strings that the DSP accepts. This is because the test is done in code, not by querying the provider's API. It is possible that the code was written to work around a bug (such as rejecting a string with a back-tick) but now that bug has been fixed. + * + * All such checks are in `providers/${providername}/auditrecords.go`. You can try removing the check that you feel is in error and see if the provider's API accepts the record. You can do this by running the integration tests, or by simply adding that record to an existing `dnsconfig.js` and seeing if `dnscontrol push` is able to push that record into production. (Be careful if you are testing this on a domain used in production.) * * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/txt */ diff --git a/documentation/advanced-features/adding-new-rtypes-v2.md b/documentation/advanced-features/adding-new-rtypes-v2.md index fd82773b9f..9092adffd2 100644 --- a/documentation/advanced-features/adding-new-rtypes-v2.md +++ b/documentation/advanced-features/adding-new-rtypes-v2.md @@ -1,16 +1,8 @@ # Creating new DNS Resource Types (rtypes) (v4.28 and later) -Everyone is familiar with A, AAAA, CNAME, NS and other Rtypes. -However there are new record types being added all the time. -Each new record type requires special handling by -DNSControl. - -Version v4.28.0 greatly simplified how to add new record types. As -a demonstration of this new method it added the "RP" type and -ported the existing "CLOUDFLAREAPI_SINGLE_REDIRECT" type. All -other records still use the old method. The old and new -methods co-exist, though eventually we hope to migrate -everything to the new method. +Everyone is familiar with A, AAAA, CNAME, NS and other Rtypes. However there are new record types being added all the time. Each new record type requires special handling by DNSControl. + +Version v4.28.0 greatly simplified how to add new record types. As a demonstration of this new method it added the "RP" type and ported the existing "CLOUDFLAREAPI_SINGLE_REDIRECT" type. All other records still use the old method. The old and new methods co-exist, though eventually we hope to migrate everything to the new method. # What's new? @@ -32,8 +24,7 @@ everything to the new method. # Overview -There are two parts to adding a new Record Type (rtype). First we activate it in the parser for dnsconfig.js. Then we update -any provider to be aware of the rtype. +There are two parts to adding a new Record Type (rtype). First we activate it in the parser for dnsconfig.js. Then we update any provider to be aware of the rtype. Activate it in dnsconfig.js: @@ -45,7 +36,6 @@ Update providers to be aware of the rtype: 1. Update the toRC() function (whatever it may be called). 1. Update the toNative() and any create/delete/change functions. - # Updating the parser In these examples, the new type will be called `THING` (or `thing`). @@ -58,9 +48,7 @@ At the end of the file, add a single line named after the record type. var RP = rawrecordBuilder('RP'); ``` -In this example, the first `RP` is the name of the function that users will -type in dnsconfig.js. For example, `A("label", "10.2.3.4"),` (though the "A" -record type hasn't been ported to the new system yet). +In this example, the first `RP` is the name of the function that users will type in dnsconfig.js. For example, `A("label", "10.2.3.4"),` (though the "A" record type hasn't been ported to the new system yet). Step 2: Create the parser @@ -103,8 +91,7 @@ type THING struct { Step 2c: Create Name() -Create a function `Name()` that outputs the -name of the type. +Create a function `Name()` that outputs the name of the type. ``` func (handle *THING) Name() string { @@ -114,14 +101,12 @@ func (handle *THING) Name() string { Step 2d: Create FromArgs -The "FromArgs" function receives an array of `any` which can contain any type. The "PaveArgs" function -will convert them to the types you need. For example, it will convert numbers to strings, or strings to numbers. +The "FromArgs" function receives an array of `any` which can contain any type. The "PaveArgs" function will convert them to the types you need. For example, it will convert numbers to strings, or strings to numbers. * "s": Convert to string * "i": Convert to int16 -`args[0]` is the label. You can skip it as that is already processed for you. (If you want -to modify the label, see cfsingle.go as an example of how to do that.) +`args[0]` is the label. You can skip it as that is already processed for you. (If you want to modify the label, see cfsingle.go as an example of how to do that.) If THING takes 4 parameters (2 ints and 2 strings), you might pave the arguments as follows: @@ -158,24 +143,17 @@ FromStruct does many things: Create the CopyToLegacyFields function -This updates any of the legacy fields. The most important is the .target field, which we -usually store a copy of the .ZonefilePartial. - -When we migrate other rtypes this will populate the legacy RecordConfig fields. For example, when -we migrate `SRV`, this function will populate the `Srv*` fields. Then, eventually, we'll remove -those legacy fields. +This updates any of the legacy fields. The most important is the .target field, which we usually store a copy of the .ZonefilePartial. +When we migrate other rtypes this will populate the legacy RecordConfig fields. For example, when we migrate `SRV`, this function will populate the `Srv*` fields. Then, eventually, we'll remove those legacy fields. TODO: `js/parse_test` ## Add a capability for the record type -You'll need to mark which providers support this record type. The -initial PR should implement this record for the `BIND` provider at -a minimum. `BIND` outputs non-standard rtypes as a comment. +You'll need to mark which providers support this record type. The initial PR should implement this record for the `BIND` provider at a minimum. `BIND` outputs non-standard rtypes as a comment. -- Add the capability to the file `dnscontrol/providers/capabilities.go` (look for `CanUseAlias` and add - it to the end of the list.) +- Add the capability to the file `dnscontrol/providers/capabilities.go` (look for `CanUseAlias` and add it to the end of the list.) - Run stringer to auto-update the file `dnscontrol/providers/capability_string.go` ```shell @@ -229,11 +207,7 @@ popd ``` {% endcode %} -- Add the capability to the list of features that zones are validated - against (i.e. if you want DNSControl to report an error if this - feature is used with a DNS provider that doesn't support it). That's - in the `checkProviderCapabilities` function in - `pkg/normalize/validate.go`. It should look like this: +- Add the capability to the list of features that zones are validated against (i.e. if you want DNSControl to report an error if this feature is used with a DNS provider that doesn't support it). That's in the `checkProviderCapabilities` function in `pkg/normalize/validate.go`. It should look like this: {% code title="pkg/normalize/validate.go" %} ```diff @@ -246,20 +220,12 @@ popd - Mark the `bind` provider as supporting this record type by updating `dnscontrol/providers/bind/bindProvider.go` (look for `providers.CanUse` and you'll see what to do). -DNSControl will warn/error if this new record is used with a -provider that does not support the capability. +DNSControl will warn/error if this new record is used with a provider that does not support the capability. -- Add the capability to the validations in `pkg/normalize/validate.go` - by adding it to `providerCapabilityChecks` -- Some capabilities can't be tested for. If - such testing can't be done, add it to the whitelist in function - `TestCapabilitiesAreFiltered` in - `pkg/normalize/capabilities_test.go` +- Add the capability to the validations in `pkg/normalize/validate.go` by adding it to `providerCapabilityChecks` +- Some capabilities can't be tested for. If such testing can't be done, add it to the whitelist in function `TestCapabilitiesAreFiltered` in `pkg/normalize/capabilities_test.go` -If the capabilities testing is not configured correctly, `go test ./...` -will report something like the `MISSING` message below. In this -example we removed `providers.CanUseCAA` from the -`providerCapabilityChecks` list. +If the capabilities testing is not configured correctly, `go test ./...` will report something like the `MISSING` message below. In this example we removed `providers.CanUseCAA` from the `providerCapabilityChecks` list. ```text --- FAIL: TestCapabilitiesAreFiltered (0.00s) @@ -282,11 +248,7 @@ Add a new Markdown file to `documentation/language-reference/domain-modifiers`. The rest of the file is the documentation. You can use Markdown syntax to format the text. -Add the new file `FOO.md` to the documentation table of contents -`documentation/SUMMARY.md` > `Domain Modifiers`, and/or to the `Service -Provider specific` section if you made a record specific to a provider, and to -the `Record Modifiers` section if you created any `*_BUILDER` or `*_HELPER` or -similar functions for the new record type: +Add the new file `FOO.md` to the documentation table of contents `documentation/SUMMARY.md` > `Domain Modifiers`, and/or to the `Service Provider specific` section if you made a record specific to a provider, and to the `Record Modifiers` section if you created any `*_BUILDER` or `*_HELPER` or similar functions for the new record type: {% code title="documentation/SUMMARY.md" %} ```diff @@ -329,7 +291,6 @@ go generate ./... This will regenerate things like the table of which providers have which features and the `dnscontrol.d.ts` file. - # Update providers When a provider needs to create a THING, they have two choices @@ -346,8 +307,7 @@ If you have the fields in variables that are strings that need to be converted, rec, err := rtypecontrol.NewRecordConfigFromRaw("CF_REDIRECT", ttl, []any{pattern, target}, dc) ``` -There's a good chance you know the zoneName but don't have a complete models.DomainConfig(). That's ok. -As long as you know the zone name, we can fake it: (this is a hack we'll figure out how to eliminate eventually). +There's a good chance you know the zoneName but don't have a complete models.DomainConfig(). That's ok. As long as you know the zone name, we can fake it: (this is a hack we'll figure out how to eliminate eventually). ``` dc := models.MakeFakeDomainConfig(zoneName) diff --git a/documentation/advanced-features/adding-new-rtypes.md b/documentation/advanced-features/adding-new-rtypes.md index 7940152ad4..a0ef8d8111 100644 --- a/documentation/advanced-features/adding-new-rtypes.md +++ b/documentation/advanced-features/adding-new-rtypes.md @@ -1,14 +1,8 @@ # Creating new DNS Resource Types (rtypes) -Everyone is familiar with A, AAAA, CNAME, NS and other Rtypes. -However there are new record types being added all the time. -Each new record type requires special handling by -DNSControl. +Everyone is familiar with A, AAAA, CNAME, NS and other Rtypes. However there are new record types being added all the time. Each new record type requires special handling by DNSControl. -If a record simply has a single "target", then there is little to -do because it is handled similarly to A, CNAME, and so on. However -if there are multiple fields within the record you have more work -to do. +If a record simply has a single "target", then there is little to do because it is handled similarly to A, CNAME, and so on. However if there are multiple fields within the record you have more work to do. Our general philosophy is: @@ -22,11 +16,7 @@ go tool stringer ``` ## Step 1: Update `RecordConfig` in `models/record.go` -If the record has any unique fields, add them to `RecordConfig`. -The field name should be the record type, then the field name as -used in `github.com/miekg/dns/types.go`. For example, the `CAA` -record has a field called `Flag`, therefore the field name in -`RecordConfig` is CaaFlag (not `CaaFlags` or `CAAFlags`). +If the record has any unique fields, add them to `RecordConfig`. The field name should be the record type, then the field name as used in `github.com/miekg/dns/types.go`. For example, the `CAA` record has a field called `Flag`, therefore the field name in `RecordConfig` is CaaFlag (not `CaaFlags` or `CAAFlags`). Here are some examples: @@ -43,18 +33,13 @@ type RecordConfig struct { } ``` -It is important to leave the `omitempty` flag present so that tests for -other record types do not start to fail because your new record types insist on -being present. +It is important to leave the `omitempty` flag present so that tests for other record types do not start to fail because your new record types insist on being present. ## Step 2: Add a capability for the record -You'll need to mark which providers support this record type. The -initial PR should implement this record for the `bind` provider at -a minimum. +You'll need to mark which providers support this record type. The initial PR should implement this record for the `bind` provider at a minimum. -- Add the capability to the file `dnscontrol/providers/capabilities.go` (look for `CanUseAlias` and add - it to the end of the list.) +- Add the capability to the file `dnscontrol/providers/capabilities.go` (look for `CanUseAlias` and add it to the end of the list.) - Run stringer to auto-update the file `dnscontrol/providers/capability_string.go` ```shell @@ -108,11 +93,7 @@ popd ``` {% endcode %} -- Add the capability to the list of features that zones are validated - against (i.e. if you want DNSControl to report an error if this - feature is used with a DNS provider that doesn't support it). That's - in the `checkProviderCapabilities` function in - `pkg/normalize/validate.go`. It should look like this: +- Add the capability to the list of features that zones are validated against (i.e. if you want DNSControl to report an error if this feature is used with a DNS provider that doesn't support it). That's in the `checkProviderCapabilities` function in `pkg/normalize/validate.go`. It should look like this: {% code title="pkg/normalize/validate.go" %} ```diff @@ -125,20 +106,12 @@ popd - Mark the `bind` provider as supporting this record type by updating `dnscontrol/providers/bind/bindProvider.go` (look for `providers.CanUse` and you'll see what to do). -DNSControl will warn/error if this new record is used with a -provider that does not support the capability. +DNSControl will warn/error if this new record is used with a provider that does not support the capability. -- Add the capability to the validations in `pkg/normalize/validate.go` - by adding it to `providerCapabilityChecks` -- Some capabilities can't be tested for. If - such testing can't be done, add it to the whitelist in function - `TestCapabilitiesAreFiltered` in - `pkg/normalize/capabilities_test.go` +- Add the capability to the validations in `pkg/normalize/validate.go` by adding it to `providerCapabilityChecks` +- Some capabilities can't be tested for. If such testing can't be done, add it to the whitelist in function `TestCapabilitiesAreFiltered` in `pkg/normalize/capabilities_test.go` -If the capabilities testing is not configured correctly, `go test ./...` -will report something like the `MISSING` message below. In this -example we removed `providers.CanUseCAA` from the -`providerCapabilityChecks` list. +If the capabilities testing is not configured correctly, `go test ./...` will report something like the `MISSING` message below. In this example we removed `providers.CanUseCAA` from the `providerCapabilityChecks` list. ```text --- FAIL: TestCapabilitiesAreFiltered (0.00s) @@ -149,14 +122,9 @@ example we removed `providers.CanUseCAA` from the ## Step 3: Add a helper function -Add a function to `pkg/js/helpers.js` for the new record type. This -is the JavaScript file that defines `dnsconfig.js`'s functions like -[`A()`](../language-reference/domain-modifiers/A.md) and [`MX()`](../language-reference/domain-modifiers/MX.md). Look at the definition of `A`, `MX` and `CAA` for good -examples to use as a base. +Add a function to `pkg/js/helpers.js` for the new record type. This is the JavaScript file that defines `dnsconfig.js`'s functions like [`A()`](../language-reference/domain-modifiers/A.md) and [`MX()`](../language-reference/domain-modifiers/MX.md). Look at the definition of `A`, `MX` and `CAA` for good examples to use as a base. -Please add the function alphabetically with the others. Also, please run -[prettier](https://github.com/prettier/prettier) on the file to ensure -your code conforms to our coding standard: +Please add the function alphabetically with the others. Also, please run [prettier](https://github.com/prettier/prettier) on the file to ensure your code conforms to our coding standard: ```shell npm install prettier @@ -165,15 +133,11 @@ node_modules/.bin/prettier --write pkg/js/helpers.js ## Step 4: Search for `#rtype_variations` -Anywhere a `rtype` requires special handling has been marked with a -comment that includes the string `#rtype_variations`. Search for -this string and add your new type to this code. +Anywhere a `rtype` requires special handling has been marked with a comment that includes the string `#rtype_variations`. Search for this string and add your new type to this code. ## Step 5: Add a `parse_tests` test case -Add at least one test case to the `pkg/js/parse_tests` directory. -Test `013-mx.js` is a very simple one and is good for cloning. -See also `017-txt.js`. +Add at least one test case to the `pkg/js/parse_tests` directory. Test `013-mx.js` is a very simple one and is good for cloning. See also `017-txt.js`. Run these tests via: @@ -183,22 +147,15 @@ go test ./... popd ``` -If this works, then you know the `dnsconfig.js` and `helpers.js` -code is working correctly. +If this works, then you know the `dnsconfig.js` and `helpers.js` code is working correctly. -As you debug, if there are places that haven't been marked -`#rtype_variations` that should be, add such a comment. -Every time you do this, an angel gets its wings. +As you debug, if there are places that haven't been marked `#rtype_variations` that should be, add such a comment. Every time you do this, an angel gets its wings. -The tests also verify that for every "capability" there is a -validation. This is explained in Step 2 (search for -`TestCapabilitiesAreFiltered` or `MISSING`) +The tests also verify that for every "capability" there is a validation. This is explained in Step 2 (search for `TestCapabilitiesAreFiltered` or `MISSING`) ## Step 6: Add an `integrationTest` test case -Add at least one test case to the `integrationTest/integration_test.go` -file. Look for `func makeTests` and add the test to the end of this -list. +Add at least one test case to the `integrationTest/integration_test.go` file. Look for `func makeTests` and add the test to the end of this list. Each `testgroup()` is a named list of tests. @@ -215,38 +172,17 @@ testgroup("MX", ``` {% endcode %} -Line 1: `testgroup()` gives a name to a group of tests. It also tells -the system to delete all records for this domain so that the tests -begin with a blank slate. - -Line 2: -Each `tc()` encodes all the records of a zone. The test framework -will try to do the smallest changes to bring the zone up to date. -In this case, we know the zone is empty, so this will add one MX -record. - -Line 3: In this example, we just change one field of an existing -record. To get to this configuration, the provider will have to -either change the priority on an existing record, or delete the old -record and insert a new one. Either way, this test case assures us -that the diff'ing functionality is working properly. - -If you look at the tests for `CAA`, it inserts a few records then -attempts to modify each field of a record one at a time. This test -was useful because it turns out we hadn't written the code to -properly see a change in priority. We fixed this bug before the -code made it into production. - -Line 4: In this example, the next zone adds a second MX record. -To get to this configuration, the provider will add an -additional MX record to the same label. New tests don't need to do -this kind of test because we're pretty sure that that part of the diffing -engine works fine. It is here as an example. - -Also notice that some tests include `requires()`, `not()` and `only()` -statements. This is how we restrict tests to certain providers. -These options must be listed first in a `testgroup`. More details are -in the source code. +Line 1: `testgroup()` gives a name to a group of tests. It also tells the system to delete all records for this domain so that the tests begin with a blank slate. + +Line 2: Each `tc()` encodes all the records of a zone. The test framework will try to do the smallest changes to bring the zone up to date. In this case, we know the zone is empty, so this will add one MX record. + +Line 3: In this example, we just change one field of an existing record. To get to this configuration, the provider will have to either change the priority on an existing record, or delete the old record and insert a new one. Either way, this test case assures us that the diff'ing functionality is working properly. + +If you look at the tests for `CAA`, it inserts a few records then attempts to modify each field of a record one at a time. This test was useful because it turns out we hadn't written the code to properly see a change in priority. We fixed this bug before the code made it into production. + +Line 4: In this example, the next zone adds a second MX record. To get to this configuration, the provider will add an additional MX record to the same label. New tests don't need to do this kind of test because we're pretty sure that that part of the diffing engine works fine. It is here as an example. + +Also notice that some tests include `requires()`, `not()` and `only()` statements. This is how we restrict tests to certain providers. These options must be listed first in a `testgroup`. More details are in the source code. To run the integration test with the BIND provider: @@ -256,18 +192,13 @@ go test -v -verbose -profile BIND popd ``` -Once the code works for BIND, consider submitting a PR at this point. -(The earlier you submit a PR, the earlier we can provide feedback.) +Once the code works for BIND, consider submitting a PR at this point. (The earlier you submit a PR, the earlier we can provide feedback.) -If you find places that haven't been marked -`#rtype_variations` but should be, please add that comment. -Every time you fail to do this, God kills a cute little kitten. -Please do it for the kittens. +If you find places that haven't been marked `#rtype_variations` but should be, please add that comment. Every time you fail to do this, God kills a cute little kitten. Please do it for the kittens. ## Step 7: Support more providers -Now add support in other providers. Add the `providers.CanUse...` -flag to the provider and re-run the integration tests: +Now add support in other providers. Add the `providers.CanUse...` flag to the provider and re-run the integration tests: For example, this will run the tests on Amazon AWS Route53: @@ -280,16 +211,9 @@ go test -v -verbose -profile ROUTE53 popd ``` -The test should reveal any bugs. Keep iterating between fixing the -code and running the tests. When the tests all work, you are done. -(Well, you might want to clean up some code a bit, but at least you -know that everything is working.) +The test should reveal any bugs. Keep iterating between fixing the code and running the tests. When the tests all work, you are done. (Well, you might want to clean up some code a bit, but at least you know that everything is working.) -If you find bugs that aren't covered by the tests, please please -please add a test that demonstrates the bug (then fix the bug, of -course). This -will help all future contributors. If you need help with adding -tests, please ask! +If you find bugs that aren't covered by the tests, please please please add a test that demonstrates the bug (then fix the bug, of course). This will help all future contributors. If you need help with adding tests, please ask! ## Step 8: Write documentation diff --git a/documentation/advanced-features/byo-secrets.md b/documentation/advanced-features/byo-secrets.md index 5d5c748436..282e2bd45e 100644 --- a/documentation/advanced-features/byo-secrets.md +++ b/documentation/advanced-features/byo-secrets.md @@ -1,8 +1,6 @@ # Bring-Your-Own-Secrets for automated testing -Goal: Enable automated integration testing without accidentally -leaking credentials (API keys and other secrets); at the same time permit everyone -to automate their own tests without having to share their credentials. +Goal: Enable automated integration testing without accidentally leaking credentials (API keys and other secrets); at the same time permit everyone to automate their own tests without having to share their credentials. The instructions in this document will enable automated tests to run in these situations: @@ -15,38 +13,19 @@ The instructions in this document will enable automated tests to run in these si # Background: How GitHub Actions protects secrets -GitHub Actions has a secure -[secrets storage system](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets). -Those secrets are available to GitHub Actions and are required for the -integration tests to communicate with the various DNS providers that -DNSControl supports. +GitHub Actions has a secure [secrets storage system](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets). Those secrets are available to GitHub Actions and are required for the integration tests to communicate with the various DNS providers that DNSControl supports. -For security reasons, those secrets are unavailable if the PR comes -from outside the project (a forked repo). This is a good thing. If -it didn't work that way, a third-party could write a PR that leaks the -secrets without the owners of the project knowing. +For security reasons, those secrets are unavailable if the PR comes from outside the project (a forked repo). This is a good thing. If it didn't work that way, a third-party could write a PR that leaks the secrets without the owners of the project knowing. -The docs (and many blog posts) describe this as forked repos don't -have access to secrets, and instead receive null strings. That's not -actually what's happening. +The docs (and many blog posts) describe this as forked repos don't have access to secrets, and instead receive null strings. That's not actually what's happening. -Actually what happens is the secrets come from the forked repo. Or, -more precisely, the secrets offered to a PR come from the repo that the -PR came from. A PR from DNSControl's owners gets secrets from -[github.com/DNSControl/dnscontrol's secret store](https://github.com/DNSControl/dnscontrol/settings/secrets/actions) -but a PR from a fork, such as -[https://github.com/TomOnTime/dnscontrol](https://github.com/TomOnTime/dnscontrol) -gets its secrets from TomOnTime's secrets. +Actually what happens is the secrets come from the forked repo. Or, more precisely, the secrets offered to a PR come from the repo that the PR came from. A PR from DNSControl's owners gets secrets from [github.com/DNSControl/dnscontrol's secret store](https://github.com/DNSControl/dnscontrol/settings/secrets/actions) but a PR from a fork, such as [https://github.com/TomOnTime/dnscontrol](https://github.com/TomOnTime/dnscontrol) gets its secrets from TomOnTime's secrets. -Our automated integration tests leverages this info to have tests -only run if they have access to the secrets they will need. +Our automated integration tests leverages this info to have tests only run if they have access to the secrets they will need. # Which providers are selected for testing? -Tests are executed if the env variable`*_DOMAIN` exists where `*` is the name of the provider. If the value is empty or -unset, the test is skipped. -For example, if a provider is called `FANCYDNS`, there must -be a variable called `FANCYDNS_DOMAIN`. +Tests are executed if the env variable`*_DOMAIN` exists where `*` is the name of the provider. If the value is empty or unset, the test is skipped. For example, if a provider is called `FANCYDNS`, there must be a variable called `FANCYDNS_DOMAIN`. # Bring your own secrets @@ -139,23 +118,13 @@ The tests will fail if a secret is wrong or missing. It may take a few iteratio # Donate secrets to the project -The DNSControl project would like to have all providers automatically tested. -However, we can't fund purchasing domains or maintaining credentials at every -provider. Instead we depend on volunteers to maintain (and pay for) such -accounts. +The DNSControl project would like to have all providers automatically tested. However, we can't fund purchasing domains or maintaining credentials at every provider. Instead we depend on volunteers to maintain (and pay for) such accounts. -We recommend the domain be named `dnscontroltest-PROVIDER.com` (or similar) -where PROVIDER is replaced by the name of your provider or an abbreviation. For -example `dnscontroltest-r53.com` and `dnscontroltest-gcloud.com`. +We recommend the domain be named `dnscontroltest-PROVIDER.com` (or similar) where PROVIDER is replaced by the name of your provider or an abbreviation. For example `dnscontroltest-r53.com` and `dnscontroltest-gcloud.com`. -When possible, use an OTE or free domain. Don't spend money if you don't have -to. This isn't just to be thrifty! It avoids renewals and other hassles too. -You'd be surprised at how many providers (such as Google and Azure) permit DNS -zones to be created in your account without registering them. +When possible, use an OTE or free domain. Don't spend money if you don't have to. This isn't just to be thrifty! It avoids renewals and other hassles too. You'd be surprised at how many providers (such as Google and Azure) permit DNS zones to be created in your account without registering them. -For actual DNS domains, please select the "private registration" option if it -is available. Otherwise you will get spam phones calls and emails. The phone -calls will make you wish you didn't own a phone. +For actual DNS domains, please select the "private registration" option if it is available. Otherwise you will get spam phones calls and emails. The phone calls will make you wish you didn't own a phone. {% hint style="danger" %} Some rules: diff --git a/documentation/advanced-features/cli-variables.md b/documentation/advanced-features/cli-variables.md index c04f4e836d..319ed04acc 100644 --- a/documentation/advanced-features/cli-variables.md +++ b/documentation/advanced-features/cli-variables.md @@ -24,7 +24,6 @@ CLI_DEFAULTS({ ``` {% endcode %} - You need to define this defaults just once in your `dnsconfig.js`. It should be defined **before** using it. _Please keep in mind that accessing an undefined variable is an error. If it is not set on the command line nor in `CLI_DEFAULTS`, accessing the variable will fail._ @@ -65,11 +64,9 @@ D("example.com", REG_NAMECOM, DnsProvider(DNS_NAMECOM), DnsProvider(DNS_BIND), ``` {% endcode %} - ## Example 2: Different DNS records -In this example different code is run when `emergency=true`. Normally -`server12` is an A record but in an emergency it is a CNAME. +In this example different code is run when `emergency=true`. Normally `server12` is an A record but in an emergency it is a CNAME. In this configuration: @@ -111,31 +108,15 @@ if (emergency) { ``` {% endcode %} - ### ProTips -The cli variables functionality permits you to create very complex and -sophisticated configurations, but you shouldn't. Be nice to the next person -that edits the file, who may not be as expert as yourself. - -While there is no limit to the number of variables that can be set on the -command line, doing so is annoying to the person using the tool. It is better -to set one variables which specifies a "mode". This mode is then used to -automatically set other variables. This way the user can determine the mode and -the code can determine what to do in that mode. This is less error-prone and -more testable. - -In the first example, you'll see that one variable is used to set a mode which -then determines many other variables. This is done in one place, at the top of -the file. Everything related to this is isolated to one place, thus easier to -maintain. The rest of the file simply uses those variables. - -In the second example, you'll see a boolean variable is set which selects which -code will run different code. While the conditional code is not isolated to the -top of the file, the conditional code is placed immediately after the domain. - -In both examples, not setting any variables on the command line does something -reasonable. If someone accidentally runs `dnscontrol push` without any -variables, the behavior is correct (assuming we're not in emergency mode, which -is unlikely). +The cli variables functionality permits you to create very complex and sophisticated configurations, but you shouldn't. Be nice to the next person that edits the file, who may not be as expert as yourself. + +While there is no limit to the number of variables that can be set on the command line, doing so is annoying to the person using the tool. It is better to set one variables which specifies a "mode". This mode is then used to automatically set other variables. This way the user can determine the mode and the code can determine what to do in that mode. This is less error-prone and more testable. + +In the first example, you'll see that one variable is used to set a mode which then determines many other variables. This is done in one place, at the top of the file. Everything related to this is isolated to one place, thus easier to maintain. The rest of the file simply uses those variables. + +In the second example, you'll see a boolean variable is set which selects which code will run different code. While the conditional code is not isolated to the top of the file, the conditional code is placed immediately after the domain. + +In both examples, not setting any variables on the command line does something reasonable. If someone accidentally runs `dnscontrol push` without any variables, the behavior is correct (assuming we're not in emergency mode, which is unlikely). diff --git a/documentation/advanced-features/code-tricks.md b/documentation/advanced-features/code-tricks.md index 09fc725f09..ac459bc58f 100644 --- a/documentation/advanced-features/code-tricks.md +++ b/documentation/advanced-features/code-tricks.md @@ -22,8 +22,7 @@ END); ``` {% endcode %} -As of [DNSControl v4.15.0](https://github.com/DNSControl/dnscontrol/releases/tag/v4.15.0), the `END` statements are no longer necessary. -These were originally included for historical reasons that are now irrelevant. You can safely remove them from your configurations. +As of [DNSControl v4.15.0](https://github.com/DNSControl/dnscontrol/releases/tag/v4.15.0), the `END` statements are no longer necessary. These were originally included for historical reasons that are now irrelevant. You can safely remove them from your configurations. # Repeat records in many domains (macros) @@ -33,9 +32,7 @@ Solution: Assign a list to a var and use the var in each domain. Example: -Domains that use Google G-Suite require a specific list of MX -records, plus there are some CNAMEs that are useful (but we only -want the CNAMEs on a subset of domains). +Domains that use Google G-Suite require a specific list of MX records, plus there are some CNAMEs that are useful (but we only want the CNAMEs on a subset of domains). {% code title="dnsconfig.js" %} ```javascript @@ -71,11 +68,9 @@ D("aliasdomain.tld", REG_NAMECOM, DnsProvider(DSP_MY_PROVIDER), ``` {% endcode %} - # Many domains with the exact same records -Problem: We have many domains, each should have the exact same -records. +Problem: We have many domains, each should have the exact same records. Solution 1: Use a macro. @@ -116,62 +111,34 @@ _.each( # Caveats about getting too fancy -The `dnsconfig.js` language is JavaScript. On the plus side, this means -you can use loops and variables and anything else you want. +The `dnsconfig.js` language is JavaScript. On the plus side, this means you can use loops and variables and anything else you want. However, we don't recommend you get too fancy. *A new JS interpreter may break your code* -Some day we may change from the -[Otto JS interpreter](https://github.com/robertkrimen/otto) to -something else. This may break your configuration if you depend on -unusual or obscure behavior of Otto. +Some day we may change from the [Otto JS interpreter](https://github.com/robertkrimen/otto) to something else. This may break your configuration if you depend on unusual or obscure behavior of Otto. Loops and macros are fine. Just don't get too fancy. *Complexity is a killer* -As Brian Kernighan wrote, "Debugging is twice as hard as writing the -code in the first place. Therefore, if you write the code as cleverly -as possible, you are, by definition, not smart enough to debug it." +As Brian Kernighan wrote, "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." -Sure, you can do a lot of neat tricks with `if/then`s and macros and -loops. Yes, YOU understand the code. However, think about your -coworkers who will be the *next* person to edit the file. Are you -setting them up for failure? +Sure, you can do a lot of neat tricks with `if/then`s and macros and loops. Yes, YOU understand the code. However, think about your coworkers who will be the *next* person to edit the file. Are you setting them up for failure? -And what about You Six Months From Now (YSMFN)? Have you met YSMFN? -They're a great person. You'll meet them soon. In about 6 months, I -predict. That person is a lot like you, but definitely won't remember -how all those clever tricks work. That person also might be tired, -sleepy, and possibly drunk. You really want to keep the configuration -file simple for YSMFN. +And what about You Six Months From Now (YSMFN)? Have you met YSMFN? They're a great person. You'll meet them soon. In about 6 months, I predict. That person is a lot like you, but definitely won't remember how all those clever tricks work. That person also might be tired, sleepy, and possibly drunk. You really want to keep the configuration file simple for YSMFN. -The goal of DNSControl is to empower non-experts to safely make DNS -changes. A DNS expert should create the initial configuration, but -your non-expert coworkers should be able to send PR and make changes -without too much hand-holding. Complexity prevents that. +The goal of DNSControl is to empower non-experts to safely make DNS changes. A DNS expert should create the initial configuration, but your non-expert coworkers should be able to send PR and make changes without too much hand-holding. Complexity prevents that. *What to do instead?* Isolate the clever stuff from what a typical user will need to edit. -For example, Stack Overflow, puts all macro definitions and fancy stuff at -the top of the file. The domains are later in the file. +For example, Stack Overflow, puts all macro definitions and fancy stuff at the top of the file. The domains are later in the file. -We name the macros to be easy to understand for the user. For -example, we have a few macros named `SPF_NONE`, `SPF_GSUITE`, and -`SPF_domain_tld` (where `domain_tld` is the name of a domain). I bet -you can guess which to use for a new domain without seeing the -definition. +We name the macros to be easy to understand for the user. For example, we have a few macros named `SPF_NONE`, `SPF_GSUITE`, and `SPF_domain_tld` (where `domain_tld` is the name of a domain). I bet you can guess which to use for a new domain without seeing the definition. -We also comment extensively. Most records have a comment at the end -of the line with the ticket number of the request related to the -record. Before each domain there is a long comment explaining why the -domain exists, who requested it, any associated ticket numbers, and so -on. +We also comment extensively. Most records have a comment at the end of the line with the ticket number of the request related to the record. Before each domain there is a long comment explaining why the domain exists, who requested it, any associated ticket numbers, and so on. -We also comment the individual parts of a record. Look at the [SPF -Optimizer](../language-reference/domain-modifiers/SPF_BUILDER.md) example. Each part of -the SPF record has a comment. +We also comment the individual parts of a record. Look at the [SPF Optimizer](../language-reference/domain-modifiers/SPF_BUILDER.md) example. Each part of the SPF record has a comment. diff --git a/documentation/advanced-features/concurrency-verified.md b/documentation/advanced-features/concurrency-verified.md index cc52ec014f..10110b64d1 100644 --- a/documentation/advanced-features/concurrency-verified.md +++ b/documentation/advanced-features/concurrency-verified.md @@ -6,8 +6,7 @@ name: CONCURRENCY_VERIFIED ❔ - The questionmark means "it hasn't been tested, safety unknown" ❌ - The red "X" means "this has been tested, and it will _not_ work concurrently". -Concurrency in this context is about gathering zone data, as seen during the -preview stage when fetching current data for all zones. +Concurrency in this context is about gathering zone data, as seen during the preview stage when fetching current data for all zones. ### Here's how to perform a test: @@ -15,41 +14,23 @@ preview stage when fetching current data for all zones. 2. Run this special binary: `dnscontrol preview` with a configuration that lists at least 4 domains using the provider in question. More domains is better. 3. The special binary runs much slower (1/10th the speed) because it is doing a lot of checking. -If it reports problems, the error message will indicate where the problem is. -It might not be 100% accurate, but it will be in the right area. +If it reports problems, the error message will indicate where the problem is. It might not be 100% accurate, but it will be in the right area. ### Development guidance -Loosely, each Provider has a top-level struct named `{providername}Provider`; -if this state is just some simple data-types initialized once before -processing starts, and then only read, then the provider is likely to be -concurrency-safe. +Loosely, each Provider has a top-level struct named `{providername}Provider`; if this state is just some simple data-types initialized once before processing starts, and then only read, then the provider is likely to be concurrency-safe. -If this contains state which is updated (eg, caches) then the provider is -probably not concurrency-safe unless every routine accessing it is protected -by appropriate primitives. +If this contains state which is updated (eg, caches) then the provider is probably not concurrency-safe unless every routine accessing it is protected by appropriate primitives. -Eg, URLs and auth credentials are fine. -An account ID determined on the first query? -That probably needs to be protected, even if every fetch returns the same data. +Eg, URLs and auth credentials are fine. An account ID determined on the first query? That probably needs to be protected, even if every fetch returns the same data. The `-race` build is a helpful hint but is not a guarantee. #### Multiple Providers -Most simple use-cases likely use just one copy of a given provider, managing -zones in an account. But there can be multiple _distinct_ copies, each for -different accounts. Someone might use this while migrating accounts, for -instance. You might have two fields in `creds.json` both with a `TYPE` of -your provider. - -The uses of the provider objects should never create copies; each is created -by a constructor, but thereafter is a singleton per constructed provider. -Thus it is safe to have synchronization objects inside the provider struct. - -See, for example, the `dnsimple` provider, where there is a `sync.Once` _per -object_, not at a global level, so that the `.accountID` can be fetched just -once per configured provider. Because `sync.Once` contains a reference to -`sync.noCopy`, the `go vet` command will catch attempts to copy that object, -and so will catch attempts to copy the containing `dnsimpleProvider` object. +Most simple use-cases likely use just one copy of a given provider, managing zones in an account. But there can be multiple _distinct_ copies, each for different accounts. Someone might use this while migrating accounts, for instance. You might have two fields in `creds.json` both with a `TYPE` of your provider. + +The uses of the provider objects should never create copies; each is created by a constructor, but thereafter is a singleton per constructed provider. Thus it is safe to have synchronization objects inside the provider struct. + +See, for example, the `dnsimple` provider, where there is a `sync.Once` _per object_, not at a global level, so that the `.accountID` can be fetched just once per configured provider. Because `sync.Once` contains a reference to `sync.noCopy`, the `go vet` command will catch attempts to copy that object, and so will catch attempts to copy the containing `dnsimpleProvider` object. diff --git a/documentation/advanced-features/dual-host.md b/documentation/advanced-features/dual-host.md index 74d1a0e3e3..2ce834b16b 100644 --- a/documentation/advanced-features/dual-host.md +++ b/documentation/advanced-features/dual-host.md @@ -1,16 +1,13 @@ # Dual Host -The dual hosting feature of DNSControl provides -for the ability to use multiple DNS providers simultaneously. -Consult your provider docs to ensure that **both** of them support this feature. +The dual hosting feature of DNSControl provides for the ability to use multiple DNS providers simultaneously. Consult your provider docs to ensure that **both** of them support this feature. -✅ - A checkmark means "this has been tested, and the provider works with dual hosting". -❔ - The questionmark means "it hasn't been tested, safety unknown" -❌ - The red "X" means "this has been tested, and it does _not_ work currently". +✅ - A checkmark means "this has been tested, and the provider works with dual hosting". +❔ - The questionmark means "it hasn't been tested, safety unknown" +❌ - The red "X" means "this has been tested, and it does _not_ work currently". ## Source reference -[The source](https://github.com/DNSControl/dnscontrol/blob/cdbd54016f93140548d846842b0d7575603069c8/providers/capabilities.go#L93) -states that this flag +[The source](https://github.com/DNSControl/dnscontrol/blob/cdbd54016f93140548d846842b0d7575603069c8/providers/capabilities.go#L93) states that this flag > provider allows full management of apex NS records, so we can safely dual-host with another provider diff --git a/documentation/advanced-features/integration-tests.md b/documentation/advanced-features/integration-tests.md index cbbebf7c1c..43fa91bdb6 100644 --- a/documentation/advanced-features/integration-tests.md +++ b/documentation/advanced-features/integration-tests.md @@ -57,11 +57,7 @@ go test -timeout 0 -v -verbose -profile CLOUDNS FYI: The order of the flags matters. Flags native to the Go testing suite (`-timeout` and `-v`) must come before flags that are part of the DNSControl integration tests (`-verbose`, `-profile`). Yeah, that sucks and is confusing. -The actual tests are in the file `integrationTest/integration_test.go`. The -tests are in a little language which can be used to describe just about any -interaction with the API. Look for the comment `START HERE` or the line -`func makeTests` for instructions. - +The actual tests are in the file `integrationTest/integration_test.go`. The tests are in a little language which can be used to describe just about any interaction with the API. Look for the comment `START HERE` or the line `func makeTests` for instructions. {% hint style="warning" %} **WARNING**: THE RECORDS IN THE TEST DOMAIN WILL BE DELETED. Only use diff --git a/documentation/advanced-features/json-reports.md b/documentation/advanced-features/json-reports.md index 25b87a8733..a3116cd06c 100644 --- a/documentation/advanced-features/json-reports.md +++ b/documentation/advanced-features/json-reports.md @@ -2,15 +2,11 @@ DNSControl can generate a machine-parseable report of changes. -The report is JSON-formatted and contains the zonename, the provider or -registrar name, the number of changes (corrections), and the correction details. -All values are in text, values may contain `<`,`>` and `&` escape as needed. +The report is JSON-formatted and contains the zonename, the provider or registrar name, the number of changes (corrections), and the correction details. All values are in text, values may contain `<`,`>` and `&` escape as needed. -To generate the report, add the `--report ` option to a `preview` or -`push` command. +To generate the report, add the `--report ` option to a `preview` or `push` command. -The report lists the changes that would be (preview) or are (push) attempted, -whether they are successful or not. +The report lists the changes that would be (preview) or are (push) attempted, whether they are successful or not. If a fatal error happens during the run, no report is generated. diff --git a/documentation/advanced-features/nameservers.md b/documentation/advanced-features/nameservers.md index ebca13250e..299217361d 100644 --- a/documentation/advanced-features/nameservers.md +++ b/documentation/advanced-features/nameservers.md @@ -1,8 +1,6 @@ # Nameservers and Delegations -DNSControl can handle a variety of provider scenarios. The registrar and DNS -provider can be the same company, different company, they can even be unknown! -The document shows examples of many common and uncommon configurations. +DNSControl can handle a variety of provider scenarios. The registrar and DNS provider can be the same company, different company, they can even be unknown! The document shows examples of many common and uncommon configurations. # Constants @@ -30,16 +28,13 @@ var DNS_BIND = NewDnsProvider("bind"); ``` {% endcode %} - # Typical Delegations ## Same provider for REG and DNS -Purpose: -Use the same provider as a registrar and DNS service. +Purpose: Use the same provider as a registrar and DNS service. -Why? -Simplicity. +Why? Simplicity. {% code title="dnsconfig.js" %} ```javascript @@ -50,15 +45,11 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - ## Different provider for REG and DNS -Purpose: -Use one provider as registrar, a different for DNS service. +Purpose: Use one provider as registrar, a different for DNS service. -Why? -Some registrars do not provide DNS server, or their service is sub-standard and -you want to use a high-performance DNS server. +Why? Some registrars do not provide DNS server, or their service is sub-standard and you want to use a high-performance DNS server. {% code title="dnsconfig.js" %} ```javascript @@ -71,14 +62,9 @@ D("example.com", REG_NAMECOM, ## Registrar is elsewhere -Purpose: -This is a "DNS only" configuration. Use it when you don't control the -registrar but you do control the DNS records. +Purpose: This is a "DNS only" configuration. Use it when you don't control the registrar but you do control the DNS records. -Why? -You don't have access to the registrar, or the registrar is not -supported by DNSControl. However you do have API access for -updating the zone's records (most likely at a different provider). +Why? You don't have access to the registrar, or the registrar is not supported by DNSControl. However you do have API access for updating the zone's records (most likely at a different provider). {% code title="dnsconfig.js" %} ```javascript @@ -92,10 +78,7 @@ D("example.com", REG_NONE, ## Domain is "nowhere" -Suppose you don't want to manage a domain, but you want to list the zone in -your `dnsconfig.js` file for inventory purposes. For example, suppose there are -domains that some other part of your company maintains, but you want to list it -in your `dnsconfig.js` because it is authoritative for the company. +Suppose you don't want to manage a domain, but you want to list the zone in your `dnsconfig.js` file for inventory purposes. For example, suppose there are domains that some other part of your company maintains, but you want to list it in your `dnsconfig.js` because it is authoritative for the company. ```javascript var REG_NONE = NewRegistrar("none"); @@ -117,13 +100,9 @@ dnscontrol print-ir | jq -r '.domains[].name' ## Zone is elsewhere -Purpose: -This is a "Registrar only" configuration. Use it when you control the registrar but want to delegate the zone to someone else. +Purpose: This is a "Registrar only" configuration. Use it when you control the registrar but want to delegate the zone to someone else. -Why? -We are delegating the domain to someone else. In this example we're -pointing the domain to the nsone.net DNS service, which someone else is -controlling. +Why? We are delegating the domain to someone else. In this example we're pointing the domain to the nsone.net DNS service, which someone else is controlling. {% code title="dnsconfig.js" %} ```javascript @@ -136,17 +115,11 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - ## Override nameservers -Purpose: -Ignore the provider's default nameservers and substitute our own. +Purpose: Ignore the provider's default nameservers and substitute our own. -Why? -Rarely used unless the DNS provider's API does not support querying what the -nameservers are, or the API is returning invalid data, or if the API returns no -information. Sometimes APIs return no (useful) information when the domain -is new; this is a good temporary work-around until the API starts working. +Why? Rarely used unless the DNS provider's API does not support querying what the nameservers are, or the API is returning invalid data, or if the API returns no information. Sometimes APIs return no (useful) information when the domain is new; this is a good temporary work-around until the API starts working. {% code title="dnsconfig.js" %} ```javascript @@ -159,14 +132,11 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - ## Add nameservers -Purpose: -Use the default nameservers from the registrar but add additional ones. +Purpose: Use the default nameservers from the registrar but add additional ones. -Why? -Usually only to correct a bug or misconfiguration elsewhere. +Why? Usually only to correct a bug or misconfiguration elsewhere. {% code title="dnsconfig.js" %} ```javascript @@ -178,14 +148,11 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - ## Shadow nameservers -Purpose: -Secretly publish your DNS zone records to another server. +Purpose: Secretly publish your DNS zone records to another server. -Why? -There are many reasons to do this: +Why? There are many reasons to do this: * You are preparing to move to a different DNS provider and want to test it before you cut over. * You want your DNS records stored somewhere else in case you have to switch over in an emergency. @@ -202,21 +169,13 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - ## Dual DNS Providers -Purpose: -Use two different DNS services: +Purpose: Use two different DNS services: -Why? -Diversity. If one DNS provider goes down, the other will be used. +Why? Diversity. If one DNS provider goes down, the other will be used. -Little known fact: Most DNS recursive resolvers monitor which DNS -servers are performing the best and automatically start avoiding -servers that are slow or down. This means that if you use this technique -and one DNS provider goes down, after a -while your users won't be affected. Not all software does this properly. -More info: https://www.dns-oarc.net/files/workshop-201203/OARC-workshop-London-2012-NS-selection.pdf +Little known fact: Most DNS recursive resolvers monitor which DNS servers are performing the best and automatically start avoiding servers that are slow or down. This means that if you use this technique and one DNS provider goes down, after a while your users won't be affected. Not all software does this properly. More info: https://www.dns-oarc.net/files/workshop-201203/OARC-workshop-London-2012-NS-selection.pdf {% hint style="info" %} **NOTE**: This is overkill unless you have millions of users and strict up-time requirements. @@ -232,20 +191,13 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - # Other uses ## Make zonefile backups -Purpose: -Make backups of DNS records in a zone. This generates a zonefile listing all -the records in the zone. +Purpose: Make backups of DNS records in a zone. This generates a zonefile listing all the records in the zone. -Why? -You want to write out a BIND-style zonefile for debugging, historical, or -auditing purposes. Some sites do backups of these zonefiles to create a history -of changes. This is different than keeping a history of `dnsconfig.js` because -this is the output of DNSControl, not the input. +Why? You want to write out a BIND-style zonefile for debugging, historical, or auditing purposes. Some sites do backups of these zonefiles to create a history of changes. This is different than keeping a history of `dnsconfig.js` because this is the output of DNSControl, not the input. {% hint style="danger" %} **NOTE**: This won't work if you use pseudo rtypes that BIND doesn't support. @@ -261,16 +213,11 @@ D("example.com", REG_NAMECOM, ``` {% endcode %} - ## Monitor delegation -Purpose: -You don't control the registrar but want to detect if the delegation changes. -You can specify the existing nameservers in `dnsconfig.js` and you will get -a notification if the delegation diverges. +Purpose: You don't control the registrar but want to detect if the delegation changes. You can specify the existing nameservers in `dnsconfig.js` and you will get a notification if the delegation diverges. -Why? -Sometimes you just want to know if something changes! +Why? Sometimes you just want to know if something changes! See the [DNS-over-HTTPS Provider](../provider/dnsoverhttps.md) documentation for more info. @@ -285,7 +232,6 @@ D("example.com", REG_MONITOR, ``` {% endcode %} - {% hint style="info" %} **NOTE**: This checks the NS records via a DNS query. It does not check the registrar's delegation (i.e. the `Name Server:` field in whois). In theory @@ -310,13 +256,11 @@ DOMAIN_ELSEWHERE("example.com", REG_NAMECOM, [ ``` {% endcode %} - ## `DOMAIN_ELSEWHERE_AUTO` Easily delegate a domain to a nameserver via an API query. -This is similar to `DOMAIN_ELSEWHERE` but the list -of nameservers is queried from the API of a single DNS provider. +This is similar to `DOMAIN_ELSEWHERE` but the list of nameservers is queried from the API of a single DNS provider. {% code title="dnsconfig.js" %} ```javascript @@ -325,7 +269,6 @@ DOMAIN_ELSEWHERE_AUTO("example2.com", REG_NAMECOM, DNS_GOOGLE); ``` {% endcode %} - # Limits {% hint style="info" %} diff --git a/documentation/advanced-features/opinions.md b/documentation/advanced-features/opinions.md index d49fd73747..f32eab80ef 100644 --- a/documentation/advanced-features/opinions.md +++ b/documentation/advanced-features/opinions.md @@ -1,99 +1,64 @@ # DNSControl is an opinionated system -DNSControl is an opinionated system. That means that we have certain -opinions about how things should work. +DNSControl is an opinionated system. That means that we have certain opinions about how things should work. This page documents those opinions. - # Opinion #1: DNS should be treated like code -Code is written in a high-level language, version controlled, -commented, tested, and reviewed by a third party... and all of that -happens before it goes into production. - -DNS information should be stored in a version control system, like -Git or Mercurial, and receive all the benefits of using VCS. Changes -should be in the form of PRs that are approved by someone-other-than-you. +Code is written in a high-level language, version controlled, commented, tested, and reviewed by a third party... and all of that happens before it goes into production. -DNS information should be tested for syntax, pass unit tests and -policy tests, all in an automated CI system that assures all changes -are made the same way. (We don't provide a CI system, but DNSControl -makes it easy to use one; and not use one when an emergency update -is needed.) +DNS information should be stored in a version control system, like Git or Mercurial, and receive all the benefits of using VCS. Changes should be in the form of PRs that are approved by someone-other-than-you. -Pushing the changes into production should be effortless, not -requiring people to know which domains are on which providers, or -that certain providers do things differently that others. The -credentials for updates should be controlled such that anyone can -write a PR, but not everyone has access to the credentials. +DNS information should be tested for syntax, pass unit tests and policy tests, all in an automated CI system that assures all changes are made the same way. (We don't provide a CI system, but DNSControl makes it easy to use one; and not use one when an emergency update is needed.) +Pushing the changes into production should be effortless, not requiring people to know which domains are on which providers, or that certain providers do things differently that others. The credentials for updates should be controlled such that anyone can write a PR, but not everyone has access to the credentials. # Opinion #2: Non-experts should be able to safely make DNS changes -The goal of DNSControl is to create a system that is set up by DNS -experts like you, but updates and changes can be made by your -coworkers who aren't DNS experts. +The goal of DNSControl is to create a system that is set up by DNS experts like you, but updates and changes can be made by your coworkers who aren't DNS experts. Things your coworkers should not have to know: -- Your coworkers should not have to know obscure DNS technical -knowledge. That's your job. - -- Your coworkers should not have to know what happens in ambiguous -situations. That's your job. +- Your coworkers should not have to know obscure DNS technical knowledge. That's your job. -- Your coworkers should be able to submit PRs to `dnsconfig.js` for you -to approve; preferably via a CI system that does rudimentary checks -before you even have to see the PR. +- Your coworkers should not have to know what happens in ambiguous situations. That's your job. -- Your coworkers should be able to figure out the language without -much training. The system should block them from doing dangerous -things (even if they are technically legal). +- Your coworkers should be able to submit PRs to `dnsconfig.js` for you to approve; preferably via a CI system that does rudimentary checks before you even have to see the PR. +- Your coworkers should be able to figure out the language without much training. The system should block them from doing dangerous things (even if they are technically legal). # Opinion #3: dnsconfig.js are not zonefiles -A zonefile can list any kind of DNS record. It has no judgement and -no morals. It will let you do bad practices as long as the bits are -RFC-compliant. - -`dnsconfig.js` is a high-level description of your DNS zone data. -Being high-level permits the code to understand intent, and stop -bad behavior. +A zonefile can list any kind of DNS record. It has no judgement and no morals. It will let you do bad practices as long as the bits are RFC-compliant. +`dnsconfig.js` is a high-level description of your DNS zone data. Being high-level permits the code to understand intent, and stop bad behavior. # Opinion #4: All DNS is lowercase for languages that have such a concept -DNSControl downcases all DNS names (domains, labels, and targets). #sorrynotsorry - -When the system reads `dnsconfig.js` or receives data from DNS providers, -the DNS names are downcased. +DNSControl downcases all DNS names (domains, labels, and targets). #sorrynotsorry -This reduces code complexity, reduces the number of edge-cases that must -be tested, and makes the system safer to operate. +When the system reads `dnsconfig.js` or receives data from DNS providers, the DNS names are downcased. -Yes, we know that DNS is case insensitive. See [Opinion #3](#opinion-3-dnsconfig.js-are-not-zonefiles). +This reduces code complexity, reduces the number of edge-cases that must be tested, and makes the system safer to operate. +Yes, we know that DNS is case insensitive. See [Opinion #3](#opinion-3-dnsconfig.js-are-not-zonefiles). # Opinion #5: Users should state what they want, and DNSControl should do the rest -When possible, `dnsconfig.js` lists a high-level description of what -is desired and the compiler does the hard work for you. +When possible, `dnsconfig.js` lists a high-level description of what is desired and the compiler does the hard work for you. Some examples: * Macros and iterators permit you to state something once, correctly, and repeat it many places. -* TXT strings are expressed as JavaScript strings, with no weird DNS-required special escape characters. DNSControl does the escaping for you. -* Domain names with Unicode are listed as real Unicode. Punycode translation is done for you. +* TXT strings are expressed as JavaScript strings, with no weird DNS-required special escape characters. DNSControl does the escaping for you. +* Domain names with Unicode are listed as real Unicode. Punycode translation is done for you. * IP addresses are expressed as IP addresses; and reversing them to in-addr.arpa addresses is done for you. * SPF records are stated in the most verbose way; DNSControl optimizes it for you in a safe, opt-in way. - # Opinion #6: If it is ambiguous in DNS, it is forbidden in DNSControl -When there is ambiguity an expert knows what the system will do. -Your coworkers should not be expected to be experts. (See [Opinion #2](#opinion-2-non-experts-should-be-able-to-safely-make-dns-changes)). +When there is ambiguity an expert knows what the system will do. Your coworkers should not be expected to be experts. (See [Opinion #2](#opinion-2-non-experts-should-be-able-to-safely-make-dns-changes)). We would rather DNSControl error out than require users to be DNS experts. @@ -101,104 +66,55 @@ For example: We know that "bar.com." is a FQDN because it ends with a dot. -Is "bar.com" a FQDN? Well, obviously it is, because it already ends -with ".com" and we all know that "bar.com.bar.com" is probably not -what the user intended. +Is "bar.com" a FQDN? Well, obviously it is, because it already ends with ".com" and we all know that "bar.com.bar.com" is probably not what the user intended. We know that "bar" is *not* an FQDN because it doesn't contain any dots. Is "meta.xyz" a FQDN? -That's ambiguous. If the user knows that "xyz" is a top level domain (TLD) -then it is obvious that it is a FQDN. However, can anyone really memorize -all the TLDSs? There used to be just gov/edu/com/mil/org/net and everyone -could memorize them easily. As of 2000, there are many, many, more. -You can't memorize them all. In fact, even before 2000 you couldn't -memorize them all. (In fact, you didn't even realize that we left out "int"!) +That's ambiguous. If the user knows that "xyz" is a top level domain (TLD) then it is obvious that it is a FQDN. However, can anyone really memorize all the TLDSs? There used to be just gov/edu/com/mil/org/net and everyone could memorize them easily. As of 2000, there are many, many, more. You can't memorize them all. In fact, even before 2000 you couldn't memorize them all. (In fact, you didn't even realize that we left out "int"!) -"xyz" became a TLD in June 2014. Thus, after 2014 a system like DNSControl -would have to act differently. We don't want to be surprised by changes -like that. +"xyz" became a TLD in June 2014. Thus, after 2014 a system like DNSControl would have to act differently. We don't want to be surprised by changes like that. -Therefore, we require all CNAME, MX, and NS targets to be FQDNs (they must -end with a "."), or to be a shortname (no dots at all). Everything -else is ambiguous and therefore an error. +Therefore, we require all CNAME, MX, and NS targets to be FQDNs (they must end with a "."), or to be a shortname (no dots at all). Everything else is ambiguous and therefore an error. # Opinion #7: Hostnames don't have underscores -DNSControl prints warnings if a hostname includes an underscore -(`_`) because underscores are not permitted in hostnames. +DNSControl prints warnings if a hostname includes an underscore (`_`) because underscores are not permitted in hostnames. -We want to prevent a naive user from including an underscore -when they meant to use a hyphen (`-`). +We want to prevent a naive user from including an underscore when they meant to use a hyphen (`-`). Hostnames are more restrictive than general DNS labels. > "While a hostname may not contain other characters, such as the -underscore character (`_`), other DNS names may contain the -underscore. Systems such as DomainKeys and service records use -the underscore as a means to assure that their special character -is not confused with hostnames. For example, -`_http._sctp.www.example.com` specifies a service pointer for an -SCTP capable webserver host (www) in the domain example.com." — _[the Wikipedia entry on hostnames](https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_hostnames)_ - -However that leads to an interesting problem. When is a DNS label -a hostname and when it it just a DNS label? There is no way to -know for sure because code can't guess intention. - -Therefore we print a warning if a label has an underscore in it, -unless the rtype is SRV, TLSA, TXT, or if the name starts with -certain prefixes such as `_dmarc`. We're always willing to -[add more exceptions](https://github.com/DNSControl/dnscontrol/pull/453/files). +underscore character (`_`), other DNS names may contain the underscore. Systems such as DomainKeys and service records use the underscore as a means to assure that their special character is not confused with hostnames. For example, `_http._sctp.www.example.com` specifies a service pointer for an SCTP capable webserver host (www) in the domain example.com." — _[the Wikipedia entry on hostnames](https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_hostnames)_ -# Opinion #8: TXT Records are one long string +However that leads to an interesting problem. When is a DNS label a hostname and when it it just a DNS label? There is no way to know for sure because code can't guess intention. -* TXT records are a single string with a length of 0 to 65,280 bytes - (the maximum possible TXT record size). +Therefore we print a warning if a label has an underscore in it, unless the rtype is SRV, TLSA, TXT, or if the name starts with certain prefixes such as `_dmarc`. We're always willing to [add more exceptions](https://github.com/DNSControl/dnscontrol/pull/453/files). + +# Opinion #8: TXT Records are one long string -It is the provider's responsibility to split, join, quote, parse, -encode, or decoded the string as needed by the provider's API. This -should be invisible to the user. +* TXT records are a single string with a length of 0 to 65,280 bytes (the maximum possible TXT record size). -The user may represent the string any way that JavaScript permits -strings to be represented (usually double-quotes). For backwards -compatibility they may also provide a list of strings which will be -concatenated. +It is the provider's responsibility to split, join, quote, parse, encode, or decoded the string as needed by the provider's API. This should be invisible to the user. -You may be wondering: Isn't a TXT record really a series of 255-octet -segments? Yes, TXT record's wire-format is a series of strings, each -no longer than 255-octets. However that kind of detail should be -hidden from users. The user should represent the string they want and -DNSControl should magically do the right thing behind the scenes. The -same with quoting and escaping required by APIs. +The user may represent the string any way that JavaScript permits strings to be represented (usually double-quotes). For backwards compatibility they may also provide a list of strings which will be concatenated. -You may be wondering: Are there any higher-level applications which -ascribe semantic value to the TXT string boundaries? I believe that -the answer is "no". My proof is not based on reading RFCs, but -instead based on (a) observing that I've never seen a DNS provider's -control panel let you specify the boundaries, (b) I've never seen a -FAQ or reddit post asking how to specify those boundaries. Therefore, -there is no need for this. I also assert that there will be no such -need in the future. +You may be wondering: Isn't a TXT record really a series of 255-octet segments? Yes, TXT record's wire-format is a series of strings, each no longer than 255-octets. However that kind of detail should be hidden from users. The user should represent the string they want and DNSControl should magically do the right thing behind the scenes. The same with quoting and escaping required by APIs. +You may be wondering: Are there any higher-level applications which ascribe semantic value to the TXT string boundaries? I believe that the answer is "no". My proof is not based on reading RFCs, but instead based on (a) observing that I've never seen a DNS provider's control panel let you specify the boundaries, (b) I've never seen a FAQ or reddit post asking how to specify those boundaries. Therefore, there is no need for this. I also assert that there will be no such need in the future. # Opinion #9: RFC 4183 is better than RFC 2317 -There is no standard for how to do reverse lookup zones (in-addr.arpa) -for CIDR blocks that are not /8, /16, or /24. There are only -recommendations. +There is no standard for how to do reverse lookup zones (in-addr.arpa) for CIDR blocks that are not /8, /16, or /24. There are only recommendations. -RFC 2317 is a good recommendation, but it only covers /25 to /32. -It also uses `/` in zone names, which many DNS providers do not -support. +RFC 2317 is a good recommendation, but it only covers /25 to /32. It also uses `/` in zone names, which many DNS providers do not support. -RFC 4183 covers /8 through /32 and uses hyphens, which are supported -universally. +RFC 4183 covers /8 through /32 and uses hyphens, which are supported universally. Originally DNSControl implemented RFC 2317. -In v5.0 we will adopt RFC 4183 as the default. A new function, -[REVCOMPAT()](../language-reference/top-level-functions/REVCOMPAT.md), will be provided to enable backwards compatibility. -v4.x users can use the function to adopt the new behavior early. +In v5.0 we will adopt RFC 4183 as the default. A new function, [REVCOMPAT()](../language-reference/top-level-functions/REVCOMPAT.md), will be provided to enable backwards compatibility. v4.x users can use the function to adopt the new behavior early. See [REVCOMPAT()](../language-reference/top-level-functions/REVCOMPAT.md) for details. diff --git a/documentation/advanced-features/styleguide-code.md b/documentation/advanced-features/styleguide-code.md index cd05b25a28..c413170e7a 100644 --- a/documentation/advanced-features/styleguide-code.md +++ b/documentation/advanced-features/styleguide-code.md @@ -4,34 +4,25 @@ - # Always favor simplicity -This is a community project. The code you write today will be maintained by -someone in the future that may not be a professional developer or one that is -as experienced as you. +This is a community project. The code you write today will be maintained by someone in the future that may not be a professional developer or one that is as experienced as you. Remember what Brian Kernighan wrote: > "Debugging is twice as hard as writing the -code in the first place. Therefore, if you write the code as cleverly as -possible, you are, by definition, not smart enough to debug it." — _Brian Kernighan_ +code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — _Brian Kernighan_ Remember the [John Woods](http://wiki.c2.com/?CodeForTheMaintainer) quote: > "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." — _[John Woods](http://wiki.c2.com/?CodeForTheMaintainer)_ -Don't code for today-you. Write code for six-months-from-now-you. Have you -met six-months-from-now-you? Oh, you should. Fine individual. They are -quite smart. They have 6 months more experience than today-you, but sadly -has had 6 months to forget what today-you knows. The job of today-you is to -write code that six-months-from-now-you can understand. +Don't code for today-you. Write code for six-months-from-now-you. Have you met six-months-from-now-you? Oh, you should. Fine individual. They are quite smart. They have 6 months more experience than today-you, but sadly has had 6 months to forget what today-you knows. The job of today-you is to write code that six-months-from-now-you can understand. * Avoid building a complex framework to be perfectly DRY when a little bit of repetition will result in easier to understand code. * Break things into well-defined functions that can be individually read, understood, and tested. - # Filenames These are the filenames to use: @@ -50,15 +41,12 @@ These are the filenames to use: # JavaScript annotations -Functions in `pkg/js/helpers.js` should be annotated using the -[JSDoc](https://jsdoc.app/tags-param.html) `@` notation. These are used to -generate autocomplete instructions for your IDE. +Functions in `pkg/js/helpers.js` should be annotated using the [JSDoc](https://jsdoc.app/tags-param.html) `@` notation. These are used to generate autocomplete instructions for your IDE. * Add `@param {type} foo` for a parameter named `foo` that is of type `type`. * Example: `@param {string} foo Description of the parameter` * Add `@deprecated` if the function is deprecated. - # Don't conditionally add/remove trailing dots {% hint style="info" %} @@ -95,9 +83,6 @@ Let's suppose the API no longer adds a "." when it previously did. Was the chang ### What should we do instead? -Option 1: Write code that assumes it won't change. If you need to add a dot, -it is safe to just `s = s + "."` The code will be readable by any Go -developer; and less cognitive load than using a function. +Option 1: Write code that assumes it won't change. If you need to add a dot, it is safe to just `s = s + "."` The code will be readable by any Go developer; and less cognitive load than using a function. -Option 2: Panic if you see something unexpected. If you are stripping a dot, -panic if the dot doesn't exist. +Option 2: Panic if you see something unexpected. If you are stripping a dot, panic if the dot doesn't exist. diff --git a/documentation/advanced-features/styleguide-doc.md b/documentation/advanced-features/styleguide-doc.md index ec2df9c18e..6bb62207db 100644 --- a/documentation/advanced-features/styleguide-doc.md +++ b/documentation/advanced-features/styleguide-doc.md @@ -33,8 +33,7 @@ Within the git repo, docs are grouped: ## Top-of-Document parameters -Files in the `documentation/language-reference/{record,domain,global}` subdirectories -have a header at the top that is used to populate other systems. +Files in the `documentation/language-reference/{record,domain,global}` subdirectories have a header at the top that is used to populate other systems. Here's an example from [`A`](../language-reference/domain-modifiers/A.md) @@ -82,8 +81,7 @@ Include a blank line between paragraphs. Leave exactly one blank line before and after a heading. -JavaScript code should use double quotes (`"`) for strings, not single quotes -(`'`). They are equivalent but consistency is good. +JavaScript code should use double quotes (`"`) for strings, not single quotes (`'`). They are equivalent but consistency is good. ### Headings @@ -187,10 +185,7 @@ This is a second line #### Mentioning language features -Not every mention to A, CNAME, or function -needs to be a link to the manual for that record type. -However, the first mention on a page should always -be a link. Others are at the authors digression. +Not every mention to A, CNAME, or function needs to be a link to the manual for that record type. However, the first mention on a page should always be a link. Others are at the authors digression. ```markdown The [`PTR`](../language-reference/domain-modifiers/PTR.md) feature is helpful in LANs. @@ -239,7 +234,4 @@ Please capitalize these terms as you see them here: Please spellcheck documents before submitting a PR. -Don't be surprised if Tom rewrites your text. He often does that to keep the -documentation consistent and make it more approachable by new users. It's not -[because he has a big ego](https://www.amazon.com/stores/author/B004J0QIVM). -Well, not usually. +Don't be surprised if Tom rewrites your text. He often does that to keep the documentation consistent and make it more approachable by new users. It's not [because he has a big ego](https://www.amazon.com/stores/author/B004J0QIVM). Well, not usually. diff --git a/documentation/advanced-features/testing-txt-records.md b/documentation/advanced-features/testing-txt-records.md index b050202294..f8c8ab9e45 100644 --- a/documentation/advanced-features/testing-txt-records.md +++ b/documentation/advanced-features/testing-txt-records.md @@ -1,34 +1,24 @@ # TXT record testing -We recently discovered a strange bug with processing TXT records and -double-quotes. Sadly we haven't been able to determine a way to test this -automatically. Therefore, I've written up this methodology. +We recently discovered a strange bug with processing TXT records and double-quotes. Sadly we haven't been able to determine a way to test this automatically. Therefore, I've written up this methodology. # The problem The problem relates to TXT records that have a string with quotes in them. -If a user creates a TXT record whose contents are `"something"` (yes, with -double quotes), some APIs get confused. +If a user creates a TXT record whose contents are `"something"` (yes, with double quotes), some APIs get confused. -This bug is most likely to appear in a provider that uses -`RecordConfig.PopulateFromString()` (see `models/t_parse.go`) to create TXT -records. That function assumes the string should always have the quotes -stripped, though it is more likely that the string should be taken verbatim. +This bug is most likely to appear in a provider that uses `RecordConfig.PopulateFromString()` (see `models/t_parse.go`) to create TXT records. That function assumes the string should always have the quotes stripped, though it is more likely that the string should be taken verbatim. # The test -To complete this test, you will need a test domain that you can add records to. -It won't be modified otherwise. +To complete this test, you will need a test domain that you can add records to. It won't be modified otherwise. -This bug has to do with double-quotes at the start and end of TXT records. If -your provider doesn't permit double-quotes in TXT records (you'd be surprised!) -you don't have to worry about this bug because those records are banned -in your `auditrecords.go` file. +This bug has to do with double-quotes at the start and end of TXT records. If your provider doesn't permit double-quotes in TXT records (you'd be surprised!) you don't have to worry about this bug because those records are banned in your `auditrecords.go` file. ## Step 1: Create the test records -Log into your DNS provider's web UI (portal) and create these 4 TXT records. (Don't use DNSControl!) Yes, include the double-quotes on test 2 and 3! +Log into your DNS provider's web UI (portal) and create these 4 TXT records. (Don't use DNSControl!) Yes, include the double-quotes on test 2 and 3! | Hostname | TXT | |---------------|-----------| @@ -37,7 +27,6 @@ Log into your DNS provider's web UI (portal) and create these 4 TXT records. (D | t2 | "test2" | | t3 | "test3" | - ## Step 2: Update `dnsconfig.js` Now in your `dnsconfig.js` file, add these records to the domain: @@ -56,14 +45,11 @@ When you do a `dnscontrol preview`, you should see changes for t1 and t2. #2: MODIFY TXT t2.example.com: ("\"test2\"" ttl=1) -> ("test2" ttl=1) ``` -If you don't see those changes, that's a bug. For example, we found that -Cloudflare left t2 alone but would try to add double-quotes to t3! This was -fixed in [PR#1543](https://github.com/DNSControl/dnscontrol/pull/1543). +If you don't see those changes, that's a bug. For example, we found that Cloudflare left t2 alone but would try to add double-quotes to t3! This was fixed in [PR#1543](https://github.com/DNSControl/dnscontrol/pull/1543). ## Step 4: Push -Let's assume you DO see the changes. Push them using `dnscontrol push` -then check the webui to see that the changes are correct. +Let's assume you DO see the changes. Push them using `dnscontrol push` then check the webui to see that the changes are correct. ```text 2 corrections @@ -73,9 +59,7 @@ SUCCESS! SUCCESS! ``` -Refresh your provider's web UI and you should see the changes as expected: t1 -should have double-quotes and t2 shouldn't. If the change wasn't correctly -done, that's a bug. +Refresh your provider's web UI and you should see the changes as expected: t1 should have double-quotes and t2 shouldn't. If the change wasn't correctly done, that's a bug. ## Step 5: That's it! diff --git a/documentation/advanced-features/unittests.md b/documentation/advanced-features/unittests.md index c1da91e86d..c2f05e9d38 100644 --- a/documentation/advanced-features/unittests.md +++ b/documentation/advanced-features/unittests.md @@ -2,15 +2,11 @@ ## Built-in Tests -DNSControl performs a number of tests during the validation stage. -You can find them in `pkg/normalize/validate.go`. - +DNSControl performs a number of tests during the validation stage. You can find them in `pkg/normalize/validate.go`. ## External tests -Tests specific to your environment may be added as external tests. -Output the intermediate representation as a JSON file and perform -tests on this data. +Tests specific to your environment may be added as external tests. Output the intermediate representation as a JSON file and perform tests on this data. Output the intermediate representation: @@ -32,8 +28,6 @@ Here is a sample test written in `bash` using the [jq](https://stedolan.github.i echo BAD fi - ## Future directions -Manipulating JSON data is difficult. If you implement ways to make it easier, we'd -gladly accept contributions. +Manipulating JSON data is difficult. If you implement ways to make it easier, we'd gladly accept contributions. diff --git a/documentation/advanced-features/writing-providers.md b/documentation/advanced-features/writing-providers.md index b934be21b6..7ef208c0a5 100644 --- a/documentation/advanced-features/writing-providers.md +++ b/documentation/advanced-features/writing-providers.md @@ -1,14 +1,8 @@ # Writing new DNS providers -Writing a new DNS provider is a relatively straightforward process. -You essentially need to implement the -[providers.DNSServiceProvider interface.](https://pkg.go.dev/github.com/DNSControl/dnscontrol/v4/pkg/providers#DNSServiceProvider) -and the system takes care of the rest. +Writing a new DNS provider is a relatively straightforward process. You essentially need to implement the [providers.DNSServiceProvider interface.](https://pkg.go.dev/github.com/DNSControl/dnscontrol/v4/pkg/providers#DNSServiceProvider) and the system takes care of the rest. -Please do note that if you submit a new provider you will be -assigned bugs related to the provider in the future (unless -you designate someone else as the maintainer). More details -[here](../provider/index.md). +Please do note that if you submit a new provider you will be assigned bugs related to the provider in the future (unless you designate someone else as the maintainer). More details [here](../provider/index.md). Please follow the [DNSControl Code Style Guide](styleguide-code.md) and the [DNSControl Documentation Style Guide](styleguide-doc.md). @@ -22,53 +16,29 @@ A typical provider implements 3 methods and DNSControl takes care of the rest: * GetZoneRecordsCorrections() -- Generate a list of corrections. * GetNameservers() -- Query the API and return the list of parent nameservers. -These three functions are all that's needed for `dnscontrol preview` -and `dnscontrol push`. +These three functions are all that's needed for `dnscontrol preview` and `dnscontrol push`. -The goal of `GetZoneRecords()` is to download all the DNS records, -convert them to `models.RecordConfig` format, and return them as one big list -(`models.Records`). +The goal of `GetZoneRecords()` is to download all the DNS records, convert them to `models.RecordConfig` format, and return them as one big list (`models.Records`). -The goal of `GetZoneRecordsCorrections()` is to return a list of -corrections. Each correction is a text string describing the change -("Delete CNAME record foo") and a function that, if called, will -make the change (i.e. call the API and delete record foo). `dnscontrol preview` -simply prints the text strings. `dnscontrol push` prints the -strings and calls the functions. Because of how Go's functions work, -the function will have everything it needs to make the change. -Pretty cool, eh? +The goal of `GetZoneRecordsCorrections()` is to return a list of corrections. Each correction is a text string describing the change ("Delete CNAME record foo") and a function that, if called, will make the change (i.e. call the API and delete record foo). `dnscontrol preview` simply prints the text strings. `dnscontrol push` prints the strings and calls the functions. Because of how Go's functions work, the function will have everything it needs to make the change. Pretty cool, eh? -Calculating the difference between existing and desired is difficult. Luckily -the work is done for you. `GetZoneRecordsCorrections()` calls a a function in -the `pkg/diff2` module that generates a list of changes (usually an ADD, -CHANGE, or DELETE) that can easily be turned into the API calls mentioned -previously. +Calculating the difference between existing and desired is difficult. Luckily the work is done for you. `GetZoneRecordsCorrections()` calls a a function in the `pkg/diff2` module that generates a list of changes (usually an ADD, CHANGE, or DELETE) that can easily be turned into the API calls mentioned previously. So, what does all this mean? -It basically means that writing a provider is as simple as writing -code that (1) downloads the existing records, (2) converts each -records into `models.RecordConfig`, (3) write functions that perform -adds, changes, and deletions. +It basically means that writing a provider is as simple as writing code that (1) downloads the existing records, (2) converts each records into `models.RecordConfig`, (3) write functions that perform adds, changes, and deletions. -If you are new to Go, there are plenty of providers you can copy -from. In fact, many non-Go programmers -[have learned Go by contributing to DNSControl](https://everythingsysadmin.com/2017/08/go-get-up-to-speed.html). +If you are new to Go, there are plenty of providers you can copy from. In fact, many non-Go programmers [have learned Go by contributing to DNSControl](https://everythingsysadmin.com/2017/08/go-get-up-to-speed.html). Now that you understand the general process, here are the details. ## Step 1: General advice -A provider can be a DnsProvider, a Registrar, or both. We recommend -you write the DnsProvider first, release it, and then write the -Registrar if needed. +A provider can be a DnsProvider, a Registrar, or both. We recommend you write the DnsProvider first, release it, and then write the Registrar if needed. -If you have any questions, please discuss them in the GitHub issue -related to the request for this provider. +If you have any questions, please discuss them in the GitHub issue related to the request for this provider. -This document is constantly being updated. Please let us know what -was confusing so we can update this document with advice for future -authors (or even better send a PR!). +This document is constantly being updated. Please let us know what was confusing so we can update this document with advice for future authors (or even better send a PR!). ## Step 2: Pick a base provider @@ -76,10 +46,7 @@ It's a good idea to start by copying a similar provider. How can you tell a provider is similar? -Each DNS provider's API falls into one of 4 category. Some update one DNS record at a time. -Others, the only change they permit is to upload the entire zone even if only one record changed! -Others are somewhere in between: all records at a label must be updated at once, or all records -in a RecordSet (the label + rType). +Each DNS provider's API falls into one of 4 category. Some update one DNS record at a time. Others, the only change they permit is to upload the entire zone even if only one record changed! Others are somewhere in between: all records at a label must be updated at once, or all records in a RecordSet (the label + rType). In summary, provider APIs basically fall into four general categories: @@ -92,11 +59,7 @@ To determine your provider's category, review your API documentation. To determine an existing provider's category, see which `diff2.By*()` function is used. -DNSControl provides 4 helper functions that do all the hard work for -you. As input, they take the existing zone (what was downloaded via -the API) and the desired zone (what is in `dnsconfig.js`). They -return a list of instructions. Implement handlers for the instructions -and DNSControl is able to perform `dnscontrol push`. +DNSControl provides 4 helper functions that do all the hard work for you. As input, they take the existing zone (what was downloaded via the API) and the desired zone (what is in `dnsconfig.js`). They return a list of instructions. Implement handlers for the instructions and DNSControl is able to perform `dnscontrol push`. The functions are: @@ -109,46 +72,33 @@ The file `pkg/diff2/diff2.go` has instructions about how to use the diff2 system ## Step 3: Create the driver skeleton -Create a directory for the provider called `providers/name` where -`name` is all lowercase and represents the commonly-used name for -the service. +Create a directory for the provider called `providers/name` where `name` is all lowercase and represents the commonly-used name for the service. -The main driver should be called `providers/name/nameProvider.go`. -The API abstraction is usually in a separate file (often called -`api.go`). +The main driver should be called `providers/name/nameProvider.go`. The API abstraction is usually in a separate file (often called `api.go`). Directory names should be consistent. It should be all lowercase and match the ALLCAPS provider name. Avoid `_`s. ## Step 4: Activate the driver -Edit -[providers/\_all/all.go](https://github.com/DNSControl/dnscontrol/blob/main/pkg/providers/_all/all.go). -Add the provider list so DNSControl knows it exists. +Edit [providers/\_all/all.go](https://github.com/DNSControl/dnscontrol/blob/main/pkg/providers/_all/all.go). Add the provider list so DNSControl knows it exists. ## Step 5: Implement **If you are implementing a DNS Service Provider:** -Implement all the calls in the -[providers.DNSServiceProvider interface](https://pkg.go.dev/github.com/DNSControl/dnscontrol/v4/pkg/providers#DNSServiceProvider). +Implement all the calls in the [providers.DNSServiceProvider interface](https://pkg.go.dev/github.com/DNSControl/dnscontrol/v4/pkg/providers#DNSServiceProvider). -The function `GetDomainCorrections()` is a bit interesting. It returns -a list of corrections to be made. These are in the form of functions -that DNSControl can call to actually make the corrections. +The function `GetDomainCorrections()` is a bit interesting. It returns a list of corrections to be made. These are in the form of functions that DNSControl can call to actually make the corrections. **If you are implementing a DNS Registrar:** -Implement all the calls in the -[providers.Registrar interface](https://pkg.go.dev/github.com/DNSControl/dnscontrol/v4/pkg/providers#Registrar). +Implement all the calls in the [providers.Registrar interface](https://pkg.go.dev/github.com/DNSControl/dnscontrol/v4/pkg/providers#Registrar). -The function `GetRegistrarCorrections()` returns -a list of corrections to be made. These are in the form of functions -that DNSControl can call to actually make the corrections. +The function `GetRegistrarCorrections()` returns a list of corrections to be made. These are in the form of functions that DNSControl can call to actually make the corrections. ## Step 6: Unit Test -Make sure the existing unit tests work. Add unit tests for any -complex algorithms in the new code. +Make sure the existing unit tests work. Add unit tests for any complex algorithms in the new code. Run the unit tests with this command: @@ -156,8 +106,7 @@ Run the unit tests with this command: ## Step 7: Integration Test -This is the most important kind of testing when adding a new provider. -Integration tests use a test account and a test domain. +This is the most important kind of testing when adding a new provider. Integration tests use a test account and a test domain. {% hint style="danger" %} All records will be deleted from the test domain! Use a OTE domain or a real domain that isn't otherwise in use and can be destroyed. @@ -207,9 +156,7 @@ Some useful `go test` flags: This is optional. -There is a potential bug in how TXT records are handled. Sadly we haven't found -an automated way to test for this bug. The manual steps are here in -[documentation/testing-txt-records.md](testing-txt-records.md) +There is a potential bug in how TXT records are handled. Sadly we haven't found an automated way to test for this bug. The manual steps are here in [documentation/testing-txt-records.md](testing-txt-records.md) ## Step 9: Update docs, CICD and other files @@ -232,43 +179,23 @@ a particular integration test, or request feedback. ## Step 10: Capabilities -Some DNS providers have features that others do not. For example some -support the SRV record. A provider announces what it can do using -the capabilities system. +Some DNS providers have features that others do not. For example some support the SRV record. A provider announces what it can do using the capabilities system. -If a provider doesn't advertise a particular capability, the integration -test system skips the appropriate tests. Therefore you might want -to initially develop the provider with no particular capabilities -advertised and code until all the integration tests work. Then -enable capabilities one at a time to finish off the project. +If a provider doesn't advertise a particular capability, the integration test system skips the appropriate tests. Therefore you might want to initially develop the provider with no particular capabilities advertised and code until all the integration tests work. Then enable capabilities one at a time to finish off the project. -Don't feel obligated to implement everything at once. In fact, we'd -prefer a few small PRs than one big one. Focus on getting the basic -provider working well before adding these extras. +Don't feel obligated to implement everything at once. In fact, we'd prefer a few small PRs than one big one. Focus on getting the basic provider working well before adding these extras. -Operational features have names like `providers.CanUseSRV` and -`providers.CanUseAlias`. The list of optional "capabilities" are -in the file `dnscontrol/pkg/providers/providers.go` (look for `CanUseAlias`). +Operational features have names like `providers.CanUseSRV` and `providers.CanUseAlias`. The list of optional "capabilities" are in the file `dnscontrol/pkg/providers/providers.go` (look for `CanUseAlias`). -Capabilities are processed early by DNSControl. For example if a -provider doesn't support SRV records, DNSControl will error out -when parsing `dnscontrol.js` rather than waiting until the API fails -at the very end. +Capabilities are processed early by DNSControl. For example if a provider doesn't support SRV records, DNSControl will error out when parsing `dnscontrol.js` rather than waiting until the API fails at the very end. -Enable optional capabilities in the `nameProvider.go` file and run -the integration tests to see what works and what doesn't. Fix any -bugs and repeat, repeat, repeat until you have all the capabilities -you want to implement. +Enable optional capabilities in the `nameProvider.go` file and run the integration tests to see what works and what doesn't. Fix any bugs and repeat, repeat, repeat until you have all the capabilities you want to implement. -FYI: If a provider's capabilities changes, run `go generate` to update -the documentation. +FYI: If a provider's capabilities changes, run `go generate` to update the documentation. ## Step 11: Automated code tests -We use a number of automated code-checking systems. Please run your code -through all of them and fix all warnings and errors. Some of the automated -fixes may not alway sbe perfect. Therefore, it is best to commit your code -before running these and verify that you agree with the changes. +We use a number of automated code-checking systems. Please run your code through all of them and fix all warnings and errors. Some of the automated fixes may not alway sbe perfect. Therefore, it is best to commit your code before running these and verify that you agree with the changes. Modernize your code: @@ -300,9 +227,7 @@ Commit any changes. ## Step 12: Dependencies -See [documentation/release-engineering.md](../release/release-engineering.md) -for tips about managing modules and checking for outdated -dependencies. +See [documentation/release-engineering.md](../release/release-engineering.md) for tips about managing modules and checking for outdated dependencies. ## Step 13: Modify the release regexp @@ -386,9 +311,7 @@ At this point you can submit a PR. The PR should include the sentence: "Please create the GitHub label 'provider-PROVIDERNAME'" (change `PROVIDERNAME` to the name of your provider.) This is -Actually you can submit the PR earlier if you just want feedback, -or have questions. However if you haven't submitted a PR by now, this is the time to do it. - +Actually you can submit the PR earlier if you just want feedback, or have questions. However if you haven't submitted a PR by now, this is the time to do it. ## Step 17: After the PR is merged diff --git a/documentation/commands/colors.md b/documentation/commands/colors.md index 4daafdb5dd..337f06e2e4 100644 --- a/documentation/commands/colors.md +++ b/documentation/commands/colors.md @@ -1,29 +1,21 @@ # Colors support -DNSControl is using colors on both its console and notification outputs, to -denote changes, such as during preview or push events. +DNSControl is using colors on both its console and notification outputs, to denote changes, such as during preview or push events. -This is on by default in all interactive prompts supporting colors. See below on -how to bypass it. +This is on by default in all interactive prompts supporting colors. See below on how to bypass it. ## Disable colors -There are cases that we might need to disable colored output, such as in certain -CI environments or particular notification mechanisms that don't support ANSI color -codes. +There are cases that we might need to disable colored output, such as in certain CI environments or particular notification mechanisms that don't support ANSI color codes. -In order to do so, a global `--no-colors` command option is provided, which when -set `--no-colors=true`, will disable colors globally. +In order to do so, a global `--no-colors` command option is provided, which when set `--no-colors=true`, will disable colors globally. Alternatively, a `NO_COLOR` environment variable set to any non-empty string will disable color output. ## (Force) Enable colors -If color support is not correctly detected, providing `--no-colors=false` would -force-enable coloring, bypassing modules TTY detection. +If color support is not correctly detected, providing `--no-colors=false` would force-enable coloring, bypassing modules TTY detection. ## Force colors in CI environments -Some CI environments, while supporting colors, fail autodetection, such as GHA. -In that case, colors can be forcibly enabled via `--no-colors=false` or by setting -a `CI` env variable to `true` (if not autoset). +Some CI environments, while supporting colors, fail autodetection, such as GHA. In that case, colors can be forcibly enabled via `--no-colors=false` or by setting a `CI` env variable to `true` (if not autoset). diff --git a/documentation/commands/creds-json.md b/documentation/commands/creds-json.md index f325f4d368..83d6e11b94 100644 --- a/documentation/commands/creds-json.md +++ b/documentation/commands/creds-json.md @@ -1,7 +1,6 @@ # creds.json -When DNSControl interacts with a provider, any API keys, credentials, or other -configuration parameters required are stored in `creds.json`. The file contains a set of key/value pairs for each configuration. That is, since a provider can be used multiple times with different credentials, the file contains a section for each set of credentials. +When DNSControl interacts with a provider, any API keys, credentials, or other configuration parameters required are stored in `creds.json`. The file contains a set of key/value pairs for each configuration. That is, since a provider can be used multiple times with different credentials, the file contains a section for each set of credentials. Here's a sample file: @@ -45,26 +44,13 @@ Here's a sample file: ## New in v3.16 -The special subkey "TYPE" is used to indicate the provider type (NONE, -CLOUDFLAREAPI, GCLOUD, etc). +The special subkey "TYPE" is used to indicate the provider type (NONE, CLOUDFLAREAPI, GCLOUD, etc). -Prior to [v3.16](../release/v316.md), the provider type is specified as the second argument -to `NewRegistrar()` and `NewDnsProvider()` in `dnsconfig.js` or as a -command-line argument in tools such as `dnscontrol get-zones`. +Prior to [v3.16](../release/v316.md), the provider type is specified as the second argument to `NewRegistrar()` and `NewDnsProvider()` in `dnsconfig.js` or as a command-line argument in tools such as `dnscontrol get-zones`. -Starting in [v3.16](../release/v316.md), `NewRegistrar()`, and `NewDnsProvider()` no longer -require the provider type to be specified. It may be specified for -backwards compatibility, but a warning will be generated with a -suggestion of how to upgrade to the 4.0 format. Likewise, -command-line tools no longer require the provider type to be -specified, but for backwards compatibility one may specify `-` since -the parameter is positional. +Starting in [v3.16](../release/v316.md), `NewRegistrar()`, and `NewDnsProvider()` no longer require the provider type to be specified. It may be specified for backwards compatibility, but a warning will be generated with a suggestion of how to upgrade to the 4.0 format. Likewise, command-line tools no longer require the provider type to be specified, but for backwards compatibility one may specify `-` since the parameter is positional. -In 4.0, DNSControl will require the "TYPE" subkey in each `creds.json` -entry. Command line tools will have a backwards-incompatible change to -remove the provider-type as a positional argument. Prior to 4.0, the -various commands will output warnings and suggestions to avoid -compatibility issues during the transition. +In 4.0, DNSControl will require the "TYPE" subkey in each `creds.json` entry. Command line tools will have a backwards-incompatible change to remove the provider-type as a positional argument. Prior to 4.0, the various commands will output warnings and suggestions to avoid compatibility issues during the transition. ## Error messages @@ -74,8 +60,7 @@ Message: `WARNING: For future compatibility, add this entry creds.json:...` Message: `WARNING: For future compatibility, update the ... entry in creds.json by adding:...` -These messages indicates that this provider is not mentioned in `creds.json`. In v4.0 -all providers used in `dnsconfig.js` will require an entry in `creds.json`. +These messages indicates that this provider is not mentioned in `creds.json`. In v4.0 all providers used in `dnsconfig.js` will require an entry in `creds.json`. For a smooth transition, please update your `creds.json` file now. @@ -95,12 +80,9 @@ Here is the minimal entry required: Message: `INFO: In dnsconfig.js New*(..., ...) can be simplified to New*(...)` -This message indicates that the same provider name is specified in -`dnsconfig.js` and `creds.json` and offers a suggestion for reducing -the redundancy. +This message indicates that the same provider name is specified in `dnsconfig.js` and `creds.json` and offers a suggestion for reducing the redundancy. -The fix is to update `dnsconfig.js` as suggested in the error. -Usually this is to simply remove the second parameter to the function. +The fix is to update `dnsconfig.js` as suggested in the error. Usually this is to simply remove the second parameter to the function. Examples: @@ -138,7 +120,6 @@ Starting with v4.0 support for the OLD format may be reported as an error. Please adopt the NEW format when your installation has eliminated any use of DNSControl pre-3.16. - ### mismatch Message: `ERROR: Mismatch found! creds.json entry ... has ... set to ... but dnsconfig.js specifies New*(..., ...)` @@ -151,9 +132,7 @@ The fix is to change one to match the other. Message: `ERROR: creds.json entry ... is missing ...: ...` -However no `TYPE` subkey was found in an entry in `creds.json`. -In 3.16 forward, it is required if new-style `NewRegistrar()` or `NewDnsProvider()` was used. -In 4.0 this is required. +However no `TYPE` subkey was found in an entry in `creds.json`. In 3.16 forward, it is required if new-style `NewRegistrar()` or `NewDnsProvider()` was used. In 4.0 this is required. The fix is to add a `TYPE` subkey to the `creds.json` entry. @@ -161,14 +140,9 @@ The fix is to add a `TYPE` subkey to the `creds.json` entry. Message: `ERROR: creds.json entry ... has invalid ... value ...` -This indicates that the type `-` was specified in a `TYPE` value in -`creds.json`. There is no provider named `-` therefore that is -invalid. Perhaps you meant to specify a `-` on a command-line tool? - -The fix is to change the `TYPE` subkey entry in `creds.json` from `-` to -a valid service provider identifier, as listed -in [the service provider list](../provider/index.md). +This indicates that the type `-` was specified in a `TYPE` value in `creds.json`. There is no provider named `-` therefore that is invalid. Perhaps you meant to specify a `-` on a command-line tool? +The fix is to change the `TYPE` subkey entry in `creds.json` from `-` to a valid service provider identifier, as listed in [the service provider list](../provider/index.md). ## Using a different file name @@ -200,11 +174,7 @@ Following commands would execute a shell command: dnscontrol preview --creds '!op inject -i creds.json.tpl' ``` -This example requires the [1Password command-line tool](https://developer.1password.com/docs/cli/) -but works with any shell command that returns a properly formatted `creds.json`. -In this case, the 1Password CLI is used to inject the secrets from -a 1Password vault, rather than storing them in environment variables. -An example of a template file containing Linode and Cloudflare API credentials is available here: [creds.json](https://github.com/DNSControl/dnscontrol/blob/main/documentation/assets/1password/creds.json). +This example requires the [1Password command-line tool](https://developer.1password.com/docs/cli/) but works with any shell command that returns a properly formatted `creds.json`. In this case, the 1Password CLI is used to inject the secrets from a 1Password vault, rather than storing them in environment variables. An example of a template file containing Linode and Cloudflare API credentials is available here: [creds.json](https://github.com/DNSControl/dnscontrol/blob/main/documentation/assets/1password/creds.json). {% code title="creds.json" %} ```json @@ -229,10 +199,6 @@ An example of a template file containing Linode and Cloudflare API credentials i Do NOT store `creds.json` (or any secrets!) in a Git repository. That is not secure. -For example, storing the creds.json at the top of this document would be horribly insecure. -Anyone with access to your Git repository *or the history* will know your apiuser is `REDACTED`. -Removing secrets accidentally stored in Git is very difficult because you'll need to rewrite -the repo history. +For example, storing the creds.json at the top of this document would be horribly insecure. Anyone with access to your Git repository *or the history* will know your apiuser is `REDACTED`. Removing secrets accidentally stored in Git is very difficult because you'll need to rewrite the repo history. -A better way is to use environment variables as in the `CNR` example above. Use -secure means to distribute the names and values of the environment variables. +A better way is to use environment variables as in the `CNR` example above. Use secure means to distribute the names and values of the environment variables. diff --git a/documentation/commands/fmt.md b/documentation/commands/fmt.md index 8ebf4f9819..3799cd3086 100644 --- a/documentation/commands/fmt.md +++ b/documentation/commands/fmt.md @@ -27,12 +27,9 @@ which will have different formatting style. The `fmt` subcommand formats and prettifies a dnsconfig.js file. -By default `dnsconfig.js` is read, reformatted, and (if there are no changes) -rewritten. It is not rewritten if there are no changes to preserve the file's -timestamp. +By default `dnsconfig.js` is read, reformatted, and (if there are no changes) rewritten. It is not rewritten if there are no changes to preserve the file's timestamp. -By default the command is silent if no changes were made. Add `-v` to always -output the filename. (Prior to v2.28.3 the filename was always output.) +By default the command is silent if no changes were made. Add `-v` to always output the filename. (Prior to v2.28.3 the filename was always output.) Changes: @@ -59,9 +56,7 @@ $ # Using `fmt` as a filter -`fmt` can also work as a filter by setting the input or output to `""` in which -case stdin or stdout is used, respectively. When the output is stdout, the -filename is never output. +`fmt` can also work as a filter by setting the input or output to `""` in which case stdin or stdout is used, respectively. When the output is stdout, the filename is never output. ```shell $ dnscontrol fmt -o "" >new-dnsconfig.js diff --git a/documentation/commands/get-zones.md b/documentation/commands/get-zones.md index 223dc9a7f3..82724dda1b 100644 --- a/documentation/commands/get-zones.md +++ b/documentation/commands/get-zones.md @@ -1,53 +1,34 @@ # get-zones -DNSControl has a stand-alone utility that will contact a provider, -download the records of one or more zones, and output them to a file -in a variety of formats. +DNSControl has a stand-alone utility that will contact a provider, download the records of one or more zones, and output them to a file in a variety of formats. -`get-zones` relies on command line parameters and `creds.json` -exclusively. It does not use `dnsconfig.js`. This is to assist -bootstrapping a new system. +`get-zones` relies on command line parameters and `creds.json` exclusively. It does not use `dnsconfig.js`. This is to assist bootstrapping a new system. ## Use case 1: Bootstrapping a new system -If you are moving a DNS zone from a provider to DNSControl, this -command will do most of the work for you by downloading the records -and writing them out in `dnsconfig.js` format. It is intended to be -"a decent first draft", only requiring minimal editing. +If you are moving a DNS zone from a provider to DNSControl, this command will do most of the work for you by downloading the records and writing them out in `dnsconfig.js` format. It is intended to be "a decent first draft", only requiring minimal editing. -Use `--format=djs` or `--format=js` (djs is recommended; djs format is a -comma-leading formatting style for lists, sometimes also called Haskell style). +Use `--format=djs` or `--format=js` (djs is recommended; djs format is a comma-leading formatting style for lists, sometimes also called Haskell style). -Minor editing is required. Not all record formats are supported. -SOA records are commented out, since most providers do not support it. -BIND supports it, but requires the data to be entered as meta data. +Minor editing is required. Not all record formats are supported. SOA records are commented out, since most providers do not support it. BIND supports it, but requires the data to be entered as meta data. -The `NAMESERVER()` command is generated commented out. This is usually -not needed as DNSControl can get more accurate information via the -API. Remove the comments only to override the DNS service provider. +The `NAMESERVER()` command is generated commented out. This is usually not needed as DNSControl can get more accurate information via the API. Remove the comments only to override the DNS service provider. ## Use case 2: Generating BIND ZONE files -The `--format=zone` generates BIND-style zonefiles. Pseudo records not -supported by BIND are generated as comments. +The `--format=zone` generates BIND-style zonefiles. Pseudo records not supported by BIND are generated as comments. -This format is useful when moving zonedata between providers, since -the format is relatively universal. +This format is useful when moving zonedata between providers, since the format is relatively universal. -This format is also useful for generating backups of DNS zones. Unlike -making a backup of the `dnsconfig.js`, this is the raw records, which -may be useful. +This format is also useful for generating backups of DNS zones. Unlike making a backup of the `dnsconfig.js`, this is the raw records, which may be useful. ## Use case 3: TAB separated values -The goal of `--format=tsv` is to provide a high-fidelity format that is easy -enough to parse with `awk`. +The goal of `--format=tsv` is to provide a high-fidelity format that is easy enough to parse with `awk`. ## Use case 4: List zones -If a provider supports it, `--format=nameonly` lists the names of the -zones at the provider. - +If a provider supports it, `--format=nameonly` lists the names of the zones at the provider. ## Syntax @@ -67,7 +48,7 @@ zone: One or more zones (domains) to download; or "all". As of [v3.16](../release/v316.md), `provider` can be `-` to indicate that the provider name is listed in `creds.json` in the `TYPE` field. Doing this will be backwards compatible with an (otherwise) breaking change due in v4.0. -As of v4.0 (BREAKING CHANGE), you must not specify `provider`. That value is found in the `TYPE` field of the credkey's `creds.json` file. For backwards compatibility, if the first `zone` is `-`, it will be skipped. +As of v4.0 (BREAKING CHANGE), you must not specify `provider`. That value is found in the `TYPE` field of the credkey's `creds.json` file. For backwards compatibility, if the first `zone` is `-`, it will be skipped. ```shell FORMATS: @@ -132,8 +113,7 @@ dnscontrol get-zones --format=tsv bind - example.com dnscontrol get-zones --format=djs --out=draft.js glcoud - example.com ``` -Read a zonefile, generate a JS file, then use the JS file to see how -different it is from the zonefile: +Read a zonefile, generate a JS file, then use the JS file to see how different it is from the zonefile: ```shell dnscontrol get-zone --format=djs -out=foo.djs bind - example.com @@ -169,27 +149,16 @@ Find the `GetZoneRecords` function in the `*Provider.go` file. It currently returns `fmt.Errorf("not implemented")`. -Instead, it should gather the records from the provider -and return them as a list of RecordConfig structs. +Instead, it should gather the records from the provider and return them as a list of RecordConfig structs. -The code to do that already exists in `GetDomainCorrections`. -You should extract it into its own function (`GetZoneRecords`), rather -than having it be buried in the middle of `GetDomainCorrections`. -`GetDomainCorrections` should call `GetZoneRecords`. +The code to do that already exists in `GetDomainCorrections`. You should extract it into its own function (`GetZoneRecords`), rather than having it be buried in the middle of `GetDomainCorrections`. `GetDomainCorrections` should call `GetZoneRecords`. Once that is done the `get-zone` subcommand should work. **Step 4. Optionally implement the `ListZones` function** -If the `ListZones` function is implemented, the "all" special case -will be activated. In this case, listing a single zone named `all` -will query the provider for the list of zones. +If the `ListZones` function is implemented, the "all" special case will be activated. In this case, listing a single zone named `all` will query the provider for the list of zones. -(Technically what is happening is by implementing the `ListZones` -function, you are completing the `ZoneLister` interface for that -provider.) +(Technically what is happening is by implementing the `ListZones` function, you are completing the `ZoneLister` interface for that provider.) -Implementing the `ListZones` function also activates the `check-creds` -subcommand for that provider. Please add to the provider documentation -a list of error messages that people might see if the credentials are -invalid. See `documentation/provider/gcloud.md` for examples. +Implementing the `ListZones` function also activates the `check-creds` subcommand for that provider. Please add to the provider documentation a list of error messages that people might see if the credentials are invalid. See `documentation/provider/gcloud.md` for examples. diff --git a/documentation/commands/preview-push.md b/documentation/commands/preview-push.md index ef784eea02..1401dca162 100644 --- a/documentation/commands/preview-push.md +++ b/documentation/commands/preview-push.md @@ -1,7 +1,6 @@ # preview/push -`preview` reads the dnsconfig.js file (or equivalent), determines what changes are to be made, and -prints them. `push` is the same but executes the changes. +`preview` reads the dnsconfig.js file (or equivalent), determines what changes are to be made, and prints them. `push` is the same but executes the changes. ```shell NAME: @@ -31,91 +30,56 @@ OPTIONS: ``` * `--config name` - * Specifies the name of the main configuration file, normally -`dnsconfig.js`. + * Specifies the name of the main configuration file, normally `dnsconfig.js`. * `--creds name` - * Specifies the name of the credentials file, normally `creds.json`. - Typically the file is read. If the executable bit is set, the file is - executed and the output is used as the configuration. See - [creds.json][creds-json.md] for details. + * Specifies the name of the credentials file, normally `creds.json`. Typically the file is read. If the executable bit is set, the file is executed and the output is used as the configuration. See [creds.json][creds-json.md] for details. * `--providers name,name2` - * Specifies a comma-separated list of providers to - enable. The default is all providers. A provider can opt out of being in the - default list by `"_exclude_from_defaults": "true"` to the credentials entry for - that provider. In that case, the provider will only be activated if it is - included in `--providers`. + * Specifies a comma-separated list of providers to enable. The default is all providers. A provider can opt out of being in the default list by `"_exclude_from_defaults": "true"` to the credentials entry for that provider. In that case, the provider will only be activated if it is included in `--providers`. * `--domains value` - * Specifies a comma-separated list of domains to include. - Example: `--domains example.com,myexample.net` - * Domains may include a wildcard at the beginning. - For example, `--domains example.com,*.in-addr.arpa` would include - `example.com` plus all IPv4 reverse lookup domains. - * Matching includes tags. If the domains are `example.com!foo` and - `example.com!bar`, then `--domains example.com!foo` would match the first - one, and `--domains example.com` will not match either. - * A wildcard tag is permitted and indicates all configured tags of that domain - should be selected. Example: `--domains=example.com!*` would match - `example.com!foo` and `example.com!bar` but not `example.com`. - * If `--domains` is not specified, the default is all domains. - * NOTE: An empty tag is considered equivalent to the untagged domain. - For example, `--domains=example.com!` will match `example.com` and `example.com!` + * Specifies a comma-separated list of domains to include. Example: `--domains example.com,myexample.net` + * Domains may include a wildcard at the beginning. For example, `--domains example.com,*.in-addr.arpa` would include `example.com` plus all IPv4 reverse lookup domains. + * Matching includes tags. If the domains are `example.com!foo` and `example.com!bar`, then `--domains example.com!foo` would match the first one, and `--domains example.com` will not match either. + * A wildcard tag is permitted and indicates all configured tags of that domain should be selected. Example: `--domains=example.com!*` would match `example.com!foo` and `example.com!bar` but not `example.com`. + * If `--domains` is not specified, the default is all domains. + * NOTE: An empty tag is considered equivalent to the untagged domain. For example, `--domains=example.com!` will match `example.com` and `example.com!` * `--v foo=bar` - * Sets the variable `foo` to the value `bar` prior to - interpreting the configuration file. Multiple `-v` options can be used. + * Sets the variable `foo` to the value `bar` prior to interpreting the configuration file. Multiple `-v` options can be used. * `--notify` - * Enables sending notifications to the destinations configured in `creds.json`. + * Enables sending notifications to the destinations configured in `creds.json`. * `--dev` - * Developer mode. Normally `helpers.js` is embedded in the dnscontrol - executable. With this flag, the local file `helpers.js` is read instead. + * Developer mode. Normally `helpers.js` is embedded in the dnscontrol executable. With this flag, the local file `helpers.js` is read instead. * `--expect-no-changes` - * If set, a non-zero exit code is returned if there are - changes. Normally DNSControl sets the exit code based on whether or not there - were protocol errors or other reasons the program can not continue. With this - flag set, the exit code indicates if any changes were required. This is - typically used with `preview` to allow scripts to determine if changes would - happen if `push` was used. For example, one might want to run `dnscontrol - preview --expect-no-changes` daily to determine if changes have been made to - a domain outside of DNSControl. + * If set, a non-zero exit code is returned if there are changes. Normally DNSControl sets the exit code based on whether or not there were protocol errors or other reasons the program can not continue. With this flag set, the exit code indicates if any changes were required. This is typically used with `preview` to allow scripts to determine if changes would happen if `push` was used. For example, one might want to run `dnscontrol preview --expect-no-changes` daily to determine if changes have been made to a domain outside of DNSControl. * `--no-populate` - * Do not auto-create non-existing zones at the provider. - Normally non-existent zones are automatically created at a provider (unless the - provider does not implement zone creation). This flag disables that feature. + * Do not auto-create non-existing zones at the provider. Normally non-existent zones are automatically created at a provider (unless the provider does not implement zone creation). This flag disables that feature. * `--full` - * Add headings, providers names, notifications of no changes, etc. to - the output. Normally the output of `preview`/`push` is extremely brief. This - makes the output more verbose. Useful for debugging. + * Add headings, providers names, notifications of no changes, etc. to the output. Normally the output of `preview`/`push` is extremely brief. This makes the output more verbose. Useful for debugging. * `--bindserial value` - * Force BIND serial numbers to this value. Normally the - BIND provider generates SOA serial numbers automatically. This flag forces the - serial number generator to output the value specified for all domains. This is - generally used for reproducibility in testing pipelines. + * Force BIND serial numbers to this value. Normally the BIND provider generates SOA serial numbers automatically. This flag forces the serial number generator to output the value specified for all domains. This is generally used for reproducibility in testing pipelines. * `--cmode value` - * Concurrency mode. See below. + * Concurrency mode. See below. * `--report name` - * Write a machine-parseable report of - corrections to the file named `name`. If no name is specified, no - report is generated. See [JSON Reports](../advanced-features/json-reports.md) + * Write a machine-parseable report of corrections to the file named `name`. If no name is specified, no report is generated. See [JSON Reports](../advanced-features/json-reports.md) ## cmode -The `preview`/`push` commands begin with a data-gathering phase that collects current configuration -from providers and zones. This collection can be done sequentially or concurrently. Concurrently is significantly faster. However since concurrent mode is newer, not all providers have been tested and certified as being compatible with this mode. Therefore the `--cmode` flag can be used to control concurrency. +The `preview`/`push` commands begin with a data-gathering phase that collects current configuration from providers and zones. This collection can be done sequentially or concurrently. Concurrently is significantly faster. However since concurrent mode is newer, not all providers have been tested and certified as being compatible with this mode. Therefore the `--cmode` flag can be used to control concurrency. The `--cmode` value may be one of the following: -* `legacy` -- Use the older, sequential code. All data is gathered sequentially. This option is removed as of release v4.16. +* `legacy` -- Use the older, sequential code. All data is gathered sequentially. This option is removed as of release v4.16. * `concurrent` -- Gathering is done either sequentially or concurrently depending on whether the provider is marked as having been tested to run concurrently. * `none` -- All providers are run sequentially. This is the safest mode. It can be used if a concurrency bug is discovered. * `all` -- This is unsafe. It runs all providers concurrently, even the ones that have not be validated to run concurrently. It is generally only used for demonstrating bugs. diff --git a/documentation/getting-started/getting-started.md b/documentation/getting-started/getting-started.md index 2ab94a0344..d2722b0b5d 100644 --- a/documentation/getting-started/getting-started.md +++ b/documentation/getting-started/getting-started.md @@ -1,6 +1,5 @@ # Getting Started - ## 1. Install the software Choose one of the following installation methods: @@ -34,8 +33,7 @@ Download binaries from [GitHub](https://github.com/DNSControl/dnscontrol/release DNSControl can be built from source with Go version 1.18 or higher. -The `go install` command will download the source, compile it, and -install `dnscontrol` in your `$GOBIN` directory. +The `go install` command will download the source, compile it, and install `dnscontrol` in your `$GOBIN` directory. To install, simply run @@ -59,8 +57,7 @@ Shell completion is available for `zsh` and `bash`. Add `eval "$(dnscontrol shell-completion zsh)"` to your `~/.zshrc` file. -This requires completion to be enabled in zsh. A good tutorial for this is available at -[The Valuable Dev](https://thevaluable.dev/zsh-completion-guide-examples/) [[archived](https://web.archive.org/web/20231015083946/https://thevaluable.dev/zsh-completion-guide-examples/)]. +This requires completion to be enabled in zsh. A good tutorial for this is available at [The Valuable Dev](https://thevaluable.dev/zsh-completion-guide-examples/) [[archived](https://web.archive.org/web/20231015083946/https://thevaluable.dev/zsh-completion-guide-examples/)]. ### bash @@ -70,24 +67,15 @@ This requires the `bash-completion` package to be installed. See [scop/bash-comp ## 2. Create a place for the config files -Create a directory where you'll store your configuration files. -We highly recommend storing these files in a Git repo, but for -simple tests anything will do. - -Create a subdirectory called `zones` in the same directory as the -configuration files. (`mkdir zones`). `zones` is where the BIND -provider writes the zonefiles it creates. Even if you don't -use BIND for DNS service, it is useful for testing. +Create a directory where you'll store your configuration files. We highly recommend storing these files in a Git repo, but for simple tests anything will do. +Create a subdirectory called `zones` in the same directory as the configuration files. (`mkdir zones`). `zones` is where the BIND provider writes the zonefiles it creates. Even if you don't use BIND for DNS service, it is useful for testing. ## 3. Create the initial `dnsconfig.js` -`dnsconfig.js` is the main configuration and defines providers, DNS -domains, and so on. +`dnsconfig.js` is the main configuration and defines providers, DNS domains, and so on. -Start your `dnsconfig.js` file by downloading -[dnsconfig.js](https://github.com/DNSControl/dnscontrol/blob/main/documentation/assets/getting-started/dnsconfig.js) -and renaming it. +Start your `dnsconfig.js` file by downloading [dnsconfig.js](https://github.com/DNSControl/dnscontrol/blob/main/documentation/assets/getting-started/dnsconfig.js) and renaming it. The file looks like: @@ -104,8 +92,7 @@ D("example.com", REG_NONE, DnsProvider(DNS_BIND), Modify this file to match your particular providers and domains. See [the DNSConfig docs](../language-reference/js.md) and [the provider docs](../provider/index.md) for more details. -Create a file called `creds.json` for storing provider configurations (API tokens and other account information). -For example, to use both name.com and Cloudflare, you would have: +Create a file called `creds.json` for storing provider configurations (API tokens and other account information). For example, to use both name.com and Cloudflare, you would have: {% code title="creds.json" %} ```json @@ -125,34 +112,19 @@ For example, to use both name.com and Cloudflare, you would have: ``` {% endcode %} -Note: Do **not** store your `creds.json` file in Git unencrypted. -That is unsafe. Add `creds.json` to your -`.gitignore` file as a precaution. This file should be encrypted -using something -like [git-crypt](https://www.agwa.name/projects/git-crypt). +Note: Do **not** store your `creds.json` file in Git unencrypted. That is unsafe. Add `creds.json` to your `.gitignore` file as a precaution. This file should be encrypted using something like [git-crypt](https://www.agwa.name/projects/git-crypt). There are 2 types of providers: -A "Registrar" is with whom you register the domain. Start with -`NONE`, which is a provider that never talks to or updates the -registrar. You can define your registrar later when you want to -use advanced features. - -A "DnsProvider" is the service that actually provides DNS service -(port 53) and may be the same or a different registrar. Even if both -your Registrar and DnsProvider are the same company, two different -definitions must be included in `dnsconfig.js`. +A "Registrar" is with whom you register the domain. Start with `NONE`, which is a provider that never talks to or updates the registrar. You can define your registrar later when you want to use advanced features. +A "DnsProvider" is the service that actually provides DNS service (port 53) and may be the same or a different registrar. Even if both your Registrar and DnsProvider are the same company, two different definitions must be included in `dnsconfig.js`. ## 4. Create the initial `creds.json` -`creds.json` stores credentials and a few global settings. -It is only needed if any providers require credentials (API keys, -usernames, passwords, etc.). +`creds.json` stores credentials and a few global settings. It is only needed if any providers require credentials (API keys, usernames, passwords, etc.). -Start your `creds.json` file by downloading -[creds.json](https://github.com/DNSControl/dnscontrol/blob/main/documentation/assets/getting-started/creds.json) -and renaming it. +Start your `creds.json` file by downloading [creds.json](https://github.com/DNSControl/dnscontrol/blob/main/documentation/assets/getting-started/creds.json) and renaming it. The file looks like: @@ -171,11 +143,9 @@ The file looks like: ``` {% endcode %} -Ignore the `r53_accountname` section. It is a placeholder and will be ignored. You -can use it later when you define your first set of API credentials. +Ignore the `r53_accountname` section. It is a placeholder and will be ignored. You can use it later when you define your first set of API credentials. -Note that `creds.json` is a JSON file. JSON is very strict about commas -and other formatting. There are a few different ways to check for typos: +Note that `creds.json` is a JSON file. JSON is very strict about commas and other formatting. There are a few different ways to check for typos: Python: @@ -203,11 +173,7 @@ FYI: `creds.json` fields can be read from an environment variable. The field mus Before you edit the sample files, verify that the system is working. -First run `dnscontrol preview` and ensure it completes without -error(s). The preview command is the "dry run" mode that shows only -what changes need to be made and never makes any actual changes. -It will use APIs if needed to find out what DNS entries currently -exist. +First run `dnscontrol preview` and ensure it completes without error(s). The preview command is the "dry run" mode that shows only what changes need to be made and never makes any actual changes. It will use APIs if needed to find out what DNS entries currently exist. (All output assumes the `--full` flag) @@ -228,9 +194,7 @@ Initialized 1 registrars and 1 dns service providers. Done. 1 corrections. ``` -Next, run `dnscontrol push` to actually make the changes. In this -case, the change will be to create a zone file where one didn't -previously exist. +Next, run `dnscontrol push` to actually make the changes. In this case, the change will be to create a zone file where one didn't previously exist. {% hint style="warn" %} **Nervous?** The first "push" can be nervous-making. How to migrate a zone @@ -257,14 +221,11 @@ SUCCESS! Done. 1 corrections. ``` - ## 6. Make a change -Try making a change to `dnsconfig.js`. For example, change the IP -address of in `A("@", "1.2.3.4")` or add an additional A record. +Try making a change to `dnsconfig.js`. For example, change the IP address of in `A("@", "1.2.3.4")` or add an additional A record. -In our case, we changed the IP address to 10.10.10.10. Previewing -our change looks like this: +In our case, we changed the IP address to 10.10.10.10. Previewing our change looks like this: ```shell dnscontrol preview @@ -281,19 +242,13 @@ MODIFY A example.com: (1.2.3.4 300) -> (10.10.10.10 300) Done. 1 corrections. ``` -Notice that it read the old zone file and was able to produce a -"diff" between the old `A` record and the new one. If the zonefile -didn't exist, the output would look different because the zone file -was being created from scratch. +Notice that it read the old zone file and was able to produce a "diff" between the old `A` record and the new one. If the zonefile didn't exist, the output would look different because the zone file was being created from scratch. Run `dnscontrol push` to see the system generate a new zone file. -Other providers use an API to do updates. In those cases the -individual changes will translate into API calls that update the -specific records. +Other providers use an API to do updates. In those cases the individual changes will translate into API calls that update the specific records. -Take a look at the `zones/example.com.zone` file. It should look -like: +Take a look at the `zones/example.com.zone` file. It should look like: ```text $TTL 300 @@ -301,38 +256,19 @@ $TTL 300 IN A 10.10.10.10 ``` -You can change the "DEFAULT_NOT_SET" text by following the documentation -for the [BIND provider](../provider/bind.md) to set -the "master" and "mbox" settings. Try that now. - +You can change the "DEFAULT_NOT_SET" text by following the documentation for the [BIND provider](../provider/bind.md) to set the "master" and "mbox" settings. Try that now. ## 7. Use your own domains -Now that we know the system is working for test data, try controlling -a real domain (or a test domain if you have one). +Now that we know the system is working for test data, try controlling a real domain (or a test domain if you have one). -Set up the provider: Add the providers's definition to `dnsconfig.js` -and list any credentials in `creds.json`. Each provider is different. -See [the provider docs](../provider/index.md) for -specifics. +Set up the provider: Add the providers's definition to `dnsconfig.js` and list any credentials in `creds.json`. Each provider is different. See [the provider docs](../provider/index.md) for specifics. -Edit the domain: Add the `D()` entry for the domain, or repurpose -the `example.com` domain. Add individual `A()`, `MX()` and other -records as needed. Remember that the first parameter to `D()` is -always a Registrar. +Edit the domain: Add the `D()` entry for the domain, or repurpose the `example.com` domain. Add individual `A()`, `MX()` and other records as needed. Remember that the first parameter to `D()` is always a Registrar. -Run `dnscontrol preview` to test your work. It may take a few tries -to list all the DNS records that make up the domain. When `preview` -shows no changes required, then you know you are at record parity. +Run `dnscontrol preview` to test your work. It may take a few tries to list all the DNS records that make up the domain. When `preview` shows no changes required, then you know you are at record parity. -The [Migrating](migrating.md) doc has advice -about converting from other systems. -You can manually create the `D()` statements, or you can -generate them automatically using the -[dnscontrol get-zones](../commands/get-zones.md) -command to import the zone from (most) providers and output it as code -that can be added to `dnsconfig.js` and used with very little -modification. +The [Migrating](migrating.md) doc has advice about converting from other systems. You can manually create the `D()` statements, or you can generate them automatically using the [dnscontrol get-zones](../commands/get-zones.md) command to import the zone from (most) providers and output it as code that can be added to `dnsconfig.js` and used with very little modification. Now you can make changes to the domain(s) and run `dnscontrol preview` @@ -347,7 +283,6 @@ on how it can be improved. If you are going to use this in production, we highly recommend the following: * Store the configuration files in Git. -* Encrypt the `creds.json` file before storing it in Git. Do NOT store - API keys or other credentials without encrypting them. +* Encrypt the `creds.json` file before storing it in Git. Do NOT store API keys or other credentials without encrypting them. * Use a CI/CD tool like [GitLab](../advanced-features/ci-cd-gitlab.md), Jenkins, CircleCI, [GitHub Actions](https://github.com/DNSControl/dnscontrol#via-github-actions-gha), etc. to automatically push DNS changes. * Join the DNSControl community. File [issues](https://github.com/DNSControl/dnscontrol/issues) and [PRs](https://github.com/DNSControl/dnscontrol/pulls). diff --git a/documentation/getting-started/migrating.md b/documentation/getting-started/migrating.md index ddd331b96c..695974422d 100644 --- a/documentation/getting-started/migrating.md +++ b/documentation/getting-started/migrating.md @@ -1,50 +1,24 @@ # Migrating zones to DNSControl -This document explains how to migrate (convert) DNS zones from -other systems to DNSControl's `dnsconfig.js` file. +This document explains how to migrate (convert) DNS zones from other systems to DNSControl's `dnsconfig.js` file. -This document assumes you have DNSControl set up and working on at -least one zone. You should have a working `dnsconfig.js` file and -`creds.json` file as explained in the -[Getting Started](getting-started.md) doc. +This document assumes you have DNSControl set up and working on at least one zone. You should have a working `dnsconfig.js` file and `creds.json` file as explained in the [Getting Started](getting-started.md) doc. ## General advice -First, use the -[Getting Started](getting-started.md) doc -so that you have a working `dnsconfig.js` with at least one domain. +First, use the [Getting Started](getting-started.md) doc so that you have a working `dnsconfig.js` with at least one domain. -We recommend migrating one zone at a time. Start with a small, -non-critical, zone first to learn the process. Convert larger, -more important, zones as you gain confidence. +We recommend migrating one zone at a time. Start with a small, non-critical, zone first to learn the process. Convert larger, more important, zones as you gain confidence. -Experience has taught us that the best way to migrate a zone is -to create an exact duplicate first. That is, convert the old DNS records -with no changes. It is tempting to clean up the data as you do the migration... -removing that old CNAME that nobody uses any more, or adding an -A record you discovered was missing. Resist that temptation. If you make any -changes it will be difficult to tell which changes were intentional -and which are mistakes. During the migration you will know you are done -when `dnscontrol preview` says there are no changes needed. At that -point it is safe to do any cleanups. +Experience has taught us that the best way to migrate a zone is to create an exact duplicate first. That is, convert the old DNS records with no changes. It is tempting to clean up the data as you do the migration... removing that old CNAME that nobody uses any more, or adding an A record you discovered was missing. Resist that temptation. If you make any changes it will be difficult to tell which changes were intentional and which are mistakes. During the migration you will know you are done when `dnscontrol preview` says there are no changes needed. At that point it is safe to do any cleanups. ## Create the first draft -Create the first draft of the `D()` statement either manually or -automatically. +Create the first draft of the `D()` statement either manually or automatically. -For a small domain you can probably create the `D()` statements by -hand, possibly with your text editor's search and replace functions. -However, where's the fun in that? +For a small domain you can probably create the `D()` statements by hand, possibly with your text editor's search and replace functions. However, where's the fun in that? -The `dnscontrol get-zones` subcommand -[documented here](../commands/get-zones.md) -can automate 90% of the conversion for you. It reads BIND-style zonefiles, -or will use a providers API to gather the DNS records. It will then output -the records in a variety of formats, including as a `D()` statement -that is usually fairly complete. You may need to touch it up a bit, -especially if you use pseudo record types in one provider that are -not supported by another. +The `dnscontrol get-zones` subcommand [documented here](../commands/get-zones.md) can automate 90% of the conversion for you. It reads BIND-style zonefiles, or will use a providers API to gather the DNS records. It will then output the records in a variety of formats, including as a `D()` statement that is usually fairly complete. You may need to touch it up a bit, especially if you use pseudo record types in one provider that are not supported by another. Example 1: Read a BIND zonefile @@ -55,19 +29,15 @@ dnscontrol get-zones --format=js bind BIND example.com dnscontrol get-zones --format=js --out=draft.js bind BIND example.com ``` -This will read the file `zones/example.com.zone`. By default the system -uses directory `zones` and file suffix `.zone`. You can modify this default -behaviour by configuring `creds.json` for BIND as described [here](../provider/bind.md). +This will read the file `zones/example.com.zone`. By default the system uses directory `zones` and file suffix `.zone`. You can modify this default behaviour by configuring `creds.json` for BIND as described [here](../provider/bind.md). Add the contents of `draft.js` to `dnsconfig.js` and edit it as needed. Example 2: Read from a provider -This requires creating a `creds.json` file as described in -[Getting Started](getting-started.md). +This requires creating a `creds.json` file as described in [Getting Started](getting-started.md). -Suppose your `creds.json` file has the name `global_aws` -for the provider `ROUTE53`. Your command would look like this: +Suppose your `creds.json` file has the name `global_aws` for the provider `ROUTE53`. Your command would look like this: ```shell dnscontrol get-zones --format=js global_aws ROUTE53 example.com @@ -76,31 +46,17 @@ dnscontrol get-zones --format=js --out=draft.js global_aws ROUTE53 example.com Add the contents of `draft.js` to `dnsconfig.js` and edit it as needed. -Run `dnscontrol preview` and see if it finds any differences. -Edit dnsconfig.js until `dnscontrol preview` shows no errors and -no changes to be made. This means the conversion of your old DNS -data is correct. +Run `dnscontrol preview` and see if it finds any differences. Edit dnsconfig.js until `dnscontrol preview` shows no errors and no changes to be made. This means the conversion of your old DNS data is correct. -`dnscontrol get-zones` makes a guess at what to do with NS records. -An NS record at the apex is turned into a NAMESERVER() call, the -rest are left as NS(). You probably want to check each of them for -correctness. +`dnscontrol get-zones` makes a guess at what to do with NS records. An NS record at the apex is turned into a NAMESERVER() call, the rest are left as NS(). You probably want to check each of them for correctness. -Resist the temptation to clean up and old, obsolete, records or to -add anything new. Experience has shown that making changes at this -time leads to unhappy surprises, and people will blame DNSControl. -Of course, once `dnscontrol preview` runs cleanly, you can do any -kind of cleanups you want. In fact, they should be easier to do -now that you are using DNSControl! +Resist the temptation to clean up and old, obsolete, records or to add anything new. Experience has shown that making changes at this time leads to unhappy surprises, and people will blame DNSControl. Of course, once `dnscontrol preview` runs cleanly, you can do any kind of cleanups you want. In fact, they should be easier to do now that you are using DNSControl! -If `dnscontrol get-zones` could have done a better job, please -[let us know](https://github.com/DNSControl/dnscontrol/issues)! +If `dnscontrol get-zones` could have done a better job, please [let us know](https://github.com/DNSControl/dnscontrol/issues)! ## Example workflow -Here is an example series of commands that would be used -to convert a zone. Lines that start with `#` are comments. - +Here is an example series of commands that would be used to convert a zone. Lines that start with `#` are comments. ```shell # Note this command uses ">>" to append to dnsconfig.js. Do not use ">" as that will erase the existing file. @@ -110,14 +66,12 @@ dnscontrol preview vim dnsconfig.js ``` -Repeat these two commands until all warnings/errors are resolved. -When everything is as you wish, push the changes live: +Repeat these two commands until all warnings/errors are resolved. When everything is as you wish, push the changes live: ```shell dnscontrol push ``` - Make any changes you do desire: ```shell diff --git a/documentation/getting-started/typescript.md b/documentation/getting-started/typescript.md index b84aa3e4b6..16350e1577 100644 --- a/documentation/getting-started/typescript.md +++ b/documentation/getting-started/typescript.md @@ -2,16 +2,11 @@ ## What is this? -Would you like your editor to support auto-completion and other advanced IDE -features when editing `dnsconfig.js`? Yes you can! +Would you like your editor to support auto-completion and other advanced IDE features when editing `dnsconfig.js`? Yes you can! -While DNSControl does not support TypeScript syntax in `dnsconfig.js`, you can -still use TypeScript’s features in editors which support it. +While DNSControl does not support TypeScript syntax in `dnsconfig.js`, you can still use TypeScript’s features in editors which support it. -If you’re using Visual Studio Code (or another editor that supports TypeScript), you -should now be able to see the type information in your `dnsconfig.js` file as -you type. Hover over record names to read their documentation without having to -open the documentation website! +If you’re using Visual Studio Code (or another editor that supports TypeScript), you should now be able to see the type information in your `dnsconfig.js` file as you type. Hover over record names to read their documentation without having to open the documentation website! ## How to activate auto-completion @@ -33,8 +28,7 @@ for the version of DNSControl you are using. 2. Tell your editor -At this point some features (autocomplete) will work. However to get the full experience, including -type checking (i.e. red squiggly underlines when you misuse APIs), there is one more step. +At this point some features (autocomplete) will work. However to get the full experience, including type checking (i.e. red squiggly underlines when you misuse APIs), there is one more step. Add these comments to the top of your `dnsconfig.js` file: @@ -45,7 +39,6 @@ Add these comments to the top of your `dnsconfig.js` file: ``` {% endcode %} - That should be all you need to do! If your editor requires extra steps, please [file a bug](https://github.com/DNSControl/dnscontrol/issues) and we'll update this page. @@ -126,7 +119,6 @@ declare const VARIABLE_NAME: string; ``` {% endcode %} - This will tell TypeScript that the variable exists, and that it’s a string. ### Known issue: `FETCH` not always accurate diff --git a/documentation/language-reference/domain-modifiers/AUTODNSSEC_ON.md b/documentation/language-reference/domain-modifiers/AUTODNSSEC_ON.md index df04516ab9..006bd813a9 100644 --- a/documentation/language-reference/domain-modifiers/AUTODNSSEC_ON.md +++ b/documentation/language-reference/domain-modifiers/AUTODNSSEC_ON.md @@ -6,13 +6,9 @@ name: AUTODNSSEC_ON [`AUTODNSSEC_OFF`](AUTODNSSEC_OFF.md) tells the provider to **disable** AutoDNSSEC. -AutoDNSSEC is a feature where a DNS provider can automatically manage -DNSSEC for a domain. Not all providers support this. +AutoDNSSEC is a feature where a DNS provider can automatically manage DNSSEC for a domain. Not all providers support this. -At this time, `AUTODNSSEC_ON` takes no parameters. There is no ability -to tune what the DNS provider sets, no algorithm choice. We simply -ask that they follow their defaults when enabling a no-fuss DNSSEC -data model. +At this time, `AUTODNSSEC_ON` takes no parameters. There is no ability to tune what the DNS provider sets, no algorithm choice. We simply ask that they follow their defaults when enabling a no-fuss DNSSEC data model. {% hint style="info" %} **NOTE**: No parenthesis should follow these keywords. That is, the @@ -33,5 +29,4 @@ D("insecure.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), ``` {% endcode %} -If neither `AUTODNSSEC_ON` or `AUTODNSSEC_OFF` is specified for a -domain no changes will be requested. +If neither `AUTODNSSEC_ON` or `AUTODNSSEC_OFF` is specified for a domain no changes will be requested. diff --git a/documentation/language-reference/domain-modifiers/CF_REDIRECT.md b/documentation/language-reference/domain-modifiers/CF_REDIRECT.md index b087d4f08c..aba8182397 100644 --- a/documentation/language-reference/domain-modifiers/CF_REDIRECT.md +++ b/documentation/language-reference/domain-modifiers/CF_REDIRECT.md @@ -18,12 +18,9 @@ generate "Dynamic Single Redirects" for a limited number of use cases. See [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md) for details. {% endhint %} -`CF_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page -Rules) to generate a HTTP 301 permanent redirect. +`CF_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page Rules) to generate a HTTP 301 permanent redirect. -If _any_ `CF_REDIRECT` or [`CF_TEMP_REDIRECT`](CF_TEMP_REDIRECT.md) functions are used then -`dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. -Page Rule types other than "Forwarding URL" will be left alone. +If _any_ `CF_REDIRECT` or [`CF_TEMP_REDIRECT`](CF_TEMP_REDIRECT.md) functions are used then `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. Page Rule types other than "Forwarding URL" will be left alone. {% hint style="warning" %} **WARNING**: Cloudflare does not currently fully document the Page Rules API and @@ -33,10 +30,7 @@ backups and manually verifying `dnscontrol preview` output before running managed by DNSControl and those that aren't. {% endhint %} -HTTP 301 redirects are cached by browsers forever, usually ignoring any TTLs or -other cache invalidation techniques. It should be used with great care. We -suggest using a `CF_TEMP_REDIRECT` initially, then changing to a `CF_REDIRECT` -only after sufficient time has elapsed to prove this is what you really want. +HTTP 301 redirects are cached by browsers forever, usually ignoring any TTLs or other cache invalidation techniques. It should be used with great care. We suggest using a `CF_TEMP_REDIRECT` initially, then changing to a `CF_REDIRECT` only after sufficient time has elapsed to prove this is what you really want. This example redirects the bare (aka apex, or naked) domain to www: diff --git a/documentation/language-reference/domain-modifiers/CF_SINGLE_REDIRECT.md b/documentation/language-reference/domain-modifiers/CF_SINGLE_REDIRECT.md index a1fe7e9988..40f5bf2ee8 100644 --- a/documentation/language-reference/domain-modifiers/CF_SINGLE_REDIRECT.md +++ b/documentation/language-reference/domain-modifiers/CF_SINGLE_REDIRECT.md @@ -15,11 +15,9 @@ parameter_types: "modifiers...": RecordModifier[] --- -`CF_SINGLE_REDIRECT` is a [Cloudflare](../../provider/cloudflareapi.md)-specific feature for creating HTTP redirects. 301, 302, 303, 307, 308 are supported. -Typically one uses 302 (temporary) or 301 (permanent). +`CF_SINGLE_REDIRECT` is a [Cloudflare](../../provider/cloudflareapi.md)-specific feature for creating HTTP redirects. 301, 302, 303, 307, 308 are supported. Typically one uses 302 (temporary) or 301 (permanent). -This feature manages dynamic "Single Redirects". (Single Redirects can be -static or dynamic but DNSControl only maintains dynamic redirects). +This feature manages dynamic "Single Redirects". (Single Redirects can be static or dynamic but DNSControl only maintains dynamic redirects). DNSControl will delete any "single redirects" it doesn't recognize (i.e. ones created via the web UI) so please be careful. @@ -42,16 +40,8 @@ The fields are: * when: What Cloudflare sometimes calls the "rule expression". * then: The replacement expression. -DNSControl does not currently choose the order of the rules. New rules are -added to the end of the list. Use Cloudflare's dashboard to re-order the rule, -DNSControl should not change them. (In the future we hope to add a feature -where the order the rules appear in dnsconfig.js is maintained in the -dashboard.) +DNSControl does not currently choose the order of the rules. New rules are added to the end of the list. Use Cloudflare's dashboard to re-order the rule, DNSControl should not change them. (In the future we hope to add a feature where the order the rules appear in dnsconfig.js is maintained in the dashboard.) ## `CF_REDIRECT` and `CF_TEMP_REDIRECT` -`CF_REDIRECT` and `CF_TEMP_REDIRECT` used to manage Cloudflare Page Rules. -However that feature is going away. To help with the migration, DNSControl now -translates those commands into CF_SINGLE_REDIRECT equivalents. The conversion -process is a transpiler that only understands certain formats. Please submit -a Github issue if you find something it can't handle. +`CF_REDIRECT` and `CF_TEMP_REDIRECT` used to manage Cloudflare Page Rules. However that feature is going away. To help with the migration, DNSControl now translates those commands into CF_SINGLE_REDIRECT equivalents. The conversion process is a transpiler that only understands certain formats. Please submit a Github issue if you find something it can't handle. diff --git a/documentation/language-reference/domain-modifiers/CF_TEMP_REDIRECT.md b/documentation/language-reference/domain-modifiers/CF_TEMP_REDIRECT.md index 347f90cee4..c613ffb839 100644 --- a/documentation/language-reference/domain-modifiers/CF_TEMP_REDIRECT.md +++ b/documentation/language-reference/domain-modifiers/CF_TEMP_REDIRECT.md @@ -18,12 +18,9 @@ generate "Dynamic Single Redirects" for a limited number of use cases. See [`CLOUDFLAREAPI`](../../provider/cloudflareapi.md) for details. {% endhint %} -`CF_TEMP_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page -Rules) to generate a HTTP 302 temporary redirect. +`CF_TEMP_REDIRECT` uses [Cloudflare](../../provider/cloudflareapi.md)-specific features ("Forwarding URL" Page Rules) to generate a HTTP 302 temporary redirect. -If _any_ [`CF_REDIRECT`](CF_REDIRECT.md) or `CF_TEMP_REDIRECT functions are used then -`dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. -Page Rule types other than "Forwarding URL" will be left alone. +If _any_ [`CF_REDIRECT`](CF_REDIRECT.md) or `CF_TEMP_REDIRECT functions are used then `dnscontrol` will manage _all_ "Forwarding URL" type Page Rules for the domain. Page Rule types other than "Forwarding URL" will be left alone. {% hint style="warning" %} **WARNING**: Cloudflare does not currently fully document the Page Rules API and diff --git a/documentation/language-reference/domain-modifiers/CF_WORKER_ROUTE.md b/documentation/language-reference/domain-modifiers/CF_WORKER_ROUTE.md index 7515742745..e05d6d1ef1 100644 --- a/documentation/language-reference/domain-modifiers/CF_WORKER_ROUTE.md +++ b/documentation/language-reference/domain-modifiers/CF_WORKER_ROUTE.md @@ -9,13 +9,9 @@ parameter_types: provider: CLOUDFLAREAPI --- -`CF_WORKER_ROUTE` uses the [Cloudflare Workers](https://developers.cloudflare.com/workers/) -API to manage [worker routes](https://developers.cloudflare.com/workers/platform/routes) -for a given domain. +`CF_WORKER_ROUTE` uses the [Cloudflare Workers](https://developers.cloudflare.com/workers/) API to manage [worker routes](https://developers.cloudflare.com/workers/platform/routes) for a given domain. -If _any_ `CF_WORKER_ROUTE` function is used then `dnscontrol` will manage _all_ -Worker Routes for the domain. To be clear: this means it will delete existing routes that -were created outside of DNSControl. +If _any_ `CF_WORKER_ROUTE` function is used then `dnscontrol` will manage _all_ Worker Routes for the domain. To be clear: this means it will delete existing routes that were created outside of DNSControl. {% hint style="warning" %} **WARNING**: This interface is not extensively tested. Take precautions such as making diff --git a/documentation/language-reference/domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md b/documentation/language-reference/domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md index 3ee2869600..9bb021d761 100644 --- a/documentation/language-reference/domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md +++ b/documentation/language-reference/domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md @@ -2,12 +2,9 @@ name: DISABLE_IGNORE_SAFETY_CHECK --- -`DISABLE_IGNORE_SAFETY_CHECK` disables the safety check. Normally it is an -error to insert records that match an `IGNORE` pattern. This disables that -safety check for the entire domain. +`DISABLE_IGNORE_SAFETY_CHECK` disables the safety check. Normally it is an error to insert records that match an `IGNORE` pattern. This disables that safety check for the entire domain. -It replaces the per-record `IGNORE_NAME_DISABLE_SAFETY_CHECK` which is -deprecated as of DNSControl v4.0.0.0. +It replaces the per-record `IGNORE_NAME_DISABLE_SAFETY_CHECK` which is deprecated as of DNSControl v4.0.0.0. See [`IGNORE`](../domain-modifiers/IGNORE.md) for more information. diff --git a/documentation/language-reference/domain-modifiers/DnsProvider.md b/documentation/language-reference/domain-modifiers/DnsProvider.md index fe6def9f38..711a77b37e 100644 --- a/documentation/language-reference/domain-modifiers/DnsProvider.md +++ b/documentation/language-reference/domain-modifiers/DnsProvider.md @@ -8,8 +8,7 @@ parameter_types: nsCount: number? --- -DnsProvider indicates that the specified provider should be used to manage -records for this domain. The name must match the name used with [NewDnsProvider](../top-level-functions/NewDnsProvider.md). +DnsProvider indicates that the specified provider should be used to manage records for this domain. The name must match the name used with [NewDnsProvider](../top-level-functions/NewDnsProvider.md). The nsCount parameter determines how the nameservers will be managed from this provider. @@ -17,12 +16,8 @@ Leaving the parameter out means "fetch and use all nameservers from this provide Using `0` for nsCount means "do not fetch nameservers from this domain, or give them to the registrar". -Using a different number, ie: `DnsProvider("name",2)`, means "fetch all nameservers from this provider, -but limit it to this many. +Using a different number, ie: `DnsProvider("name",2)`, means "fetch all nameservers from this provider, but limit it to this many. See [this page](../../advanced-features/nameservers.md) for a detailed explanation of how DNSControl handles nameservers and NS records. -If a domain (`D()`) does not include any `DnsProvider()` functions, -the DNS records will not be modified. In fact, if you want to control -the Registrar for a domain but not the DNS records themselves, simply -do not include a `DnsProvider()` function for that `D()`. +If a domain (`D()`) does not include any `DnsProvider()` functions, the DNS records will not be modified. In fact, if you want to control the Registrar for a domain but not the DNS records themselves, simply do not include a `DnsProvider()` function for that `D()`. diff --git a/documentation/language-reference/domain-modifiers/IGNORE.md b/documentation/language-reference/domain-modifiers/IGNORE.md index ccd9258c26..00b7939388 100644 --- a/documentation/language-reference/domain-modifiers/IGNORE.md +++ b/documentation/language-reference/domain-modifiers/IGNORE.md @@ -10,27 +10,15 @@ parameter_types: targetSpec: string? --- -`IGNORE()` makes it possible for DNSControl to share management of a domain -with an external system. The parameters of `IGNORE()` indicate which records -are managed elsewhere and should not be modified or deleted. +`IGNORE()` makes it possible for DNSControl to share management of a domain with an external system. The parameters of `IGNORE()` indicate which records are managed elsewhere and should not be modified or deleted. -Use case: Suppose a domain is managed by both DNSControl and a third-party -system. This creates a problem because DNSControl will try to delete records -inserted by the other system. The other system may get confused and re-insert -those records. The two systems will get into an endless update cycle where -each will revert changes made by the other in an endless loop. +Use case: Suppose a domain is managed by both DNSControl and a third-party system. This creates a problem because DNSControl will try to delete records inserted by the other system. The other system may get confused and re-insert those records. The two systems will get into an endless update cycle where each will revert changes made by the other in an endless loop. -To solve this problem simply include `IGNORE()` statements that identify which -records are managed elsewhere. DNSControl will not modify or delete those -records. +To solve this problem simply include `IGNORE()` statements that identify which records are managed elsewhere. DNSControl will not modify or delete those records. -Technically `IGNORE_NAME` is a promise that DNSControl will not modify or -delete existing records that match particular patterns. It is like -[`NO_PURGE`](../domain-modifiers/NO_PURGE.md) that matches only specific records. +Technically `IGNORE_NAME` is a promise that DNSControl will not modify or delete existing records that match particular patterns. It is like [`NO_PURGE`](../domain-modifiers/NO_PURGE.md) that matches only specific records. -Including a record that is ignored is considered an error and may have -undefined behavior. This safety check can be disabled using the -[`DISABLE_IGNORE_SAFETY_CHECK`](../domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md) feature. +Including a record that is ignored is considered an error and may have undefined behavior. This safety check can be disabled using the [`DISABLE_IGNORE_SAFETY_CHECK`](../domain-modifiers/DISABLE_IGNORE_SAFETY_CHECK.md) feature. ## Syntax @@ -54,9 +42,7 @@ D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), ## Globs -The `labelSpec` and `targetSpec` parameters supports glob patterns in the style -of the [gobwas/glob](https://github.com/gobwas/glob) library. All of the -following patterns will work: +The `labelSpec` and `targetSpec` parameters supports glob patterns in the style of the [gobwas/glob](https://github.com/gobwas/glob) library. All of the following patterns will work: * `IGNORE("*.foo")` will ignore all records in the style of `bar.foo`, but will not ignore records using a double subdomain, such as `foo.bar.foo`. * `IGNORE("**.foo")` will ignore all subdomains of `foo`, including double subdomains. @@ -124,9 +110,7 @@ D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), Here are some examples that illustrate how matching works. -All the examples assume the following DNS records are the "existing" records -that a third-party is maintaining. (Don't be confused by the fact that we're -using DNSControl notation for the records. Pretend some other system inserted them.) +All the examples assume the following DNS records are the "existing" records that a third-party is maintaining. (Don't be confused by the fact that we're using DNSControl notation for the records. Pretend some other system inserted them.) {% code title="dnsconfig.js" %} ```javascript @@ -303,8 +287,7 @@ D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), ## Conflict handling -It is considered as an error for a `dnsconfig.js` to both ignore and insert the -same record in a domain. This is done as a safety mechanism. +It is considered as an error for a `dnsconfig.js` to both ignore and insert the same record in a domain. This is done as a safety mechanism. This will generate an error: @@ -318,8 +301,7 @@ D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), ``` {% endcode %} -To disable this safety check, add the `DISABLE_IGNORE_SAFETY_CHECK` statement -to the `D()`. +To disable this safety check, add the `DISABLE_IGNORE_SAFETY_CHECK` statement to the `D()`. {% code title="dnsconfig.js" %} ```javascript @@ -337,9 +319,7 @@ FYI: Previously DNSControl permitted disabling this check on a per-record basis using `IGNORE_NAME_DISABLE_SAFETY_CHECK`: {% endhint %} -The `IGNORE_NAME_DISABLE_SAFETY_CHECK` feature does not exist in the diff2 -world and its use will result in a validation error. Use the above example -instead. +The `IGNORE_NAME_DISABLE_SAFETY_CHECK` feature does not exist in the diff2 world and its use will result in a validation error. Use the above example instead. {% code %} ```javascript diff --git a/documentation/language-reference/domain-modifiers/IGNORE_EXTERNAL_DNS.md b/documentation/language-reference/domain-modifiers/IGNORE_EXTERNAL_DNS.md index fec32ca9c7..7d846c6dba 100644 --- a/documentation/language-reference/domain-modifiers/IGNORE_EXTERNAL_DNS.md +++ b/documentation/language-reference/domain-modifiers/IGNORE_EXTERNAL_DNS.md @@ -6,26 +6,19 @@ parameter_types: prefix: string? --- -`IGNORE_EXTERNAL_DNS` makes DNSControl automatically detect and ignore DNS records -managed by Kubernetes external-dns. +`IGNORE_EXTERNAL_DNS` makes DNSControl automatically detect and ignore DNS records managed by Kubernetes external-dns. ## Background -[External-dns](https://github.com/kubernetes-sigs/external-dns) is a popular -Kubernetes controller that synchronizes exposed Kubernetes Services and Ingresses -with DNS providers. It creates DNS records automatically based on annotations on -your Kubernetes resources. +[External-dns](https://github.com/kubernetes-sigs/external-dns) is a popular Kubernetes controller that synchronizes exposed Kubernetes Services and Ingresses with DNS providers. It creates DNS records automatically based on annotations on your Kubernetes resources. -External-dns uses TXT records to track ownership of the DNS records it manages. -These TXT records contain metadata in this format: +External-dns uses TXT records to track ownership of the DNS records it manages. These TXT records contain metadata in this format: ``` "heritage=external-dns,external-dns/owner=,external-dns/resource=" ``` -When you have both DNSControl and external-dns managing the same DNS zone, conflicts -can occur. DNSControl will try to delete records created by external-dns, and -external-dns will recreate them, leading to an endless update cycle. +When you have both DNSControl and external-dns managing the same DNS zone, conflicts can occur. DNSControl will try to delete records created by external-dns, and external-dns will recreate them, leading to an endless update cycle. ## How it works @@ -37,15 +30,14 @@ When `IGNORE_EXTERNAL_DNS` is enabled, DNSControl will: External-dns creates TXT records with prefixes based on record type: - `a-` for A records -- `aaaa-` for AAAA records +- `aaaa-` for AAAA records - `cname-` for CNAME records - `ns-` for NS records - `mx-` for MX records - `srv-` for SRV records - `txt-` for TXT records (when external-dns manages TXT records) -For example, if external-dns creates an A record at `myapp.example.com`, it will -also create a TXT record at `a-myapp.example.com` containing the heritage information. +For example, if external-dns creates an A record at `myapp.example.com`, it will also create a TXT record at `a-myapp.example.com` containing the heritage information. ## Usage @@ -66,9 +58,7 @@ D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), ## Custom Prefix Support -If your external-dns is configured with a custom `--txt-prefix` (as documented in the -[external-dns TXT registry docs](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md#prefixes-and-suffixes)), -pass that prefix to `IGNORE_EXTERNAL_DNS()`: +If your external-dns is configured with a custom `--txt-prefix` (as documented in the [external-dns TXT registry docs](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md#prefixes-and-suffixes)), pass that prefix to `IGNORE_EXTERNAL_DNS()`: {% code title="dnsconfig.js" %} ```javascript @@ -113,27 +103,21 @@ With `IGNORE_EXTERNAL_DNS` enabled, DNSControl will: ### One per domain -Only one `IGNORE_EXTERNAL_DNS()` should be used per domain. If you call it multiple -times, the last prefix wins. If you have multiple external-dns instances with -different prefixes managing the same zone, use `IGNORE()` patterns for additional -prefixes. +Only one `IGNORE_EXTERNAL_DNS()` should be used per domain. If you call it multiple times, the last prefix wins. If you have multiple external-dns instances with different prefixes managing the same zone, use `IGNORE()` patterns for additional prefixes. ### TXT Registry Format -This feature relies on external-dns's [TXT registry](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md), -which is the default registry type. The TXT record content format is well-documented: +This feature relies on external-dns's [TXT registry](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/registry/txt.md), which is the default registry type. The TXT record content format is well-documented: ``` "heritage=external-dns,external-dns/owner=,external-dns/resource=" ``` -This feature detects the `heritage=external-dns` marker in TXT records to identify -external-dns managed records. +This feature detects the `heritage=external-dns` marker in TXT records to identify external-dns managed records. ### Custom Prefix Support -This feature supports custom prefixes configured via external-dns's `--txt-prefix` flag. -If you're using a custom prefix, pass it to `IGNORE_EXTERNAL_DNS()`: +This feature supports custom prefixes configured via external-dns's `--txt-prefix` flag. If you're using a custom prefix, pass it to `IGNORE_EXTERNAL_DNS()`: ```javascript // If external-dns uses --txt-prefix="extdns-" @@ -153,8 +137,7 @@ Without a prefix argument, it detects: #### Period Format for Apex Domains -If you need external-dns to manage apex (root) domain records, the external-dns -documentation recommends using a prefix with `%{record_type}` followed by a period: +If you need external-dns to manage apex (root) domain records, the external-dns documentation recommends using a prefix with `%{record_type}` followed by a period: ```yaml # external-dns deployment args @@ -162,8 +145,7 @@ args: - --txt-prefix=extdns-%{record_type}. ``` -This creates TXT records like `extdns-a.www` for the `www` A record, and `extdns-a` -for the apex A record. DNSControl's `IGNORE_EXTERNAL_DNS` supports both formats: +This creates TXT records like `extdns-a.www` for the `www` A record, and `extdns-a` for the apex A record. DNSControl's `IGNORE_EXTERNAL_DNS` supports both formats: - Hyphen format: `extdns-a-www` (from `--txt-prefix=extdns-` with default `%{record_type}-`) - Period format: `extdns-a.www` (from `--txt-prefix=extdns-%{record_type}.`) @@ -184,10 +166,7 @@ The following registries are **not supported**: ### Legacy TXT Format -External-dns versions prior to v0.16 created TXT records without the record type -prefix (e.g., `myapp.example.com` instead of `a-myapp.example.com`). This legacy -format is supported but may match more records than intended since the record type -cannot be determined. +External-dns versions prior to v0.16 created TXT records without the record type prefix (e.g., `myapp.example.com` instead of `a-myapp.example.com`). This legacy format is supported but may match more records than intended since the record type cannot be determined. ## See also diff --git a/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM.md b/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM.md index 0c137ccd82..672005c0e0 100644 --- a/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM.md +++ b/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM.md @@ -12,8 +12,7 @@ ts_ignore: true Don't use this feature. It was added for a very specific situation at Stack Overflow. {% endhint %} -`IMPORT_TRANSFORM` adds to the domain the records from another -domain, after making certain transformations and resetting the TTL. +`IMPORT_TRANSFORM` adds to the domain the records from another domain, after making certain transformations and resetting the TTL. Not all records are copied and transformed: * The record must be record type A or CNAME. @@ -22,15 +21,9 @@ Not all records are copied and transformed: Example: -Suppose foo.com is a regular domain. bar.com is a regular domain, -but certain records should be the same as foo.com with these -exceptions: "bar.com" is added to the name, the TTL is changed to -300, if the IP address is between 1.2.3.10 and 1.2.3.20 then rewrite -the IP address to be based on 123.123.123.100 (i.e. .113 or .114). +Suppose foo.com is a regular domain. bar.com is a regular domain, but certain records should be the same as foo.com with these exceptions: "bar.com" is added to the name, the TTL is changed to 300, if the IP address is between 1.2.3.10 and 1.2.3.20 then rewrite the IP address to be based on 123.123.123.100 (i.e. .113 or .114). -You wouldn't want to maintain bar.com manually, would you? It would -be very error prone. Therefore instead you maintain foo.com and -let `IMPORT_TRANSFORM` automatically generate bar.com. +You wouldn't want to maintain bar.com manually, would you? It would be very error prone. Therefore instead you maintain foo.com and let `IMPORT_TRANSFORM` automatically generate bar.com. ```text foo.com: diff --git a/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM_STRIP.md b/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM_STRIP.md index 68572f2952..6551d207d8 100644 --- a/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM_STRIP.md +++ b/documentation/language-reference/domain-modifiers/IMPORT_TRANSFORM_STRIP.md @@ -15,15 +15,10 @@ Don't use this feature. It was added for a very specific situation at Stack Over `IMPORT_TRANSFORM_STRIP` is the same as `IMPORT_TRANSFORM` with an additional parameter: `suffixstrip`. -When `IMPORT_TRANSFORM_STRIP` is generating the label for new records, it -checks the label. If the label ends with `.` + `suffixstrip`, that suffix is removed. -If the label does not end with `suffixstrip`, an error is returned. +When `IMPORT_TRANSFORM_STRIP` is generating the label for new records, it checks the label. If the label ends with `.` + `suffixstrip`, that suffix is removed. If the label does not end with `suffixstrip`, an error is returned. For CNAMEs, the `suffixstrip` is stripped from the beginning (prefix) of the target domain. -For example, if the domain is `com.extra` and the label is `foo.com`, -`IMPORT_TRANSFORM` would generate a label `foo.com.com.extra`. -`IMPORT_TRANSFORM_STRIP(... , 'com')` would generate -the label `foo.com.extra` instead. +For example, if the domain is `com.extra` and the label is `foo.com`, `IMPORT_TRANSFORM` would generate a label `foo.com.com.extra`. `IMPORT_TRANSFORM_STRIP(... , 'com')` would generate the label `foo.com.extra` instead. In the case of a CNAME, if the target is `foo.com.`, the new target would be `foo.com.extra`. diff --git a/documentation/language-reference/domain-modifiers/LOC.md b/documentation/language-reference/domain-modifiers/LOC.md index 867f41df07..2878b20c49 100644 --- a/documentation/language-reference/domain-modifiers/LOC.md +++ b/documentation/language-reference/domain-modifiers/LOC.md @@ -45,7 +45,6 @@ horizontal_precision: float32 vertical_precision: float32 ``` - ## Description ## Strictly follows [RFC 1876](https://datatracker.ietf.org/doc/html/rfc1876). @@ -62,10 +61,7 @@ On the wire, it is in a binary format. A use case for LOC is suggested in the RFC: > Some uses for the LOC RR have already been suggested, including the - USENET backbone flow maps, a "visual traceroute" application showing - the geographical path of an IP packet, and network management - applications that could use LOC RRs to generate a map of hosts and - routers being managed. + USENET backbone flow maps, a "visual traceroute" application showing the geographical path of an IP packet, and network management applications that could use LOC RRs to generate a map of hosts and routers being managed. There is the UK based [https://find.me.uk](https://find.me.uk/) whereby you can do: @@ -73,20 +69,12 @@ There is the UK based [https://find.me.uk](https://find.me.uk/) whereby you can dig loc .find.me.uk ``` - There are some behaviours that you should be aware of, however: > If omitted, minutes and seconds default to zero, size defaults to 1m, - horizontal precision defaults to 10000m, and vertical precision - defaults to 10m. These defaults are chosen to represent typical - ZIP/postal code area sizes, since it is often easy to find - approximate geographical location by ZIP/postal code. - + horizontal precision defaults to 10000m, and vertical precision defaults to 10m. These defaults are chosen to represent typical ZIP/postal code area sizes, since it is often easy to find approximate geographical location by ZIP/postal code. -Alas, the world does not revolve around US ZIP codes, but here we are. Internally, -the LOC record type will supply defaults where values were absent on DNS import. -One must supply the `LOC()` js helper all parameters. If that seems like too -much work, see also helper functions: +Alas, the world does not revolve around US ZIP codes, but here we are. Internally, the LOC record type will supply defaults where values were absent on DNS import. One must supply the `LOC()` js helper all parameters. If that seems like too much work, see also helper functions: * [`LOC_BUILDER_DD({})`](LOC_BUILDER_DD.md) - build a `LOC` by supplying only **d**ecimal **d**egrees. * [`LOC_BUILDER_DMS_STR({})`](LOC_BUILDER_DMS_STR.md) - accepts DMS 33°51′31″S 151°12′51″E @@ -99,9 +87,7 @@ The coordinate format for `LOC()` is: `degrees,minutes,seconds,[NnSs],deg,min,sec,[EeWw],altitude,size,horizontal_precision,vertical_precision` -where: - altitude: [-100000.00 .. 42849672.95] BY .01 (altitude in meters) - size, horizontal_precision, vertical_precision: [0 .. 90000000.00] (size/precision in meters) +where: altitude: [-100000.00 .. 42849672.95] BY .01 (altitude in meters) size, horizontal_precision, vertical_precision: [0 .. 90000000.00] (size/precision in meters) values outside of the above ranges are gated to within the ranges. diff --git a/documentation/language-reference/domain-modifiers/NAMESERVER.md b/documentation/language-reference/domain-modifiers/NAMESERVER.md index f32a25a65a..8f28e78eeb 100644 --- a/documentation/language-reference/domain-modifiers/NAMESERVER.md +++ b/documentation/language-reference/domain-modifiers/NAMESERVER.md @@ -8,15 +8,11 @@ parameter_types: "modifiers...": RecordModifier[] --- -`NAMESERVER()` instructs DNSControl to inform the domain's registrar where to find this zone. -For some registrars this will also add NS records to the zone itself. +`NAMESERVER()` instructs DNSControl to inform the domain's registrar where to find this zone. For some registrars this will also add NS records to the zone itself. -This takes exactly one argument: the name of the nameserver. It must end with -a "." if it is a FQDN, just like all targets. +This takes exactly one argument: the name of the nameserver. It must end with a "." if it is a FQDN, just like all targets. -This is different than the [`NS()`](NS.md) function, which inserts NS records -in the current zone and accepts a label. [`NS()`](NS.md) is for downward -delegations. `NAMESERVER()` is for informing upstream delegations. +This is different than the [`NS()`](NS.md) function, which inserts NS records in the current zone and accepts a label. [`NS()`](NS.md) is for downward delegations. `NAMESERVER()` is for informing upstream delegations. For more information, refer to [this page](../../advanced-features/nameservers.md). @@ -38,46 +34,27 @@ D("example2.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), ``` {% endcode %} - # The difference between NS() and NAMESERVER() -Nameservers are one of the least -understood parts of DNS, so a little extra explanation is required. +Nameservers are one of the least understood parts of DNS, so a little extra explanation is required. -* [`NS()`](NS.md) adds an NS record to a zone, just like [`A()`](A.md) adds an A - record to the zone. This is generally used to delegate a subzone. +* [`NS()`](NS.md) adds an NS record to a zone, just like [`A()`](A.md) adds an A record to the zone. This is generally used to delegate a subzone. * The `NAMESERVER()` directive speaks to the Registrar about how the parent should delegate the zone. -Since the parent zone could be completely unrelated to the current -zone, changes made by `NAMESERVER()` have to be done by an API call to -the registrar, who then figures out what to do. For example, if I -use `NAMESERVER()` in the zone `stackoverflow.com`, DNSControl talks to -the registrar who does the hard work of talking to the people that -control `.com`. If the domain was `gmeet.io`, the registrar does -the right thing to talk to the people that control `.io`. +Since the parent zone could be completely unrelated to the current zone, changes made by `NAMESERVER()` have to be done by an API call to the registrar, who then figures out what to do. For example, if I use `NAMESERVER()` in the zone `stackoverflow.com`, DNSControl talks to the registrar who does the hard work of talking to the people that control `.com`. If the domain was `gmeet.io`, the registrar does the right thing to talk to the people that control `.io`. -(A better name might have been `PARENTNAMESERVER()` but we didn't -think of that at the time.) +(A better name might have been `PARENTNAMESERVER()` but we didn't think of that at the time.) -Each registrar handles delegations differently. Most use -the `NAMESERVER()` targets to update the delegation, adding -`NS` records to the parent zone as required. -Some providers restrict the names to hosts they control. -Others may require you to add the `NS` records to the parent domain -manually. +Each registrar handles delegations differently. Most use the `NAMESERVER()` targets to update the delegation, adding `NS` records to the parent zone as required. Some providers restrict the names to hosts they control. Others may require you to add the `NS` records to the parent domain manually. # How to prevent changing the parent NS records? -If dnsconfig.js has zero `NAMESERVER()` commands for a domain, it will -use the API to remove all non-default nameservers. +If dnsconfig.js has zero `NAMESERVER()` commands for a domain, it will use the API to remove all non-default nameservers. -If `dnsconfig.js` has 1 or more `NAMESERVER()` commands for a domain, it -will use the API to add those nameservers (unless, of course, -they already exist). +If `dnsconfig.js` has 1 or more `NAMESERVER()` commands for a domain, it will use the API to add those nameservers (unless, of course, they already exist). -So how do you tell DNSControl not to make any changes at all? Use the -special Registrar called "NONE". It makes no changes. +So how do you tell DNSControl not to make any changes at all? Use the special Registrar called "NONE". It makes no changes. It looks like this: diff --git a/documentation/language-reference/domain-modifiers/NO_PURGE.md b/documentation/language-reference/domain-modifiers/NO_PURGE.md index 664a29da3b..e4c43735ee 100644 --- a/documentation/language-reference/domain-modifiers/NO_PURGE.md +++ b/documentation/language-reference/domain-modifiers/NO_PURGE.md @@ -2,28 +2,17 @@ name: NO_PURGE --- -`NO_PURGE` indicates that existing records should not be deleted from a domain. -Records will be added and updated, but not removed. +`NO_PURGE` indicates that existing records should not be deleted from a domain. Records will be added and updated, but not removed. -Suppose a domain is managed by both DNSControl and a third-party system. This -creates a problem because DNSControl will try to delete records inserted by the -other system. +Suppose a domain is managed by both DNSControl and a third-party system. This creates a problem because DNSControl will try to delete records inserted by the other system. -By setting `NO_PURGE` on a domain, this tells DNSControl not to delete the -records found in the domain. +By setting `NO_PURGE` on a domain, this tells DNSControl not to delete the records found in the domain. It is similar to [`IGNORE`](IGNORE.md) but more general. -The original reason for `NO_PURGE` was that a legacy system was adopting -DNSControl. Previously the domain was managed via Microsoft DNS Server's GUI. -ActiveDirectory was in use, so various records were being inserted behind the -scenes. It was decided to use DNSControl to simply insert a few records. The -`NO_PURGE` setting instructed DNSControl not to delete the existing records. +The original reason for `NO_PURGE` was that a legacy system was adopting DNSControl. Previously the domain was managed via Microsoft DNS Server's GUI. ActiveDirectory was in use, so various records were being inserted behind the scenes. It was decided to use DNSControl to simply insert a few records. The `NO_PURGE` setting instructed DNSControl not to delete the existing records. -In this example DNSControl will insert "foo.example.com" into the zone, but -otherwise leave the zone alone. Changes to "foo"'s IP address will update the -record. Removing the A("foo", ...) record from DNSControl will leave the record -in place. +In this example DNSControl will insert "foo.example.com" into the zone, but otherwise leave the zone alone. Changes to "foo"'s IP address will update the record. Removing the A("foo", ...) record from DNSControl will leave the record in place. {% code title="dnsconfig.js" %} ```javascript @@ -33,20 +22,13 @@ D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), NO_PURGE, ``` {% endcode %} -The main caveat of `NO_PURGE` is that intentionally deleting records becomes -more difficult. Suppose a `NO_PURGE` zone has an record such as A("ken", -"1.2.3.4"). Removing the record from `dnsconfig.js` will not delete "ken" from -the domain. DNSControl has no way of knowing the record was deleted from the -file The DNS record must be removed manually. Users of `NO_PURGE` are prone -to finding themselves with an accumulation of orphaned DNS records. That's easy -to fix for a small zone but can be a big mess for large zones. +The main caveat of `NO_PURGE` is that intentionally deleting records becomes more difficult. Suppose a `NO_PURGE` zone has an record such as A("ken", "1.2.3.4"). Removing the record from `dnsconfig.js` will not delete "ken" from the domain. DNSControl has no way of knowing the record was deleted from the file The DNS record must be removed manually. Users of `NO_PURGE` are prone to finding themselves with an accumulation of orphaned DNS records. That's easy to fix for a small zone but can be a big mess for large zones. ## Support Prior to DNSControl v4.0.0, not all providers supported `NO_PURGE`. -With introduction of `diff2` algorithm (enabled by default in v4.0.0), -`NO_PURGE` works with all providers. +With introduction of `diff2` algorithm (enabled by default in v4.0.0), `NO_PURGE` works with all providers. ## See also diff --git a/documentation/language-reference/domain-modifiers/OPENPGPKEY.md b/documentation/language-reference/domain-modifiers/OPENPGPKEY.md index 0d38b4e39c..7545c35f50 100644 --- a/documentation/language-reference/domain-modifiers/OPENPGPKEY.md +++ b/documentation/language-reference/domain-modifiers/OPENPGPKEY.md @@ -10,15 +10,11 @@ parameter_types: "modifiers...": RecordModifier[] --- -`OPENPGPKEY` adds an [OpenPGP public key -record](https://datatracker.ietf.org/doc/html/rfc7929) to the domain. +`OPENPGPKEY` adds an [OpenPGP public key record](https://datatracker.ietf.org/doc/html/rfc7929) to the domain. -So far, no transformation is applied to the parameters. The data will be -passed to the DNS server as-is. DNSControl supports both hex-encoded and -base64-encoded input for the public key portion of the record. +So far, no transformation is applied to the parameters. The data will be passed to the DNS server as-is. DNSControl supports both hex-encoded and base64-encoded input for the public key portion of the record. -There are multiple ways to generate the appropriately-formatted record -values: +There are multiple ways to generate the appropriately-formatted record values: 1. By using `gpg --export-options=export-dane`: @@ -92,9 +88,7 @@ values: ``` {% endcode %} -3. By using the [`hash-slinger` - package](https://github.com/letoams/hash-slinger/) (which is - available in most Linux distro package repositories): +3. By using the [`hash-slinger` package](https://github.com/letoams/hash-slinger/) (which is available in most Linux distro package repositories): {% code title="Shell Transcript" %} ```shell-session diff --git a/documentation/language-reference/domain-modifiers/PTR.md b/documentation/language-reference/domain-modifiers/PTR.md index f11cfb9018..107a54aa1e 100644 --- a/documentation/language-reference/domain-modifiers/PTR.md +++ b/documentation/language-reference/domain-modifiers/PTR.md @@ -12,53 +12,25 @@ parameter_types: `PTR` adds a [PTR Resource record](https://www.rfc-editor.org/rfc/rfc1035) to the domain. -The name is normally a relative label for the domain, or a FQDN that ends with `.`. If magic mode is enabled (see below) it can also be an IP address, which will be replaced by the proper string automatically, thus -saving the user from having to reverse the IP address manually. +The name is normally a relative label for the domain, or a FQDN that ends with `.`. If magic mode is enabled (see below) it can also be an IP address, which will be replaced by the proper string automatically, thus saving the user from having to reverse the IP address manually. Target should be a string representing the FQDN of a host. Like all FQDNs in DNSControl, it must end with a `.`. # Magic Mode -PTR records are complex and typos are common. Therefore DNSControl -enables features to save labor and -prevent typos. This magic is only -enabled when the domain ends with `in-addr.arpa.` or `ipv6.arpa.`. - -*Automatic IP-to-reverse:* If the name is a valid IP address, DNSControl will replace it with -a string that is appropriate for the domain. That is, if the domain -ends with `in-addr.arpa` (no `.`) and name is a valid IPv4 address, the name -will be replaced with the correct string to make a reverse lookup for that address. -IPv6 is properly handled too. - -*Extra Validation:* DNSControl considers it an error to include a name that -is inappropriate for the domain. For example -`PTR("1.2.3.4", "f.co.")` is valid for the domain `D("3.2.1.in-addr.arpa",` - but DNSControl will generate an error if the domain is `D("9.9.9.in-addr.arpa",`. -This is because `1.2.3.4` is contained in `1.2.3.0/24` but not `9.9.9.0/24`. -This validation works for IPv6, IPv4, and -RFC2317 "Classless in-addr.arpa delegation" domains. - -*Automatic truncation:* DNSControl will automatically truncate FQDNs -as needed. -If the name is a FQDN ending with `.`, DNSControl will verify that the -name is contained within the CIDR block implied by domain. For example -if name is `4.3.2.1.in-addr.arpa.` (note the trailing `.`) -and the domain is `2.1.in-addr.arpa` (no trailing `.`) -then the name will be replaced with `4.3`. Note that the output -of `REV("1.2.3.4")` is `4.3.2.1.in-addr.arpa.`, which means the following -are all equivalent: +PTR records are complex and typos are common. Therefore DNSControl enables features to save labor and prevent typos. This magic is only enabled when the domain ends with `in-addr.arpa.` or `ipv6.arpa.`. + +*Automatic IP-to-reverse:* If the name is a valid IP address, DNSControl will replace it with a string that is appropriate for the domain. That is, if the domain ends with `in-addr.arpa` (no `.`) and name is a valid IPv4 address, the name will be replaced with the correct string to make a reverse lookup for that address. IPv6 is properly handled too. + +*Extra Validation:* DNSControl considers it an error to include a name that is inappropriate for the domain. For example `PTR("1.2.3.4", "f.co.")` is valid for the domain `D("3.2.1.in-addr.arpa",` but DNSControl will generate an error if the domain is `D("9.9.9.in-addr.arpa",`. This is because `1.2.3.4` is contained in `1.2.3.0/24` but not `9.9.9.0/24`. This validation works for IPv6, IPv4, and RFC2317 "Classless in-addr.arpa delegation" domains. + +*Automatic truncation:* DNSControl will automatically truncate FQDNs as needed. If the name is a FQDN ending with `.`, DNSControl will verify that the name is contained within the CIDR block implied by domain. For example if name is `4.3.2.1.in-addr.arpa.` (note the trailing `.`) and the domain is `2.1.in-addr.arpa` (no trailing `.`) then the name will be replaced with `4.3`. Note that the output of `REV("1.2.3.4")` is `4.3.2.1.in-addr.arpa.`, which means the following are all equivalent: * `PTR(REV("1.2.3.4", ...` * `PTR("4.3.2.1.in-addr.arpa.", ...` * `PTR("4.3", ...` // Assuming the domain is `2.1.in-addr.arpa` -All magic is RFC2317-aware. We use the first format listed in the -RFC for both [`REV()`](../top-level-functions/REV.md) and `PTR()`. The format is -`FIRST/MASK.C.B.A.in-addr.arpa` where `FIRST` is the first IP address -of the zone, `MASK` is the netmask of the zone (25-31 inclusive), -and A, B, C are the first 3 octets of the IP address. For example -`172.20.18.130/27` is located in a zone named -`128/27.18.20.172.in-addr.arpa` +All magic is RFC2317-aware. We use the first format listed in the RFC for both [`REV()`](../top-level-functions/REV.md) and `PTR()`. The format is `FIRST/MASK.C.B.A.in-addr.arpa` where `FIRST` is the first IP address of the zone, `MASK` is the netmask of the zone (25-31 inclusive), and A, B, C are the first 3 octets of the IP address. For example `172.20.18.130/27` is located in a zone named `128/27.18.20.172.in-addr.arpa` {% code title="dnsconfig.js" %} ```javascript @@ -93,10 +65,7 @@ D(REV("2001:db8:302::/48"), REGISTRAR, DnsProvider(BIND), # Automatic forward and reverse lookups -DNSControl does not automatically generate forward and reverse lookups. However -it is possible to write a macro that does this by using the -[`D_EXTEND()`](../top-level-functions/D_EXTEND.md) -function to insert `A` and `PTR` records into previously-defined domains. +DNSControl does not automatically generate forward and reverse lookups. However it is possible to write a macro that does this by using the [`D_EXTEND()`](../top-level-functions/D_EXTEND.md) function to insert `A` and `PTR` records into previously-defined domains. {% code title="dnsconfig.js" %} ```javascript diff --git a/documentation/language-reference/domain-modifiers/PURGE.md b/documentation/language-reference/domain-modifiers/PURGE.md index 7b7593d005..2f19581509 100644 --- a/documentation/language-reference/domain-modifiers/PURGE.md +++ b/documentation/language-reference/domain-modifiers/PURGE.md @@ -2,11 +2,9 @@ name: PURGE --- -`PURGE` is the default setting for all domains. Therefore `PURGE` is -a no-op. It is included for completeness only. +`PURGE` is the default setting for all domains. Therefore `PURGE` is a no-op. It is included for completeness only. -A domain with a mixture of `NO_PURGE` and `PURGE` parameters will abide -by the last one. +A domain with a mixture of `NO_PURGE` and `PURGE` parameters will abide by the last one. These three examples all are equivalent. diff --git a/documentation/language-reference/domain-modifiers/SPF_BUILDER.md b/documentation/language-reference/domain-modifiers/SPF_BUILDER.md index 07834c73e2..17ee406560 100644 --- a/documentation/language-reference/domain-modifiers/SPF_BUILDER.md +++ b/documentation/language-reference/domain-modifiers/SPF_BUILDER.md @@ -21,9 +21,7 @@ parameter_types: flatten: string[]? --- -DNSControl can optimize the SPF settings on a domain by flattening -(inlining) includes and removing duplicates. DNSControl also makes -it easier to document your SPF configuration. +DNSControl can optimize the SPF settings on a domain by flattening (inlining) includes and removing duplicates. DNSControl also makes it easier to document your SPF configuration. {% hint style="warning" %} **WARNING**: Flattening SPF includes is risky. Only flatten an SPF @@ -32,7 +30,6 @@ to be less than 10. In fact, it is debatable whether or not ISPs enforce the "10 lookup rule". {% endhint %} - ## The old way Here is an example of how SPF settings are normally done: @@ -93,8 +90,7 @@ By using the `SPF_BUILDER()` we gain many benefits: ## Syntax -When you want to specify SPF settings for a domain, use the -`SPF_BUILDER()` function. +When you want to specify SPF settings for a domain, use the `SPF_BUILDER()` function. {% code title="dnsconfig.js" %} ```javascript @@ -133,8 +129,7 @@ The parameters are: * `parts:` The individual parts of the SPF settings. * `flatten:` Which includes should be inlined. For safety purposes the flattening is done on an opt-in basis. If `"*"` is listed, all includes will be flattened... this might create more problems than is solves due to length limitations. -[multi-string]: https://tools.ietf.org/html/rfc4408#section-3.1.3 -[record-size]: https://tools.ietf.org/html/rfc4408#section-3.1.4 +[multi-string]: https://tools.ietf.org/html/rfc4408#section-3.1.3 [record-size]: https://tools.ietf.org/html/rfc4408#section-3.1.4 `SPF_BUILDER()` returns multiple `TXT()` records: @@ -145,33 +140,21 @@ The parameters are: * `TXT("_rawspf", "v=spf1 .... ~all")` * This is the unaltered SPF configuration. This is purely for debugging purposes and is not used by any email or anti-spam system. It is only generated if flattening is requested. +We recommend first using this without any flattening. Make sure `dnscontrol preview` works as expected. Once that is done, add the flattening required to reduce the number of lookups to 10 or less. -We recommend first using this without any flattening. Make sure -`dnscontrol preview` works as expected. Once that is done, add the -flattening required to reduce the number of lookups to 10 or less. - -To count the number of lookups, you can use our interactive SPF -debugger at [https://dnscontrol.github.io/dnscontrol/flattener/index.html](https://dnscontrol.github.io/dnscontrol/flattener/index.html) +To count the number of lookups, you can use our interactive SPF debugger at [https://dnscontrol.github.io/dnscontrol/flattener/index.html](https://dnscontrol.github.io/dnscontrol/flattener/index.html) # The first in a chain is special -When generating the chain of SPF -records, each one is max length 255. For the first item in -the chain, the max is 255 - "overhead1". Setting this to 255 or -higher has undefined behavior. +When generating the chain of SPF records, each one is max length 255. For the first item in the chain, the max is 255 - "overhead1". Setting this to 255 or higher has undefined behavior. Why is this useful? -Some sites desire having all DNS queries fit in a single packet so -that UDP, not TCP, can be used to satisfy all requests. That means all -responses have to be relatively small. +Some sites desire having all DNS queries fit in a single packet so that UDP, not TCP, can be used to satisfy all requests. That means all responses have to be relatively small. -When an SPF system does a "TXT" lookup, it gets SPF and non-SPF -records. This makes the first link in the chain extra large. +When an SPF system does a "TXT" lookup, it gets SPF and non-SPF records. This makes the first link in the chain extra large. -The bottom line is that if you want the TXT records to fit in a UDP -packet, keep increasing the value of `overhead1` until the packet -is no longer truncated. +The bottom line is that if you want the TXT records to fit in a UDP packet, keep increasing the value of `overhead1` until the packet is no longer truncated. Example: @@ -187,30 +170,17 @@ dig +short stackoverflow.com txt | wc -c 582 ``` -Since 582 is bigger than 255, it might not be possible to achieve the -goal. Any value larger than 255 will disable all flattening. Try -170, then 180, 190 until you get the desired results. +Since 582 is bigger than 255, it might not be possible to achieve the goal. Any value larger than 255 will disable all flattening. Try 170, then 180, 190 until you get the desired results. -A validator such as -[https://www.kitterman.com/spf/validate.html](https://www.kitterman.com/spf/validate.html) -will tell you if the queries are being truncated and TCP was required -to get the entire record. (Sadly it caches heavily.) +A validator such as [https://www.kitterman.com/spf/validate.html](https://www.kitterman.com/spf/validate.html) will tell you if the queries are being truncated and TCP was required to get the entire record. (Sadly it caches heavily.) ## Notes about the `spfcache.json` -DNSControl will optionally keep a cache of the DNS lookups performed during -optimization. In the event that a DNS server is down, the cache will be used. -This makes it possible to do `dnscontrol -push` even if your or third-party DNS servers are down. +DNSControl will optionally keep a cache of the DNS lookups performed during optimization. In the event that a DNS server is down, the cache will be used. This makes it possible to do `dnscontrol push` even if your or third-party DNS servers are down. -To enable this feature, create an (empty) file called `spfcache.json` in the -current directory. To disable this feature, delete the file. There are no -command-line flags related to this feature. +To enable this feature, create an (empty) file called `spfcache.json` in the current directory. To disable this feature, delete the file. There are no command-line flags related to this feature. -The `spfcache.json` stored the cached DNS lookups. If it needs -to be updated, the new file contents will be written to a file called -`spfcache.updated.json` and instructions such as the ones below -will be output telling you exactly what to do: +The `spfcache.json` stored the cached DNS lookups. If it needs to be updated, the new file contents will be written to a file called `spfcache.updated.json` and instructions such as the ones below will be output telling you exactly what to do: ```shell dnscontrol preview @@ -221,72 +191,41 @@ Wrote changes to spfcache.updated.json. Please rename and commit: $ git commit spfcache.json ``` -In this case, you are being asked to replace `spfcache.json` with -the newly generated data in `spfcache.updated.json`. +In this case, you are being asked to replace `spfcache.json` with the newly generated data in `spfcache.updated.json`. -The instructions are hardcoded strings. The filenames will -not change. -The instructions assume you use git. If you use something -else, please do the appropriate equivalent command. +The instructions are hardcoded strings. The filenames will not change. The instructions assume you use git. If you use something else, please do the appropriate equivalent command. ## Caveats -1. DNSControl 'gives up' if it sees SPF records it can't understand. -This includes: syntax errors, features that our spflib doesn't know -about, overly complex SPF settings, and anything else that we we -didn't feel like implementing. +1. DNSControl 'gives up' if it sees SPF records it can't understand. This includes: syntax errors, features that our spflib doesn't know about, overly complex SPF settings, and anything else that we we didn't feel like implementing. -2. The TXT record that is generated may exceed DNS limits. dnscontrol -will not generate a single TXT record that exceeds DNS limits, but -it ignores the fact that there may be other TXT records on the same -label. For example, suppose it generates a TXT record on the bare -domain (stackoverflow.com) that is 250 bytes long. That's fine and -doesn't require a continuation record. However if there is another -TXT record (not an SPF record, perhaps a TXT record used to verify -domain ownership), the total packet size of all the TXT records -could exceed 512 bytes, and will require EDNS or a TCP request. +2. The TXT record that is generated may exceed DNS limits. dnscontrol will not generate a single TXT record that exceeds DNS limits, but it ignores the fact that there may be other TXT records on the same label. For example, suppose it generates a TXT record on the bare domain (stackoverflow.com) that is 250 bytes long. That's fine and doesn't require a continuation record. However if there is another TXT record (not an SPF record, perhaps a TXT record used to verify domain ownership), the total packet size of all the TXT records could exceed 512 bytes, and will require EDNS or a TCP request. -3. DNSControl does not warn if the number of lookups exceeds 10. -We hope to implement this some day. - -4. The `redirect=` directive is only partially implemented. We only -handle the case where redirect is the last item in the SPF record. -In which case, it is equivalent to `include:`. +3. DNSControl does not warn if the number of lookups exceeds 10. We hope to implement this some day. +4. The `redirect=` directive is only partially implemented. We only handle the case where redirect is the last item in the SPF record. In which case, it is equivalent to `include:`. ## Advanced Technique: Interactive SPF Debugger -DNSControl includes an experimental system for viewing -SPF settings: +DNSControl includes an experimental system for viewing SPF settings: [https://dnscontrol.github.io/dnscontrol/flattener/index.html](https://dnscontrol.github.io/dnscontrol/flattener/index.html) -You can also run this locally (it is self-contained) by opening -`dnscontrol/docs/flattener/index.html` in your browser. +You can also run this locally (it is self-contained) by opening `dnscontrol/docs/flattener/index.html` in your browser. -You can use this to determine the minimal number of domains you -need to flatten to have fewer than 10 lookups. +You can use this to determine the minimal number of domains you need to flatten to have fewer than 10 lookups. The output is as follows: -1. The top part lists the domain as it current is configured, how -many lookups it requires, and includes a checkbox for each item -that could be flattened. - -2. Fully flattened: This section shows the SPF configuration if you -fully flatten it. i.e. This is what it would look like if all the -checkboxes were checked. Note that this result is likely to be -longer than 255 bytes, the limit for a single TXT string. +1. The top part lists the domain as it current is configured, how many lookups it requires, and includes a checkbox for each item that could be flattened. -3. Fully flattened split: This takes the "fully flattened" result -and splits it into multiple DNS records. To continue to the next -record an include is added. +2. Fully flattened: This section shows the SPF configuration if you fully flatten it. i.e. This is what it would look like if all the checkboxes were checked. Note that this result is likely to be longer than 255 bytes, the limit for a single TXT string. +3. Fully flattened split: This takes the "fully flattened" result and splits it into multiple DNS records. To continue to the next record an include is added. ## Advanced Technique: Define once, use many -In some situations we define an SPF setting once and want to reuse -it on many domains. Here's how to do this: +In some situations we define an SPF setting once and want to reuse it on many domains. Here's how to do this: {% code title="dnsconfig.js" %} ```javascript diff --git a/documentation/language-reference/domain-modifiers/TXT.md b/documentation/language-reference/domain-modifiers/TXT.md index 03cf7ab485..ed03be91e7 100644 --- a/documentation/language-reference/domain-modifiers/TXT.md +++ b/documentation/language-reference/domain-modifiers/TXT.md @@ -10,15 +10,11 @@ parameter_types: "modifiers...": RecordModifier[] --- -`TXT` adds a [Text record](https://www.rfc-editor.org/rfc/rfc1035) to a domain. The name should be the relative -label for the record. Use `@` for the domain apex. +`TXT` adds a [Text record](https://www.rfc-editor.org/rfc/rfc1035) to a domain. The name should be the relative label for the record. Use `@` for the domain apex. -The contents is either a single or multiple strings. To -specify multiple strings, specify them as an array. +The contents is either a single or multiple strings. To specify multiple strings, specify them as an array. -Each string is a JavaScript string (quoted using single or double -quotes). The (somewhat complex) quoting rules of the DNS protocol -will be done for you. +Each string is a JavaScript string (quoted using single or double quotes). The (somewhat complex) quoting rules of the DNS protocol will be done for you. Modifiers can be any number of [record modifiers](https://docs.dnscontrol.org/language-reference/record-modifiers) or JSON objects, which will be merged into the record's metadata. @@ -42,72 +38,34 @@ Modifiers can be any number of [record modifiers](https://docs.dnscontrol.org/la ### Long strings -Strings that are longer than 255 octets (bytes) will be quietly -split into 255-octets chunks or the provider may report an error -if it does not handle multiple strings. - +Strings that are longer than 255 octets (bytes) will be quietly split into 255-octets chunks or the provider may report an error if it does not handle multiple strings. ### TXT record edge cases -Most providers do not support the full possibilities of what a `TXT` -record can store. DNSControl can not handle all the edge cases -and incompatibles that providers have introduced. Instead, it -stores the string(s) that you provide and passes them to the provider -verbatim. The provider may opt to accept the data, fix it, or -reject it. This happens early in the processing, long before -the DNSControl talks to the provider's API. +Most providers do not support the full possibilities of what a `TXT` record can store. DNSControl can not handle all the edge cases and incompatibles that providers have introduced. Instead, it stores the string(s) that you provide and passes them to the provider verbatim. The provider may opt to accept the data, fix it, or reject it. This happens early in the processing, long before the DNSControl talks to the provider's API. -The RFCs specify that a `TXT` record stores one or more strings, -each is up to 255 octets (bytes) long. We call these individual -strings *chunks*. Each chunk may be zero to 255 octets long. -There is no limit to the number of chunks in a `TXT` record, -other than IP packet length restrictions. The contents of each chunk -may be octets of value from 0x00 to 0xff. +The RFCs specify that a `TXT` record stores one or more strings, each is up to 255 octets (bytes) long. We call these individual strings *chunks*. Each chunk may be zero to 255 octets long. There is no limit to the number of chunks in a `TXT` record, other than IP packet length restrictions. The contents of each chunk may be octets of value from 0x00 to 0xff. -In reality DNS Service Providers (DSPs) place many restrictions on `TXT` -records. +In reality DNS Service Providers (DSPs) place many restrictions on `TXT` records. -Some DSPs only support a single string of 255 octets or fewer. -Multiple strings, or any one string being longer than 255 octets will -result in an error. One provider limits the string to 254 octets, -which makes me think they're code has an off-by-one error. +Some DSPs only support a single string of 255 octets or fewer. Multiple strings, or any one string being longer than 255 octets will result in an error. One provider limits the string to 254 octets, which makes me think they're code has an off-by-one error. -Some DSPs only support one string, but it may be of any length. -Behind the scenes the provider splits it into 255-octet chunks -(except the last one, of course). +Some DSPs only support one string, but it may be of any length. Behind the scenes the provider splits it into 255-octet chunks (except the last one, of course). -Some DSPs support multiple strings, but API requests must be 512-bytes -or fewer, and with quoting, escaping, and other encoding mishegoss -you can't be sure what will be permitted until you actually try it. +Some DSPs support multiple strings, but API requests must be 512-bytes or fewer, and with quoting, escaping, and other encoding mishegoss you can't be sure what will be permitted until you actually try it. -Regardless of the quantity and length of strings, some providers ban -double quotes, back-ticks, or other chars. +Regardless of the quantity and length of strings, some providers ban double quotes, back-ticks, or other chars. ### Testing the support of a provider #### How can you tell if a provider will support a particular `TXT()` record? -Include the `TXT()` record in a [`D()`](../top-level-functions/D.md) as usual, along -with the `DnsProvider()` for that provider. Run `dnscontrol check` to -see if any errors are produced. The check command does not talk to -the provider's API, thus permitting you to do this without having an -account at that provider. +Include the `TXT()` record in a [`D()`](../top-level-functions/D.md) as usual, along with the `DnsProvider()` for that provider. Run `dnscontrol check` to see if any errors are produced. The check command does not talk to the provider's API, thus permitting you to do this without having an account at that provider. #### What if the provider rejects a string that is supported? -Suppose I can create the TXT record using the DSP's web portal but -DNSControl rejects the string? - -It is possible that the provider code in DNSControl rejects strings -that the DSP accepts. This is because the test is done in code, not -by querying the provider's API. It is possible that the code was -written to work around a bug (such as rejecting a string with a -back-tick) but now that bug has been fixed. - -All such checks are in `providers/${providername}/auditrecords.go`. -You can try removing the check that you feel is in error and see if -the provider's API accepts the record. You can do this by running the -integration tests, or by simply adding that record to an existing -`dnsconfig.js` and seeing if `dnscontrol push` is able to push that -record into production. (Be careful if you are testing this on a -domain used in production.) +Suppose I can create the TXT record using the DSP's web portal but DNSControl rejects the string? + +It is possible that the provider code in DNSControl rejects strings that the DSP accepts. This is because the test is done in code, not by querying the provider's API. It is possible that the code was written to work around a bug (such as rejecting a string with a back-tick) but now that bug has been fixed. + +All such checks are in `providers/${providername}/auditrecords.go`. You can try removing the check that you feel is in error and see if the provider's API accepts the record. You can do this by running the integration tests, or by simply adding that record to an existing `dnsconfig.js` and seeing if `dnscontrol push` is able to push that record into production. (Be careful if you are testing this on a domain used in production.) diff --git a/documentation/language-reference/top-level-functions/D.md b/documentation/language-reference/top-level-functions/D.md index 7a7c842538..a5700f7507 100644 --- a/documentation/language-reference/top-level-functions/D.md +++ b/documentation/language-reference/top-level-functions/D.md @@ -10,16 +10,13 @@ parameter_types: "modifiers...": DomainModifier[] --- -`D` adds a new Domain for DNSControl to manage. The first two arguments are required: the domain name (fully qualified `example.com` without a trailing dot), and the -name of the registrar (as previously declared with [NewRegistrar](NewRegistrar.md)). Any number of additional arguments may be included to add DNS Providers with [DNSProvider](NewDnsProvider.md), -add records with [A](../domain-modifiers/A.md), [CNAME](../domain-modifiers/CNAME.md), and so forth, or add metadata. +`D` adds a new Domain for DNSControl to manage. The first two arguments are required: the domain name (fully qualified `example.com` without a trailing dot), and the name of the registrar (as previously declared with [NewRegistrar](NewRegistrar.md)). Any number of additional arguments may be included to add DNS Providers with [DNSProvider](NewDnsProvider.md), add records with [A](../domain-modifiers/A.md), [CNAME](../domain-modifiers/CNAME.md), and so forth, or add metadata. Modifier arguments are processed according to type as follows: - A function argument will be called with the domain object as it's only argument. Most of the [built-in modifier functions](https://docs.dnscontrol.org/language-reference/domain-modifiers) return such functions. - An object argument will be merged into the domain's metadata collection. -- An array argument will have all of it's members evaluated recursively. This allows you to combine multiple common records or modifiers into a variable that can - be used like a macro in multiple domains. +- An array argument will have all of it's members evaluated recursively. This allows you to combine multiple common records or modifiers into a variable that can be used like a macro in multiple domains. {% code title="dnsconfig.js" %} ```javascript @@ -56,14 +53,9 @@ In the above example, `example.com` has an `A` record with the value `"1.2.3.4"` # `no_ns` -To prevent DNSControl from accidentally deleting your nameservers (at the -parent domain), registrar updates are disabled if the list of nameservers for a -zone (as computed from `dnsconfig.js`) is empty. +To prevent DNSControl from accidentally deleting your nameservers (at the parent domain), registrar updates are disabled if the list of nameservers for a zone (as computed from `dnsconfig.js`) is empty. -This can happen when a provider doesn't give any control over the apex NS -records, there are no default nameservers, there are no `NAMESERVER()` -statements, and the provider returns an empty list of nameservers (such as -Gandi and Vercel). +This can happen when a provider doesn't give any control over the apex NS records, there are no default nameservers, there are no `NAMESERVER()` statements, and the provider returns an empty list of nameservers (such as Gandi and Vercel). In this situation, you will see an error message such as: @@ -87,13 +79,9 @@ D("example.com", REG_MY_PROVIDER, {no_ns: "true"}, # Split Horizon DNS -DNSControl supports Split Horizon DNS. Simply -define the domain two or more times, each with -their own unique parameters. +DNSControl supports Split Horizon DNS. Simply define the domain two or more times, each with their own unique parameters. -To differentiate the different domains, specify the domains as -`domain.tld!tag`, such as `example.com!inside` and -`example.com!outside`. +To differentiate the different domains, specify the domains as `domain.tld!tag`, such as `example.com!inside` and `example.com!outside`. {% code title="dnsconfig.js" %} ```javascript @@ -115,17 +103,9 @@ D_EXTEND("example.com!inside", ``` {% endcode %} -A domain name without a `!` is assigned a tag that is the empty -string. For example, `example.com` and `example.com!` are equivalent. -However, we strongly recommend against using the empty tag, as it -risks creating confusion. In other words, if you have `domain.tld` -and `domain.tld!external` you now require humans to remember that -`domain.tld` is the external one. I mean... the internal one. You -may have noticed this mistake, but will your coworkers? Will you in -six months? You get the idea. - -DNSControl command line flag `--domains` matches the full name (with the "!"). If you -define domains `example.com!john`, `example.com!paul`, and `example.com!george` then: +A domain name without a `!` is assigned a tag that is the empty string. For example, `example.com` and `example.com!` are equivalent. However, we strongly recommend against using the empty tag, as it risks creating confusion. In other words, if you have `domain.tld` and `domain.tld!external` you now require humans to remember that `domain.tld` is the external one. I mean... the internal one. You may have noticed this mistake, but will your coworkers? Will you in six months? You get the idea. + +DNSControl command line flag `--domains` matches the full name (with the "!"). If you define domains `example.com!john`, `example.com!paul`, and `example.com!george` then: * `--domains=example.com` will not match any of the three. * `--domains='example.com!george'` will only match george. diff --git a/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE.md b/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE.md index 5dca9adaff..25cc4ad286 100644 --- a/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE.md +++ b/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE.md @@ -10,16 +10,9 @@ parameter_types: nameserver_names: string[] --- -`DOMAIN_ELSEWHERE()` is a helper macro that lets you easily indicate that -a domain's zones are managed elsewhere. That is, it permits you easily delegate -a domain to a hard-coded list of DNS servers. +`DOMAIN_ELSEWHERE()` is a helper macro that lets you easily indicate that a domain's zones are managed elsewhere. That is, it permits you easily delegate a domain to a hard-coded list of DNS servers. -`DOMAIN_ELSEWHERE` is useful when you control a domain's registrar but not the -DNS servers. For example, suppose you own a domain but the DNS servers are run -by someone else, perhaps a SaaS product you've subscribed to or a DNS server -that is run by your brother-in-law who doesn't trust you with the API keys that -would let you maintain the domain using DNSControl. You need an easy way to -point (delegate) the domain at a specific list of DNS servers. +`DOMAIN_ELSEWHERE` is useful when you control a domain's registrar but not the DNS servers. For example, suppose you own a domain but the DNS servers are run by someone else, perhaps a SaaS product you've subscribed to or a DNS server that is run by your brother-in-law who doesn't trust you with the API keys that would let you maintain the domain using DNSControl. You need an easy way to point (delegate) the domain at a specific list of DNS servers. For example these two statements are equivalent: diff --git a/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE_AUTO.md b/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE_AUTO.md index 49e4a2ccf4..25efbe2990 100644 --- a/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE_AUTO.md +++ b/documentation/language-reference/top-level-functions/DOMAIN_ELSEWHERE_AUTO.md @@ -12,19 +12,11 @@ parameter_types: dns provider: string --- -`DOMAIN_ELSEWHERE_AUTO()` is similar to `DOMAIN_ELSEWHERE()` but instead of -a hardcoded list of nameservers, a DnsProvider() is queried. +`DOMAIN_ELSEWHERE_AUTO()` is similar to `DOMAIN_ELSEWHERE()` but instead of a hardcoded list of nameservers, a DnsProvider() is queried. -`DOMAIN_ELSEWHERE_AUTO` is useful when you control a domain's registrar but the -DNS zones are managed by another system. Luckily you have enough access to that -other system that you can query it to determine the zone's nameservers. +`DOMAIN_ELSEWHERE_AUTO` is useful when you control a domain's registrar but the DNS zones are managed by another system. Luckily you have enough access to that other system that you can query it to determine the zone's nameservers. -For example, suppose you own a domain but the DNS servers for it are in Azure. -Further suppose that something in Azure maintains the zones (automatic or -human). Azure picks the nameservers for the domains automatically, and that -list may change occasionally. `DOMAIN_ELSEWHERE_AUTO` allows you to easily -query Azure to determine the domain's delegations so that you do not need to -hard-code them in your dnsconfig.js file. +For example, suppose you own a domain but the DNS servers for it are in Azure. Further suppose that something in Azure maintains the zones (automatic or human). Azure picks the nameservers for the domains automatically, and that list may change occasionally. `DOMAIN_ELSEWHERE_AUTO` allows you to easily query Azure to determine the domain's delegations so that you do not need to hard-code them in your dnsconfig.js file. For example these two statements are equivalent: diff --git a/documentation/language-reference/top-level-functions/D_EXTEND.md b/documentation/language-reference/top-level-functions/D_EXTEND.md index 86c2998a27..f70f60e993 100644 --- a/documentation/language-reference/top-level-functions/D_EXTEND.md +++ b/documentation/language-reference/top-level-functions/D_EXTEND.md @@ -8,30 +8,15 @@ parameter_types: "modifiers...": DomainModifier[] --- -`D_EXTEND` adds records (and metadata) to a domain previously defined -by [`D()`](D.md). It can also be used to add subdomain records (and metadata) -to a previously defined domain. +`D_EXTEND` adds records (and metadata) to a domain previously defined by [`D()`](D.md). It can also be used to add subdomain records (and metadata) to a previously defined domain. -The first argument is a domain name. If it exactly matches a -previously defined domain, `D_EXTEND()` behaves the same as [`D()`](D.md), -simply adding records as if they had been specified in the original -[`D()`](D.md). +The first argument is a domain name. If it exactly matches a previously defined domain, `D_EXTEND()` behaves the same as [`D()`](D.md), simply adding records as if they had been specified in the original [`D()`](D.md). -If the domain name does not match an existing domain, but could be a -(non-delegated) subdomain of an existing domain, the new records (and -metadata) are added with the subdomain part appended to all record -names (labels), and targets (as appropriate). See the examples below. +If the domain name does not match an existing domain, but could be a (non-delegated) subdomain of an existing domain, the new records (and metadata) are added with the subdomain part appended to all record names (labels), and targets (as appropriate). See the examples below. -Matching the domain name to previously-defined domains is done using a -`longest match` algorithm. If `domain.tld` and `sub.domain.tld` are -defined as separate domains via separate [`D()`](D.md) statements, then -`D_EXTEND("sub.sub.domain.tld", ...)` would match `sub.domain.tld`, -not `domain.tld`. +Matching the domain name to previously-defined domains is done using a `longest match` algorithm. If `domain.tld` and `sub.domain.tld` are defined as separate domains via separate [`D()`](D.md) statements, then `D_EXTEND("sub.sub.domain.tld", ...)` would match `sub.domain.tld`, not `domain.tld`. -Some operators only act on an apex domain (e.g. -[`CF_SINGLE_REDIRECT`](../domain-modifiers/CF_SINGLE_REDIRECT.md), -[`CF_REDIRECT`](../domain-modifiers/CF_REDIRECT.md), and [`CF_TEMP_REDIRECT`](../domain-modifiers/CF_TEMP_REDIRECT.md)). Using them -in a `D_EXTEND` subdomain may not be what you expect. +Some operators only act on an apex domain (e.g. [`CF_SINGLE_REDIRECT`](../domain-modifiers/CF_SINGLE_REDIRECT.md), [`CF_REDIRECT`](../domain-modifiers/CF_REDIRECT.md), and [`CF_TEMP_REDIRECT`](../domain-modifiers/CF_TEMP_REDIRECT.md)). Using them in a `D_EXTEND` subdomain may not be what you expect. {% code title="dnsconfig.js" %} ```javascript @@ -80,11 +65,4 @@ This will end up in the following modifications: (This output assumes the `--ful #12: CREATE CNAME i.sub.domain.tld j.sub.domain.tld. ``` -ProTips: `D_EXTEND()` permits you to create very complex and -sophisticated configurations, but you shouldn't. Be nice to the next -person that edits the file, who may not be as expert as yourself. -Enhance readability by putting any `D_EXTEND()` statements immediately -after the original [`D()`](D.md), like in above example. Avoid the temptation -to obscure the addition of records to existing domains with randomly -placed `D_EXTEND()` statements. Don't build up a domain using loops of -`D_EXTEND()` statements. You'll be glad you didn't. +ProTips: `D_EXTEND()` permits you to create very complex and sophisticated configurations, but you shouldn't. Be nice to the next person that edits the file, who may not be as expert as yourself. Enhance readability by putting any `D_EXTEND()` statements immediately after the original [`D()`](D.md), like in above example. Avoid the temptation to obscure the addition of records to existing domains with randomly placed `D_EXTEND()` statements. Don't build up a domain using loops of `D_EXTEND()` statements. You'll be glad you didn't. diff --git a/documentation/language-reference/top-level-functions/REV.md b/documentation/language-reference/top-level-functions/REV.md index d054b5aaf1..6c3e58a758 100644 --- a/documentation/language-reference/top-level-functions/REV.md +++ b/documentation/language-reference/top-level-functions/REV.md @@ -7,9 +7,7 @@ parameter_types: ts_return: string --- -`REV` returns the reverse lookup domain for an IP network. For -example `REV("1.2.3.0/24")` returns `3.2.1.in-addr.arpa.` and -`REV("2001:db8:302::/48")` returns `2.0.3.0.8.b.d.0.1.0.0.2.ip6.arpa.`. +`REV` returns the reverse lookup domain for an IP network. For example `REV("1.2.3.0/24")` returns `3.2.1.in-addr.arpa.` and `REV("2001:db8:302::/48")` returns `2.0.3.0.8.b.d.0.1.0.0.2.ip6.arpa.`. `REV()` is commonly used with the [`D()`](D.md) functions to create reverse DNS lookup zones. @@ -29,27 +27,19 @@ D(REV("1.2.3.0/24", ... The latter is easier to type and less error-prone. -If the address does not include a "/" then `REV()` assumes /32 for IPv4 addresses -and /128 for IPv6 addresses. +If the address does not include a "/" then `REV()` assumes /32 for IPv4 addresses and /128 for IPv6 addresses. # RFC compliance -`REV()` implements both RFC 2317 and the newer RFC 4183. The `REVCOMPAT()` -function selects which mode is used. If `REVCOMPAT()` is not called, a default -is selected for you. The default will change to RFC 4183 in DNSControl v5.0. +`REV()` implements both RFC 2317 and the newer RFC 4183. The `REVCOMPAT()` function selects which mode is used. If `REVCOMPAT()` is not called, a default is selected for you. The default will change to RFC 4183 in DNSControl v5.0. See [`REVCOMPAT()`](REVCOMPAT.md) for details. - # Host bits -v4.x: -The host bits (the ones outside the netmask) must be zeros. They are not zeroed -out automatically. Thus, `REV("1.2.3.4/24")` is an error. +v4.x: The host bits (the ones outside the netmask) must be zeros. They are not zeroed out automatically. Thus, `REV("1.2.3.4/24")` is an error. -v5.0 and later: -The host bits (the ones outside the netmask) are ignored. Thus -`REV("1.2.3.4/24")` and `REV("1.2.3.0/24")` are equivalent. +v5.0 and later: The host bits (the ones outside the netmask) are ignored. Thus `REV("1.2.3.4/24")` and `REV("1.2.3.0/24")` are equivalent. # Examples @@ -76,6 +66,4 @@ D(REV("2001:db8:302::/48"), REGISTRAR, DnsProvider(BIND), # Automatic forward and reverse record generation -DNSControl does not automatically generate forward and reverse lookups. However -it is possible to write a macro that does this. See -[`PTR()`](../domain-modifiers/PTR.md) for an example. +DNSControl does not automatically generate forward and reverse lookups. However it is possible to write a macro that does this. See [`PTR()`](../domain-modifiers/PTR.md) for an example. diff --git a/documentation/language-reference/top-level-functions/REVCOMPAT.md b/documentation/language-reference/top-level-functions/REVCOMPAT.md index e26b172800..374aeb023c 100644 --- a/documentation/language-reference/top-level-functions/REVCOMPAT.md +++ b/documentation/language-reference/top-level-functions/REVCOMPAT.md @@ -18,20 +18,15 @@ REVCOMPAT("rfc4183"); // RFC 4183: Adopt the newer standard. ``` {% endcode %} -`REVCOMPAT()` is global for all of `dnsconfig.js`. It must appear before any -use of `REV()`; If not, behavior is undefined. +`REVCOMPAT()` is global for all of `dnsconfig.js`. It must appear before any use of `REV()`; If not, behavior is undefined. # RFC 4183 vs RFC 2317 -RFC 2317 and RFC 4183 are two different ways to implement reverse lookups for -CIDR blocks that are not on 8-bit boundaries (/24, /16, /8). +RFC 2317 and RFC 4183 are two different ways to implement reverse lookups for CIDR blocks that are not on 8-bit boundaries (/24, /16, /8). -Originally DNSControl implemented the older standard, which only specifies what -to do for /8, /16, /24 - /32. Using `REV()` for /9-17 and /17-23 CIDRs was an -error. +Originally DNSControl implemented the older standard, which only specifies what to do for /8, /16, /24 - /32. Using `REV()` for /9-17 and /17-23 CIDRs was an error. -v4 defaults to RFC 2317. In v5.0 the default will change to RFC 4183. -`REVCOMPAT()` is provided for those that wish to retain the old behavior. +v4 defaults to RFC 2317. In v5.0 the default will change to RFC 4183. `REVCOMPAT()` is provided for those that wish to retain the old behavior. For more information, see [Opinion #9](../../advanced-features/opinions.md#opinion-9-rfc-4183-is-better-than-rfc-2317). diff --git a/documentation/language-reference/top-level-functions/require.md b/documentation/language-reference/top-level-functions/require.md index b7d8622381..9bbbf2a1c1 100644 --- a/documentation/language-reference/top-level-functions/require.md +++ b/documentation/language-reference/top-level-functions/require.md @@ -5,26 +5,17 @@ parameters: ts_ignore: true --- -`require(...)` loads the specified JavaScript, JSON, or JSON5 file, allowing -to split your configuration across multiple files. +`require(...)` loads the specified JavaScript, JSON, or JSON5 file, allowing to split your configuration across multiple files. A better name for this function might be "include". -If the supplied `path` string ends with `.js`, the file is interpreted -as JavaScript code, almost as though its contents had been included in -the currently-executing file. If the path string ends with `.json` or `.json5` (case insensitive), -`require()` returns the `JSON.parse()` of the file's contents. +If the supplied `path` string ends with `.js`, the file is interpreted as JavaScript code, almost as though its contents had been included in the currently-executing file. If the path string ends with `.json` or `.json5` (case insensitive), `require()` returns the `JSON.parse()` of the file's contents. -If the path string begins with a `./`, it is interpreted relative to -the currently-loading file (which may not be the file where the -`require()` statement is, if called within a function). Otherwise it -is interpreted relative to the program's working directory at the time -of the call. +If the path string begins with a `./`, it is interpreted relative to the currently-loading file (which may not be the file where the `require()` statement is, if called within a function). Otherwise it is interpreted relative to the program's working directory at the time of the call. ### Example 1: Simple -In this example, we separate our macros in one file, and put groups of domains -in 3 other files. The result is a cleaner separation of code vs. domains. +In this example, we separate our macros in one file, and put groups of domains in 3 other files. The result is a cleaner separation of code vs. domains. {% code title="dnsconfig.js" %} ```javascript @@ -109,18 +100,10 @@ for (var domain in domains) { ``` {% endcode %} -JSON5 works the same way, but the filename ends in `.json5`. (Note: JSON5 -features are supported whether the filename ends with `.json` or `.json5`. -However please don't rely on JSON5 features in a `.json` file as this may -change some day.) +JSON5 works the same way, but the filename ends in `.json5`. (Note: JSON5 features are supported whether the filename ends with `.json` or `.json5`. However please don't rely on JSON5 features in a `.json` file as this may change some day.) # Notes -`require()` is *much* closer to PHP's `include()` function than it -is to node's `require()`. +`require()` is *much* closer to PHP's `include()` function than it is to node's `require()`. -Node's `require()` only includes a file once. -In contrast, DNSControl's `require()` is actually an imperative command to -load the file and execute the code or parse the data from it. For example if -two files both `require("./tools.js")`, then it will be -loaded twice, whereas in node.js it would only be loaded once. +Node's `require()` only includes a file once. In contrast, DNSControl's `require()` is actually an imperative command to load the file and execute the code or parse the data from it. For example if two files both `require("./tools.js")`, then it will be loaded twice, whereas in node.js it would only be loaded once. diff --git a/documentation/language-reference/why-the-dot.md b/documentation/language-reference/why-the-dot.md index 85e9f5f5b7..3275a591c2 100644 --- a/documentation/language-reference/why-the-dot.md +++ b/documentation/language-reference/why-the-dot.md @@ -21,11 +21,7 @@ People are often confused about this error message: 1: ERROR: target (ghs.googlehosted.com) includes a (.), must end with a (.) ``` -What this means is that CNAME/MX/NS records (anything where -the "target" is a hostname) must end with a "." to indicate -that it is a FQDN. The exception to this is that if it is -simply a "short name" (i.e. no dots) then DNSControl will -add the domain to it. +What this means is that CNAME/MX/NS records (anything where the "target" is a hostname) must end with a "." to indicate that it is a FQDN. The exception to this is that if it is simply a "short name" (i.e. no dots) then DNSControl will add the domain to it. Here are four examples: @@ -38,74 +34,36 @@ Here are four examples: ``` {% endcode %} - -The first 2 examples are permitted. The last 2 examples are -ambiguous and are therefore are considered errors. +The first 2 examples are permitted. The last 2 examples are ambiguous and are therefore are considered errors. How are they ambiguous? - * Should $DOMAIN be added to "bar.com"? Well, obviously not, because it already ends with ".com" and we all know that "bar.com.bar.com" is probably not what they want. No, it isn't that obvious! Why? (see the next bullet point) - * Should $DOMAIN be added to "meta.xyz"? Everyone knows that ".xyz" isn't a TLD. Obviously, yes, $DOMAIN should be appended. However, wait... ".xyz" became a TLD in June 2014. We don't want to be surprised by changes like that. Also, users should not be required to memorize all the TLDs. (In the old days it was reasonable to expect people to memorize the 7 TLDs (gov/edu/com/mil/org/net) but since 2000 that's all changed. By the way, we forgot to include "int" in the original and you didn't notice.) - * What if the CNAME target is "www.bar.com" and the domain is "bar.com"? Then It is reasonable to infer the user's intent, right? `www.bar.com.bar.com.` would be silly, right? Maybe. What if we are copying 100 lines of `dnsconfig.js` from one `D()` to another. Buried in the middle is this one CNAME that means something entirely different when in a new $DOMAIN. That would be bad. We've seen this in production and want to prevent this kind of error. - -Yes, we could layer rule upon rule upon rule. Eventually we'd get -all the rules right. However, now a user would have to know all the -rules to be able to use DNSControl. The point of the DNSControl DSL -is to enable the casual user to be able to make DNS updates. By -"casual user" we do not mean someone someone that lives and breathes DNS -like you and I do. In fact, we mean someone that hasn't memorized -the list of rules. - -We know of no time where a human intentionally wanted -"foo.example.com.domain.com" as the target of an MX record. -In fact, the opposite is true. StackExchange.com had -a big email outage in 2013 because MX records were updated and the -"trailing dot" was forgotten. Our MX records became -"aspmx.l.google.com.stackexchange.com" and due to a high TTL we -lost email for a few hours. Recently (2017) we had a similar problem -and it delayed a new service from working. Luckily this was a new -service and didn't have existing users so the problem was unnoticed -except for the fact that a project schedule slipped by 3 days. - -Therefore, we prefer the rule to be "when in doubt, error out". It -is less to remember and catches errors. It also doesn't remove -the expressiveness of the language. One dot is better than 100 rules. + * Should $DOMAIN be added to "bar.com"? Well, obviously not, because it already ends with ".com" and we all know that "bar.com.bar.com" is probably not what they want. No, it isn't that obvious! Why? (see the next bullet point) + * Should $DOMAIN be added to "meta.xyz"? Everyone knows that ".xyz" isn't a TLD. Obviously, yes, $DOMAIN should be appended. However, wait... ".xyz" became a TLD in June 2014. We don't want to be surprised by changes like that. Also, users should not be required to memorize all the TLDs. (In the old days it was reasonable to expect people to memorize the 7 TLDs (gov/edu/com/mil/org/net) but since 2000 that's all changed. By the way, we forgot to include "int" in the original and you didn't notice.) + * What if the CNAME target is "www.bar.com" and the domain is "bar.com"? Then It is reasonable to infer the user's intent, right? `www.bar.com.bar.com.` would be silly, right? Maybe. What if we are copying 100 lines of `dnsconfig.js` from one `D()` to another. Buried in the middle is this one CNAME that means something entirely different when in a new $DOMAIN. That would be bad. We've seen this in production and want to prevent this kind of error. + +Yes, we could layer rule upon rule upon rule. Eventually we'd get all the rules right. However, now a user would have to know all the rules to be able to use DNSControl. The point of the DNSControl DSL is to enable the casual user to be able to make DNS updates. By "casual user" we do not mean someone someone that lives and breathes DNS like you and I do. In fact, we mean someone that hasn't memorized the list of rules. +We know of no time where a human intentionally wanted "foo.example.com.domain.com" as the target of an MX record. In fact, the opposite is true. StackExchange.com had a big email outage in 2013 because MX records were updated and the "trailing dot" was forgotten. Our MX records became "aspmx.l.google.com.stackexchange.com" and due to a high TTL we lost email for a few hours. Recently (2017) we had a similar problem and it delayed a new service from working. Luckily this was a new service and didn't have existing users so the problem was unnoticed except for the fact that a project schedule slipped by 3 days. + +Therefore, we prefer the rule to be "when in doubt, error out". It is less to remember and catches errors. It also doesn't remove the expressiveness of the language. One dot is better than 100 rules. ## Simple mental models are better SRE ... the R stands for reliability. -A big source of human error is mental-model mismatch. That is, when -operating a complex system, the user has a mental model of -what is going on in the system. They are, essentially, emulating -the software in their head to predict that the change they are -making will have the result they seek. The more complex the -system the less likely the mental model will match reality. - -A mental model mismatch leads to confusion, frustration, and -more importantly it increases the risk of operating error the creates -production problems. +A big source of human error is mental-model mismatch. That is, when operating a complex system, the user has a mental model of what is going on in the system. They are, essentially, emulating the software in their head to predict that the change they are making will have the result they seek. The more complex the system the less likely the mental model will match reality. -If the rules are simple, the mental model will be more accurate -than if it is complex. "If something is ambiguous, we give an error -and tell you to add a dot to the end" is *simple.* "If something -is ambiguous, we follow this list of 100 rules that decide what -the user had intended" is *complex.* +A mental model mismatch leads to confusion, frustration, and more importantly it increases the risk of operating error the creates production problems. -One could argue that your users are very smart and can memorize -all the rules. Why should they have to? It's just a single keystroke! +If the rules are simple, the mental model will be more accurate than if it is complex. "If something is ambiguous, we give an error and tell you to add a dot to the end" is *simple.* "If something is ambiguous, we follow this list of 100 rules that decide what the user had intended" is *complex.* +One could argue that your users are very smart and can memorize all the rules. Why should they have to? It's just a single keystroke! ## Future We welcome proposals for how to resolve this ambiguity. -["Future proofing is not adding stuff. Future proofing is making sure you can easily add code/features without breaking existing functionality."](http://softwareengineering.stackexchange.com/a/79591/116123) -By not solving the problem now, we open the door to upwards compatible -solutions. If we created a partial solution now, we might prevent -future solutions from being upward compatible. By simply giving an -error we open the door to new solutions. +["Future proofing is not adding stuff. Future proofing is making sure you can easily add code/features without breaking existing functionality."](http://softwareengineering.stackexchange.com/a/79591/116123) By not solving the problem now, we open the door to upwards compatible solutions. If we created a partial solution now, we might prevent future solutions from being upward compatible. By simply giving an error we open the door to new solutions. -We should warn you, however, that any new proposals should be -simpler than "add a dot". +We should warn you, however, that any new proposals should be simpler than "add a dot". diff --git a/documentation/provider/akamaiedgedns.md b/documentation/provider/akamaiedgedns.md index db42d2b74d..05477f04b6 100644 --- a/documentation/provider/akamaiedgedns.md +++ b/documentation/provider/akamaiedgedns.md @@ -1,17 +1,12 @@ -"Akamai Edge DNS Provider" configures Akamai's -[Edge DNS](https://www.akamai.com/products/edge-dns) service. +"Akamai Edge DNS Provider" configures Akamai's [Edge DNS](https://www.akamai.com/products/edge-dns) service. -This provider interacts with Edge DNS via the -[Edge DNS Zone Management API](https://techdocs.akamai.com/edge-dns/reference/edge-dns-api). +This provider interacts with Edge DNS via the [Edge DNS Zone Management API](https://techdocs.akamai.com/edge-dns/reference/edge-dns-api). -Before you can use this provider, you need to create an "API Client" with authorization to use the -[Edge DNS Zone Management API](https://techdocs.akamai.com/edge-dns/reference/edge-dns-api). +Before you can use this provider, you need to create an "API Client" with authorization to use the [Edge DNS Zone Management API](https://techdocs.akamai.com/edge-dns/reference/edge-dns-api). -See the "Get Started" section of [Edge DNS Zone Management API](https://techdocs.akamai.com/edge-dns/reference/edge-dns-api), -which says, "To enable this API, choose the API service named DNS—Zone Record Management, and set the access level to READ-WRITE." +See the "Get Started" section of [Edge DNS Zone Management API](https://techdocs.akamai.com/edge-dns/reference/edge-dns-api), which says, "To enable this API, choose the API service named DNS—Zone Record Management, and set the access level to READ-WRITE." -Follow directions at [Authenticate With EdgeGrid](https://www.akamai.com/developer) to generate -the required credentials. +Follow directions at [Authenticate With EdgeGrid](https://www.akamai.com/developer) to generate the required credentials. ## Configuration @@ -54,8 +49,7 @@ The AKAMAITLC record can only be used at the zone apex (`@`). The AKAMAITLC record can only be used once per zone. #### ALIAS -Akamai Edge DNS does directly support `ALIAS` records. This provider will convert `ALIAS` records used at the -zone apex (`@`) to `AKAMAITLC` records, and any other names to `CNAME` records. +Akamai Edge DNS does directly support `ALIAS` records. This provider will convert `ALIAS` records used at the zone apex (`@`) to `AKAMAITLC` records, and any other names to `CNAME` records. ### Secondary zones @@ -64,8 +58,7 @@ This provider only supports creating primary zones in Akamai. If a secondary zon ## Usage Store your zone configuration details in a dnsconfig.js file in the same folder where the creds.json file is present. -Akamai assigns a unique set of authoritative nameservers for each contract. These authorities should be -used as the NS records on all zones belonging to this contract. +Akamai assigns a unique set of authoritative nameservers for each contract. These authorities should be used as the NS records on all zones belonging to this contract. The NS records for these authorities have a TTL of 86400. @@ -99,8 +92,7 @@ D("example.com", REG_NONE, DnsProvider(DSP_AKAMAIEDGEDNS), **Note:** TTL for AKAMAICDN record must always be set to 20. -AKAMAICDN is a proprietary record type that is used to configure [Zone Apex Mapping](https://www.akamai.com/blog/security/edge-dns--zone-apex-mapping---dnssec). -The AKAMAICDN target must be preconfigured in the Akamai network. +AKAMAICDN is a proprietary record type that is used to configure [Zone Apex Mapping](https://www.akamai.com/blog/security/edge-dns--zone-apex-mapping---dnssec). The AKAMAICDN target must be preconfigured in the Akamai network. ### dnscontrol check command ```shell @@ -173,7 +165,6 @@ Command: dnscontrol preview --populate-on-preview ``` - Output: ``` ******************** Domain: example.com @@ -198,7 +189,6 @@ Serially Gathering: "example.com" ``` In the above example since, the zone `example.com` did not exist, running `dnscontrol preview` with the `--populate-on-preview` flag created a zone named example.com with only the NS and SOA records and showed what changes will be applied by `dnscontrol push`. - ### dnscontrol push command ```shell dnscontrol push @@ -356,4 +346,3 @@ Created zone: example_3.com GroupId: NNNNN ``` - diff --git a/documentation/provider/axfrddns.md b/documentation/provider/axfrddns.md index e4841f740f..353e1abef8 100644 --- a/documentation/provider/axfrddns.md +++ b/documentation/provider/axfrddns.md @@ -1,12 +1,6 @@ -This provider uses the native DNS protocols. It uses the AXFR (RFC5936, -Zone Transfer Protocol) protocol to retrieve existing records and uses DDNS -(RFC2136, Dynamic Update) to make updates. It can use both TSIG (RFC2845) and -IP-based authentication (ACLs). +This provider uses the native DNS protocols. It uses the AXFR (RFC5936, Zone Transfer Protocol) protocol to retrieve existing records and uses DDNS (RFC2136, Dynamic Update) to make updates. It can use both TSIG (RFC2845) and IP-based authentication (ACLs). -It can work with any standards-compliant -authoritative DNS server. It has been tested with -[BIND](https://www.isc.org/bind/), [Knot](https://www.knot-dns.cz/), -and [Yadifa](https://yadifa.eu/home.html). +It can work with any standards-compliant authoritative DNS server. It has been tested with [BIND](https://www.isc.org/bind/), [Knot](https://www.knot-dns.cz/), and [Yadifa](https://yadifa.eu/home.html). ## Configuration @@ -16,16 +10,14 @@ To use this provider, add an entry to `creds.json` with `TYPE` set to `AXFRDDNS` Zone transfers and DDNS updates default to TCP when using this provider. -The following two parameters in `creds.json` allow switching -to TCP or TCP over TLS. +The following two parameters in `creds.json` allow switching to TCP or TCP over TLS. * `update-mode`: May contain `tcp` (the default), `udp`, or `tcp-tls`. * `transfer-mode`: May contain `tcp` (the default), or `tcp-tls`. ### Authentication -Authentication information is included in the `creds.json` entry for -the provider: +Authentication information is included in the `creds.json` entry for the provider: * `transfer-key`: If this exists, the value is used to authenticate AXFR transfers. * `update-key`: If this exists, the value is used to authenticate DDNS updates. @@ -44,13 +36,9 @@ For instance, your `creds.json` might look like: ``` {% endcode %} -If either key is missing, DNSControl defaults to IP-based ACL -authentication for that function. Including both keys is the most -secure option. Omitting both keys defaults to IP-based ACLs for all -operations, which is the least secure option. +If either key is missing, DNSControl defaults to IP-based ACL authentication for that function. Including both keys is the most secure option. Omitting both keys defaults to IP-based ACLs for all operations, which is the least secure option. -If distinct zones require distinct keys, you will need to instantiate the -provider once for each key: +If distinct zones require distinct keys, you will need to instantiate the provider once for each key: {% code title="dnsconfig.js" %} ```javascript @@ -80,12 +68,9 @@ And update `creds.json` accordingly: ### Default nameservers -The AXFR+DDNS provider can be configured with a list of default -nameservers. They will be added to all the zones handled by the -provider. +The AXFR+DDNS provider can be configured with a list of default nameservers. They will be added to all the zones handled by the provider. -This list can be provided either as metadata or in `creds.json`. Only -the later allows `get-zones` to work properly. +This list can be provided either as metadata or in `creds.json`. Only the later allows `get-zones` to work properly. {% code title="dnsconfig.js" %} ```javascript @@ -114,14 +99,7 @@ var DSP_AXFRDDNS = NewDnsProvider("axfrddns", { ### Primary master -By default, the AXFR+DDNS provider will send the AXFR requests and the -DDNS updates to the first nameserver of the zone, usually known as the -"primary master". Typically, this is the first of the default -nameservers. Though, on some networks, the primary master is a private -node, hidden behind slaves, and it does not appear in the `NS` records -of the zone. In that case, the IP or the name of the primary server -must be provided in `creds.json`. With this option, a non-standard -port might be used. +By default, the AXFR+DDNS provider will send the AXFR requests and the DDNS updates to the first nameserver of the zone, usually known as the "primary master". Typically, this is the first of the default nameservers. Though, on some networks, the primary master is a private node, hidden behind slaves, and it does not appear in the `NS` records of the zone. In that case, the IP or the name of the primary server must be provided in `creds.json`. With this option, a non-standard port might be used. {% code title="creds.json" %} ```json @@ -134,9 +112,7 @@ port might be used. ``` {% endcode %} -When no nameserver appears in the zone, and no default nameservers nor -custom master are configured, the AXFR+DDNS provider will fail with -the following error message: +When no nameserver appears in the zone, and no default nameservers nor custom master are configured, the AXFR+DDNS provider will fail with the following error message: ```text [Error] AXFRDDNS: the nameservers list cannot be empty. @@ -145,10 +121,7 @@ Please consider adding default `nameservers` or an explicit `master` in `creds.j ### Transfer/AXFR server -As mentioned above, the AXFR+DDNS provider will send AXFR requests to the -primary master for the zone. On some networks, AXFR requests are handled -by a different server than DDNS requests. Use the `transfer-server` option in -`creds.json`. If not specified, it falls back to the primary master. +As mentioned above, the AXFR+DDNS provider will send AXFR requests to the primary master for the zone. On some networks, AXFR requests are handled by a different server than DDNS requests. Use the `transfer-server` option in `creds.json`. If not specified, it falls back to the primary master. {% code title="creds.json" %} ```json @@ -163,8 +136,7 @@ by a different server than DDNS requests. Use the `transfer-server` option in ### Example: local testing -When testing `dnscontrol` against a local nameserver, you might use -the following minimal configuration: +When testing `dnscontrol` against a local nameserver, you might use the following minimal configuration: {% code title="creds.json" %} ```json @@ -192,14 +164,11 @@ D("example.com", REG_NONE, DnsProvider(DNS), ``` {% endcode %} - ## Server configuration examples ### Bind9 -This is a sample `named.conf` example for an authoritative server hosting the -zone `example.com`. It uses a simple IP-based ACL for the AXFR -transfer and a conjunction of TSIG and IP-based ACL for the updates. +This is a sample `named.conf` example for an authoritative server hosting the zone `example.com`. It uses a simple IP-based ACL for the AXFR transfer and a conjunction of TSIG and IP-based ACL for the updates. {% code title="named.conf" %} ```text @@ -249,12 +218,9 @@ key update-key-id { ## FYI: get-zones -When using `get-zones`, a custom master or a list of default -nameservers should be configured in `creds.json`. +When using `get-zones`, a custom master or a list of default nameservers should be configured in `creds.json`. -The AXFR+DDNS provider does not display DNSSEC records. But, if any -DNSSEC records are found in the zone, it will replace all of them with -a single placeholder record: +The AXFR+DDNS provider does not display DNSSEC records. But, if any DNSSEC records are found in the zone, it will replace all of them with a single placeholder record: ```text __dnssec IN TXT "Domain has DNSSec records, not displayed here." diff --git a/documentation/provider/bind.md b/documentation/provider/bind.md index 2921083cc4..d15171a7b2 100644 --- a/documentation/provider/bind.md +++ b/documentation/provider/bind.md @@ -1,10 +1,6 @@ -This provider maintains a directory with a collection of .zone files -as appropriate for ISC BIND, and other systems that use the RFC 1035 -zone-file format. - -This provider does not generate or update the named.conf file, nor does it deploy the .zone files to the BIND master. -Both of those tasks are different at each site, so they are best done by a locally-written script. +This provider maintains a directory with a collection of .zone files as appropriate for ISC BIND, and other systems that use the RFC 1035 zone-file format. +This provider does not generate or update the named.conf file, nor does it deploy the .zone files to the BIND master. Both of those tasks are different at each site, so they are best done by a locally-written script. ## Configuration @@ -28,11 +24,7 @@ Example: ``` {% endcode %} -As of v4.2.0 `dnscontrol push` will create subdirectories along the path to -the filename. This includes both the portion of the path created by the -`directory` setting and the `filenameformat` setting. For security reasons, the -automatic creation of subdirectories is disabled if `dnscontrol` is running as -root. (Running DNSControl as root is not recommended in general.) +As of v4.2.0 `dnscontrol push` will create subdirectories along the path to the filename. This includes both the portion of the path created by the `directory` setting and the `filenameformat` setting. For security reasons, the automatic creation of subdirectories is disabled if `dnscontrol` is running as root. (Running DNSControl as root is not recommended in general.) ## Meta configuration @@ -75,7 +67,6 @@ Because BIND is unique, BIND's SOA support is kind of a hack. It leaves the SOA The `default_soa` values are only used when creating an SOA for the first time. The values are not used to update an SOA. Most people edit the SOA values by manually editing the zonefile or using the `SOA()` function. - # FYI: SOA serial numbers DNSControl maintains beautiful zone serial numbers. @@ -86,12 +77,9 @@ The good news is that DNSControl is smart enough to only increment a zone's seri DNSControl does not handle special serial number math such as "looping through zero" nor does it pay attention to the rules around the maximum delta permitted. Those are simply avoided because yyyymmdd99 fits in the first quadrant of the 32-bit serial number space. If you don't understand this paragraph consider yourself lucky; with DNSControl you don't need to. - # filenameformat -The `filenameformat` parameter specifies the file name to be used when -writing the zone file. The default (`%c.zone`) is acceptable in most cases: the -file name is the name as specified in the `D()` function plus ".zone". +The `filenameformat` parameter specifies the file name to be used when writing the zone file. The default (`%c.zone`) is acceptable in most cases: the file name is the name as specified in the `D()` function plus ".zone". The filenameformat is a string with a few printf-like `%` verbs: @@ -111,14 +99,9 @@ The filenameformat is a string with a few printf-like `%` verbs: | `%D` | (deprecated, use `%r`) mangles Unicode (risky!) | `example.com` | `example.com` | `рф.com` | * `%?x` is typically used to generate an optional `!` or `_` if there is a tag. -* `%r` is considered "risky" because it can produce a domain name that is not - canonical. For example, if you use `D("FOO.com")` and later change it to `D("foo.com")`, your file names will change. +* `%r` is considered "risky" because it can produce a domain name that is not canonical. For example, if you use `D("FOO.com")` and later change it to `D("foo.com")`, your file names will change. * Format strings must not end with an incomplete `%` or `%?` -* Generating a filename without a tag is risky. For example, if the same - `dnsconfig.js` has `D("example.com!inside", DSP_BIND)` and - `D("example.com!outside", DSP_BIND)`, both will use the same filename. - DNSControl will write both zone files to the same file, flapping between the - two. No error or warning will be output. +* Generating a filename without a tag is risky. For example, if the same `dnsconfig.js` has `D("example.com!inside", DSP_BIND)` and `D("example.com!outside", DSP_BIND)`, both will use the same filename. DNSControl will write both zone files to the same file, flapping between the two. No error or warning will be output. Useful examples: @@ -131,30 +114,17 @@ Useful examples: Compatibility notes: -* `%D` should not be used. It downcases the string in a way that is probably - incompatible with Unicode characters. It is retained for compatibility with - pre-v4.28 releases. If your domain has capital Unicode characters, backwards - compatibility is not guaranteed. Use `%r` instead. +* `%D` should not be used. It downcases the string in a way that is probably incompatible with Unicode characters. It is retained for compatibility with pre-v4.28 releases. If your domain has capital Unicode characters, backwards compatibility is not guaranteed. Use `%r` instead. * `%U` relies on `%D` which is deprecated. Use `%c` instead. -* As of v4.28 the default format string changed from `%U.zone` to `%c.zone`. This - should only matter if your `D()` statements included non-ASCII (Unicode) - runes that were capitalized. -* If you are using pre-v4.28 releases the above table is slightly misleading - because uppercase ASCII letters do not always work. If you are using - pre-v4.28 releases, assume the above table lists `example.com` instead - of `EXAMpl.com`. +* As of v4.28 the default format string changed from `%U.zone` to `%c.zone`. This should only matter if your `D()` statements included non-ASCII (Unicode) runes that were capitalized. +* If you are using pre-v4.28 releases the above table is slightly misleading because uppercase ASCII letters do not always work. If you are using pre-v4.28 releases, assume the above table lists `example.com` instead of `EXAMpl.com`. # FYI: get-zones -The DNSControl `get-zones all` subcommand scans the directory for -any files named `*.zone` and assumes they are zone files. +The DNSControl `get-zones all` subcommand scans the directory for any files named `*.zone` and assumes they are zone files. ```shell dnscontrol get-zones --format=nameonly - BIND all ``` -If `filenameformat` is defined, `dnscontrol` makes a guess at which filenames -are zones by reversing the logic of the format string. It doesn't try very hard -to get this right, as getting it right in all situations is mathematically -impossible. Feel free to file an issue if find a situation where it doesn't -work. I love a challenge! +If `filenameformat` is defined, `dnscontrol` makes a guess at which filenames are zones by reversing the logic of the format string. It doesn't try very hard to get this right, as getting it right in all situations is mathematically impossible. Feel free to file an issue if find a situation where it doesn't work. I love a challenge! diff --git a/documentation/provider/cloudflareapi.md b/documentation/provider/cloudflareapi.md index b5c40e9ff0..cece74799b 100644 --- a/documentation/provider/cloudflareapi.md +++ b/documentation/provider/cloudflareapi.md @@ -31,8 +31,7 @@ Example: ### Debugging -Setting the envvar CLOUDFLAREAPI_DEBUG will output all HTTP requests and -replies. +Setting the envvar CLOUDFLAREAPI_DEBUG will output all HTTP requests and replies. ```shell export CLOUDFLAREAPI_DEBUG=1 @@ -46,8 +45,7 @@ NOTE: You can not mix the two authentication methods. If you try, DNSControl wi ### API Tokens (recommended) -The recommended (newer) method is to -provide a [Cloudflare API token](https://dash.cloudflare.com/profile/api-tokens). +The recommended (newer) method is to provide a [Cloudflare API token](https://dash.cloudflare.com/profile/api-tokens). This method is enabled by setting the `apitoken` value in `creds.json`: @@ -83,8 +81,7 @@ DNSControl requires the token to have the following permissions: ### Username+Key (not recommended) -The other (older, not recommended) method is to -provide your Cloudflare API username and access key. +The other (older, not recommended) method is to provide your Cloudflare API username and access key. This method is not recommended because these credentials give DNSControl access to everything (think of it as "super user" for your account). @@ -147,8 +144,7 @@ DEFAULTS( **Aliases:** -To make configuration files more readable and less prone to errors, -the following aliases are *pre-defined*: +To make configuration files more readable and less prone to errors, the following aliases are *pre-defined*: {% code title="dnsconfig.js" %} ```javascript @@ -222,8 +218,7 @@ D("example2.tld", REG_NONE, DnsProvider(DSP_CLOUDFLARE), {% endcode %} ## Populating new domains at Cloudflare -If a domain does not exist in your Cloudflare account, DNSControl -will automatically add it when `dnscontrol push` is executed. +If a domain does not exist in your Cloudflare account, DNSControl will automatically add it when `dnscontrol push` is executed. ## CNAME flattening @@ -388,8 +383,7 @@ var CF_MANAGE_TAGS = {"cloudflare_manage_tags": "true"}; ## Old-style vs new-style redirects -Old-style redirects uses the [Page Rules](https://developers.cloudflare.com/rules/page-rules/) product feature, which is [going away](https://developers.cloudflare.com/rules/reference/page-rules-migration/). In this mode, -`CF_REDIRECT` and `CF_TEMP_REDIRECT` functions generate Page Rules. +Old-style redirects uses the [Page Rules](https://developers.cloudflare.com/rules/page-rules/) product feature, which is [going away](https://developers.cloudflare.com/rules/reference/page-rules-migration/). In this mode, `CF_REDIRECT` and `CF_TEMP_REDIRECT` functions generate Page Rules. Enable it using: @@ -400,8 +394,7 @@ var DSP_CLOUDFLARE = NewDnsProvider("cloudflare", { }); ``` -New redirects uses the [Single Redirects](https://developers.cloudflare.com/rules/url-forwarding/) product feature. In this mode, -`CF_REDIRECT` and `CF_TEMP_REDIRECT` functions generates Single Redirects. +New redirects uses the [Single Redirects](https://developers.cloudflare.com/rules/url-forwarding/) product feature. In this mode, `CF_REDIRECT` and `CF_TEMP_REDIRECT` functions generates Single Redirects. Enable it using: @@ -418,9 +411,7 @@ as of v4.12.0 and may have bugs. Please test carefully. ### Conversion mode: -DNSControl can convert from old-style redirects (Page Rules) to new-style -redirect (Single Redirects). To enable this mode, set both `manage_redirects` -and `manage_single_redirects` to true. +DNSControl can convert from old-style redirects (Page Rules) to new-style redirect (Single Redirects). To enable this mode, set both `manage_redirects` and `manage_single_redirects` to true. {% hint style="warning" %} The conversion process only handles a few, very simple, patterns. @@ -428,27 +419,15 @@ See `providers/cloudflare/rtypes/cfsingleredirect/convert_test.go` for a list of supported. Please file bugs if you find problems. PRs welcome! {% endhint %} -In conversion mode, DNSControl takes `CF_REDIRECT`/`CF_TEMP_REDIRECT` -statements and turns each of them into two records: a Page Rules and an -equivalent Single Redirects rule. +In conversion mode, DNSControl takes `CF_REDIRECT`/`CF_TEMP_REDIRECT` statements and turns each of them into two records: a Page Rules and an equivalent Single Redirects rule. -Cloudflare processes Single Redirects before Page Rules, thus it is safe to -have both at the same time, and provides an easy way to test the new-style -rules. If they do not work properly, use the Cloudflare web-based control -panel to manually delete the new-style rule to expose the old-style rule. (and -report the bug to DNSControl!) +Cloudflare processes Single Redirects before Page Rules, thus it is safe to have both at the same time, and provides an easy way to test the new-style rules. If they do not work properly, use the Cloudflare web-based control panel to manually delete the new-style rule to expose the old-style rule. (and report the bug to DNSControl!) -You'll find the new-style rule in the Cloudflare control panel. It will have -a very long name that includes the `CF_REDIRECT`/`CF_TEMP_REDIRECT` operands -plus matcher and replacement expressions. +You'll find the new-style rule in the Cloudflare control panel. It will have a very long name that includes the `CF_REDIRECT`/`CF_TEMP_REDIRECT` operands plus matcher and replacement expressions. -There is no mechanism to easily delete the old-style rules. Either delete them -manually using the Cloudflare control panel or wait for Cloudflare to remove -the old-style Page Rule feature. +There is no mechanism to easily delete the old-style rules. Either delete them manually using the Cloudflare control panel or wait for Cloudflare to remove the old-style Page Rule feature. -Once the conversion is complete, change -`manage_redirects` to `false` then either delete the old redirects -via the CloudFlare control panel or wait for Cloudflare to remove support for the old-style feature. +Once the conversion is complete, change `manage_redirects` to `false` then either delete the old redirects via the CloudFlare control panel or wait for Cloudflare to remove support for the old-style feature. {% hint style="warning" %} Cloudflare's announcement says that they will convert old-style redirects (Page Rules) to new-style @@ -465,13 +444,9 @@ If you have suggestions on how to handle this better please file a bug. ### Converting to CF_SINGLE_REDIRECT permanently -DNSControl will help convert `CF_REDIRECT`/`CF_TEMP_REDIRECT` statements into -`CF_SINGLE_REDIRECT` statements. You might choose to do this if you do not want -to rely on the automatic translation, or if you want to edit the results of the -translation. +DNSControl will help convert `CF_REDIRECT`/`CF_TEMP_REDIRECT` statements into `CF_SINGLE_REDIRECT` statements. You might choose to do this if you do not want to rely on the automatic translation, or if you want to edit the results of the translation. -DNSControl will generate a file of the translated statements if you specify -a filename using the `transcode_log` meta option. +DNSControl will generate a file of the translated statements if you specify a filename using the `transcode_log` meta option. ```javascript var DSP_CLOUDFLARE = NewDnsProvider("cloudflare", { @@ -511,7 +486,6 @@ D("otherdomain.com", ... Copying the statements to the proper place in `dnsconfig.js` is manual. - ## Redirects The Cloudflare provider can manage "Forwarding URL" Page Rules (redirects) for your domains. Simply use the `CF_REDIRECT` and `CF_TEMP_REDIRECT` functions to make redirects: @@ -562,17 +536,13 @@ D("foo.com", REG_NONE, DnsProvider(DSP_CLOUDFLARE), ``` {% endcode %} -The API key you use must be enabled to edit workers. In the portal, edit the API key, -under "Permissions" add "Account", "Workers Scripts", "Edit". Without this permission you may see errors that mention "failed fetching worker route list from cloudflare: bad status code from cloudflare: 403 not 200" +The API key you use must be enabled to edit workers. In the portal, edit the API key, under "Permissions" add "Account", "Workers Scripts", "Edit". Without this permission you may see errors that mention "failed fetching worker route list from cloudflare: bad status code from cloudflare: 403 not 200" -Please notice that if _any_ `CF_WORKER_ROUTE` function is used then `dnscontrol` will manage _all_ -Worker Routes for the domain. To be clear: this means it will delete existing routes that -were created outside of DNSControl. +Please notice that if _any_ `CF_WORKER_ROUTE` function is used then `dnscontrol` will manage _all_ Worker Routes for the domain. To be clear: this means it will delete existing routes that were created outside of DNSControl. ## DS records -Cloudflare has restrictions that may result in DNSControl's attempt to insert -DS records to fail. +Cloudflare has restrictions that may result in DNSControl's attempt to insert DS records to fail. ## TXT records @@ -593,10 +563,7 @@ If you are unable to ignore the warning, any of these will remove it: ## Integration testing -The integration tests assume that Cloudflare Workers are enabled and the credentials used -have the required permissions listed above. The flag `-cfworkers=false` will disable tests related to Workers. -This flag is intended for use with legacy domains where the integration test credentials do not -have access to read/edit Workers. This flag will eventually go away. +The integration tests assume that Cloudflare Workers are enabled and the credentials used have the required permissions listed above. The flag `-cfworkers=false` will disable tests related to Workers. This flag is intended for use with legacy domains where the integration test credentials do not have access to read/edit Workers. This flag will eventually go away. ```shell cd integrationTest # NOTE: Not needed if already in that subdirectory @@ -607,8 +574,7 @@ When `-cfworkers=false` is set, tests related to Workers are skipped. The Accou ### CNAME flattening tests -Tests for per-record CNAME flattening (`CF_CNAME_FLATTEN_ON`/`CF_CNAME_FLATTEN_OFF`) are disabled by default -because they require a paid Cloudflare plan. To enable these tests, use the `-cfflatten=true` flag: +Tests for per-record CNAME flattening (`CF_CNAME_FLATTEN_ON`/`CF_CNAME_FLATTEN_OFF`) are disabled by default because they require a paid Cloudflare plan. To enable these tests, use the `-cfflatten=true` flag: ```shell cd integrationTest @@ -619,8 +585,7 @@ If you run with `-cfflatten=true` on a free zone, the tests will fail with an er ### Tag tests -Tests for record comments (`CF_COMMENT`) always run since comments work on all plans. -Tests for record tags (`CF_TAGS`) are disabled by default because they require a paid plan. +Tests for record comments (`CF_COMMENT`) always run since comments work on all plans. Tests for record tags (`CF_TAGS`) are disabled by default because they require a paid plan. ```shell cd integrationTest @@ -636,9 +601,7 @@ go test -v -verbose -profile CLOUDFLAREAPI -cfflatten=true -cftags=true ## Cloudflare special TTLs -Cloudflare plays tricks with TTLs. Cloudflare uses "1" to mean "auto-ttl"; -which as far as we can tell means 300 seconds (5 minutes) with the option that -CloudFlare may dynamically adjust the actual TTL. +Cloudflare plays tricks with TTLs. Cloudflare uses "1" to mean "auto-ttl"; which as far as we can tell means 300 seconds (5 minutes) with the option that CloudFlare may dynamically adjust the actual TTL. If the TTL isn't set to 1, Cloudflare has a minimum of 1 minutes. diff --git a/documentation/provider/cnr.md b/documentation/provider/cnr.md index 047226ba6f..0d65fc8fa8 100644 --- a/documentation/provider/cnr.md +++ b/documentation/provider/cnr.md @@ -6,8 +6,7 @@ This is based on API documents found at [https://kb.centralnicreseller.com/api/a ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `CNR` -along with your CentralNic Reseller login data. +To use this provider, add an entry to `creds.json` with `TYPE` set to `CNR` along with your CentralNic Reseller login data. Example: @@ -49,8 +48,7 @@ Here a working example for our OT&E System: **NOTE**: The above credentials are known to the public. {% endhint %} -With the above CentralNic Reseller entry in `creds.json`, you can run the -integration tests or by specifying the data per environment vars as follows: +With the above CentralNic Reseller entry in `creds.json`, you can run the integration tests or by specifying the data per environment vars as follows: ```shell # Review the output. Pick one domain and set CNR_DOMAIN. @@ -71,9 +69,7 @@ Fetch a list of all DNSZones: dnscontrol get-zones --format=nameonly cnr CNR all ``` -Here's an example DNS Configuration `dnsconfig.js` using our provider module. -Even though it shows how you use us as Domain Registrar AND DNS Provider, we don't force you to do that. -You are free to decide if you want to use both of our provider technology or just one of them. +Here's an example DNS Configuration `dnsconfig.js` using our provider module. Even though it shows how you use us as Domain Registrar AND DNS Provider, we don't force you to do that. You are free to decide if you want to use both of our provider technology or just one of them. {% code title="dnsconfig.js" %} ```javascript @@ -105,15 +101,12 @@ This provider does not recognize any special metadata fields unique to CentralNi ## get-zones -`dnscontrol get-zones` is implemented for this provider. The list -includes both basic and premier zones. +`dnscontrol get-zones` is implemented for this provider. The list includes both basic and premier zones. ## New domains -If a dnszone does not exist in your CNR account, DNSControl will *not* automatically add it with the `dnscontrol push` or `dnscontrol preview` command. You'll need to do that via the control panel manually or using the command `dnscontrol create-domains`. -This is because it could lead to unwanted costs on customer-side that we want to avoid. +If a dnszone does not exist in your CNR account, DNSControl will *not* automatically add it with the `dnscontrol push` or `dnscontrol preview` command. You'll need to do that via the control panel manually or using the command `dnscontrol create-domains`. This is because it could lead to unwanted costs on customer-side that we want to avoid. ## Debug Mode -As shown in the configuration examples above, this can be activated on demand and it can be used to check the API commands send to our system. -In general this is thought for our purpose to have an easy way to dive into issues. But if you're interested what's going on, feel free to activate it. +As shown in the configuration examples above, this can be activated on demand and it can be used to check the API commands send to our system. In general this is thought for our purpose to have an easy way to dive into issues. But if you're interested what's going on, feel free to activate it. diff --git a/documentation/provider/desec.md b/documentation/provider/desec.md index 0a5b3afeb0..01fc67f3f2 100644 --- a/documentation/provider/desec.md +++ b/documentation/provider/desec.md @@ -1,7 +1,6 @@ ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `DESEC` -along with a deSEC account auth token. +To use this provider, add an entry to `creds.json` with `TYPE` set to `DESEC` along with a deSEC account auth token. Example: @@ -34,8 +33,7 @@ D("example.com", REG_NONE, DnsProvider(DSP_DESEC), {% endcode %} ## Activation -DNSControl depends on a deSEC account auth token. -This token can be obtained by [logging in via the deSEC API](https://desec.readthedocs.io/en/latest/auth/account.html#log-in). +DNSControl depends on a deSEC account auth token. This token can be obtained by [logging in via the deSEC API](https://desec.readthedocs.io/en/latest/auth/account.html#log-in). {% hint style="warning" %} deSEC enforces a daily limit of 300 RRset creation/deletion/modification per @@ -44,9 +42,4 @@ integration test suite can not be run in a single session. See [https://desec.readthedocs.io/en/latest/rate-limits.html#api-request-throttling](https://desec.readthedocs.io/en/latest/rate-limits.html#api-request-throttling) {% endhint %} -Upon domain creation, the DNSKEY and DS records needed for DNSSEC setup are -printed in the command output. If you need these values later, get them from -the deSEC web interface or query deSEC nameservers for the CDS records. For -example: `dig +short @ns1.desec.io example.com CDS` will return the published -CDS records which can be used to insert the required DS records into the parent -zone. \ No newline at end of file +Upon domain creation, the DNSKEY and DS records needed for DNSSEC setup are printed in the command output. If you need these values later, get them from the deSEC web interface or query deSEC nameservers for the CDS records. For example: `dig +short @ns1.desec.io example.com CDS` will return the published CDS records which can be used to insert the required DS records into the parent zone. \ No newline at end of file diff --git a/documentation/provider/gandiv5.md b/documentation/provider/gandiv5.md index 0ab618fadb..80c120c512 100644 --- a/documentation/provider/gandiv5.md +++ b/documentation/provider/gandiv5.md @@ -1,6 +1,4 @@ -`GANDI_V5` uses the v5 API and can act as a registrar provider -or a DNS provider. It is only able to work with domains -migrated to the new LiveDNS API, which should be all domains. +`GANDI_V5` uses the v5 API and can act as a registrar provider or a DNS provider. It is only able to work with domains migrated to the new LiveDNS API, which should be all domains. * API Documentation: https://api.gandi.net/docs * API Endpoint: https://api.gandi.net/ @@ -9,30 +7,19 @@ migrated to the new LiveDNS API, which should be all domains. ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `GANDI_V5` -along with other settings: +To use this provider, add an entry to `creds.json` with `TYPE` set to `GANDI_V5` along with other settings: * (mandatory, string) your Gandi.net access credentials (see below) - one of: * `token`: Personal Access Token (PAT) * `apikey` API Key (deprecated) -* `apiurl`: (optional, string) the endpoint of the API. When empty or absent the production -endpoint is used (default) ; you can use it to select the Sandbox API Endpoint instead. -* `sharing_id`: (optional, string) let you scope to a specific organization. When empty or absent -calls are not scoped to a specific organization. +* `apiurl`: (optional, string) the endpoint of the API. When empty or absent the production endpoint is used (default) ; you can use it to select the Sandbox API Endpoint instead. +* `sharing_id`: (optional, string) let you scope to a specific organization. When empty or absent calls are not scoped to a specific organization. -When both `token` and `apikey` are defined, the priority is given to `token` which will -be used for API communication (as if `apikey` was not set). -See [the Authentication section](#authentication) for details on obtaining these credentials. +When both `token` and `apikey` are defined, the priority is given to `token` which will be used for API communication (as if `apikey` was not set). See [the Authentication section](#authentication) for details on obtaining these credentials. +The [sharing_id](https://api.gandi.net/docs/reference/#Sharing-ID) selects between different organizations which your account is a member of; to manage domains in multiple organizations, you can use multiple `creds.json` entries. -The [sharing_id](https://api.gandi.net/docs/reference/#Sharing-ID) selects between different organizations which your account is -a member of; to manage domains in multiple organizations, you can use multiple -`creds.json` entries. - -How to find the `sharing_id`: The sharing ID is the second hex string found in -the URL on the portal. Log into the Gandi website, click on "organizations" in -the leftnav, and click on the organization name. The URL will be something -like: +How to find the `sharing_id`: The sharing ID is the second hex string found in the URL on the portal. Log into the Gandi website, click on "organizations" in the leftnav, and click on the organization name. The URL will be something like: ```text https://admin.gandi.net/organizations/[not this hex string]/PLTS/[sharing id]/profile @@ -54,32 +41,17 @@ Example: ## Authentication -(Cf [official documentation of the API](https://api.gandi.net/docs/authentication/) -The **Personal Access Token** (PAT) is configured in the [Account Settings of the -Gandi Admin application](https://admin.gandi.net/organizations/account/pat), then -click on "Create a token" button. -Choose an organisation (if your account happens to have multiple ones). -Then, choose a name (limited to 42 chars), an expiration date. -You can choose to limit the scope to a select number of products (domain names). -Finally, choose the permissions : the needed one is "Manage domain name technical configurations" -(in French: "Gérer la configuration technique des domaines"), which automatically -implies "See and renew domain names" (in French: "Voir et renouveler les domaines"). -You then have only one (1) chance to copy and save the token somewhere. - -The **API Key** is the previous (deprecated) mechanism used to do api calls. -To generate or delete your API key, go to User Settings, -"Manage the user account and security settings", the "Authentication options" -tab, then regenerate the "Production API key" under "Developer access" +(Cf [official documentation of the API](https://api.gandi.net/docs/authentication/) The **Personal Access Token** (PAT) is configured in the [Account Settings of the Gandi Admin application](https://admin.gandi.net/organizations/account/pat), then click on "Create a token" button. Choose an organisation (if your account happens to have multiple ones). Then, choose a name (limited to 42 chars), an expiration date. You can choose to limit the scope to a select number of products (domain names). Finally, choose the permissions : the needed one is "Manage domain name technical configurations" (in French: "Gérer la configuration technique des domaines"), which automatically implies "See and renew domain names" (in French: "Voir et renouveler les domaines"). You then have only one (1) chance to copy and save the token somewhere. + +The **API Key** is the previous (deprecated) mechanism used to do api calls. To generate or delete your API key, go to User Settings, "Manage the user account and security settings", the "Authentication options" tab, then regenerate the "Production API key" under "Developer access" ## Metadata This provider does not recognize any special metadata fields unique to Gandi. ## Limitations -This provider does not support using `ALIAS` in combination with DNSSEC, -whether `AUTODNSSEC` or otherwise. +This provider does not support using `ALIAS` in combination with DNSSEC, whether `AUTODNSSEC` or otherwise. -This provider only supports `ALIAS` on the `"@"` zone apex, not on any other -names. +This provider only supports `ALIAS` on the `"@"` zone apex, not on any other names. ## Usage An example configuration: @@ -95,14 +67,11 @@ D("example.com", REG_GANDI, DnsProvider(DSP_GANDI), ``` {% endcode %} -If you are converting from the old "GANDI" provider, -simply change "GANDI" to "GANDI_V5" in `dnsconfig.js`. -Be sure to test with `dnscontrol preview` before running `dnscontrol push`. +If you are converting from the old "GANDI" provider, simply change "GANDI" to "GANDI_V5" in `dnsconfig.js`. Be sure to test with `dnscontrol preview` before running `dnscontrol push`. ## New domains If a domain does not exist in your Gandi account, DNSControl will *not* automatically add it with the `create-domains` command. You'll need to do that via the web UI manually. - ## Common errors ### Error getting corrections @@ -119,16 +88,11 @@ This is the error you'll see if your `token` (or (deprecated) `apikey`) in `cred WARNING: Domain 'example.com' does not exist in the 'secname' profile and will be added automatically. ``` -This error is caused by the internal `ListZones()` functions returning no domain names. This is usually because your `creds.json` information is pointing at an empty organization or no organization. The solution is to set -`sharing_id` in `creds.json`. +This error is caused by the internal `ListZones()` functions returning no domain names. This is usually because your `creds.json` information is pointing at an empty organization or no organization. The solution is to set `sharing_id` in `creds.json`. ### get-zones "nameonly" returns nothing -If a `dnscontrol get-zones --format=nameonly CredId - all` returns nothing, -this is usually because your `creds.json` information is pointing at an empty -organization or no organization. The solution is to set `sharing_id` in -`creds.json`. - +If a `dnscontrol get-zones --format=nameonly CredId - all` returns nothing, this is usually because your `creds.json` information is pointing at an empty organization or no organization. The solution is to set `sharing_id` in `creds.json`. ## Development diff --git a/documentation/provider/hetzner.md b/documentation/provider/hetzner.md index 0616f878fe..2103c92667 100644 --- a/documentation/provider/hetzner.md +++ b/documentation/provider/hetzner.md @@ -1,7 +1,6 @@ ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `HETZNER` -along with a [Hetzner API Key](https://dns.hetzner.com/settings/api-token). +To use this provider, add an entry to `creds.json` with `TYPE` set to `HETZNER` along with a [Hetzner API Key](https://dns.hetzner.com/settings/api-token). Example: @@ -18,8 +17,7 @@ Example: ## Metadata -This provider does not recognize any special metadata fields unique to Hetzner - DNS Console. +This provider does not recognize any special metadata fields unique to Hetzner DNS Console. ## Usage @@ -38,15 +36,13 @@ D("example.com", REG_NONE, DnsProvider(DSP_HETZNER), ## Activation -Create a new API Key in the -[Hetzner DNS Console](https://dns.hetzner.com/settings/api-token). +Create a new API Key in the [Hetzner DNS Console](https://dns.hetzner.com/settings/api-token). ## Caveats ### CAA -As of June 2022, the Hetzner DNS Console API does not accept spaces in CAA - records. +As of June 2022, the Hetzner DNS Console API does not accept spaces in CAA records. ```text 0 issue "letsencrypt.org; validationmethods=dns-01; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234" ``` @@ -58,10 +54,7 @@ Removing the spaces might still work for any consumer of the record. ### SOA -Hetzner DNS Console does not allow changing the SOA record via their API. -There is an alternative method using an import of a full BIND file, but this - approach does not play nice with incremental changes or ignored records. -At this time you cannot update SOA records via DNSControl. +Hetzner DNS Console does not allow changing the SOA record via their API. There is an alternative method using an import of a full BIND file, but this approach does not play nice with incremental changes or ignored records. At this time you cannot update SOA records via DNSControl. ### Rate Limiting @@ -69,9 +62,7 @@ Hetzner is rate limiting requests quite heavily. The rate limit and remaining quota is advertised in the API response headers. -DNSControl will burst through half of the quota, and then it spreads the - requests evenly throughout the remaining window. This allows you to move fast - and be able to revert accidental changes to the DNS config in a timely manner. +DNSControl will burst through half of the quota, and then it spreads the requests evenly throughout the remaining window. This allows you to move fast and be able to revert accidental changes to the DNS config in a timely manner. Every response from the Hetzner DNS Console API includes your limits: @@ -90,11 +81,6 @@ Vary Origin X-Ratelimit-Limit-Minute 42 X-Ratelimit-Remaining-Minute 33 ``` -With the above values, DNSControl will not delay the next 12 requests (until it - hits `Ratelimit-Remaining: 21 # 42/2`) and then slow down requests with a - delay of `7s/22 ≈ 300ms` between requests (about 3 requests per second). -Performing these 12 requests might take longer than 7s, at which point the - quota resets and DNSControl will burst through the quota again. - -DNSControl will retry rate-limited requests (status 429) and respect the - advertised `Retry-After` delay. +With the above values, DNSControl will not delay the next 12 requests (until it hits `Ratelimit-Remaining: 21 # 42/2`) and then slow down requests with a delay of `7s/22 ≈ 300ms` between requests (about 3 requests per second). Performing these 12 requests might take longer than 7s, at which point the quota resets and DNSControl will burst through the quota again. + +DNSControl will retry rate-limited requests (status 429) and respect the advertised `Retry-After` delay. diff --git a/documentation/provider/hetznerv2.md b/documentation/provider/hetznerv2.md index d8788d8862..79600685b9 100644 --- a/documentation/provider/hetznerv2.md +++ b/documentation/provider/hetznerv2.md @@ -1,7 +1,6 @@ ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `HETZNER_V2` -along with a [Hetzner API Token](https://docs.hetzner.cloud/reference/cloud#getting-started). +To use this provider, add an entry to `creds.json` with `TYPE` set to `HETZNER_V2` along with a [Hetzner API Token](https://docs.hetzner.cloud/reference/cloud#getting-started). Example: @@ -37,8 +36,7 @@ D("example.com", REG_NONE, DnsProvider(DSP_HETZNER), ## Activation -Create a new API Key in the -[Hetzner Console](https://docs.hetzner.cloud/reference/cloud#getting-started). +Create a new API Key in the [Hetzner Console](https://docs.hetzner.cloud/reference/cloud#getting-started). ## Caveats @@ -48,7 +46,4 @@ Removing the Hetzner provided NS records at the root is not possible. ### SOA -Hetzner DNS API does not allow changing the SOA record via their API. -There is an alternative method using an import of a full BIND file, but this - approach does not play nice with incremental changes or ignored records. -At this time you cannot update SOA records via DNSControl. +Hetzner DNS API does not allow changing the SOA record via their API. There is an alternative method using an import of a full BIND file, but this approach does not play nice with incremental changes or ignored records. At this time you cannot update SOA records via DNSControl. diff --git a/documentation/provider/index.md b/documentation/provider/index.md index 2002b3c44c..b56d2c39cd 100644 --- a/documentation/provider/index.md +++ b/documentation/provider/index.md @@ -2,12 +2,9 @@ ## Provider Features -The table below shows various features supported, or not supported by DNSControl providers. -This table is automatically generated from metadata supplied by the provider when they register themselves inside dnscontrol. +The table below shows various features supported, or not supported by DNSControl providers. This table is automatically generated from metadata supplied by the provider when they register themselves inside dnscontrol. -An empty space may indicate the feature is not supported by a provider, or it may simply mean -the feature has not been investigated and implemented yet. If a feature you need is missing from -a provider that supports it, we'd love your contribution to ensure it works correctly and add it to this matrix. +An empty space may indicate the feature is not supported by a provider, or it may simply mean the feature has not been investigated and implemented yet. If a feature you need is missing from a provider that supports it, we'd love your contribution to ensure it works correctly and add it to this matrix. If a feature is definitively not supported for whatever reason, we would also like a PR to clarify why it is not supported, and fill in this entire matrix. @@ -402,12 +399,9 @@ Providers in this category and their maintainers are: ### Providers with "contributor support" -The other providers are supported by community members, usually the -original contributor. +The other providers are supported by community members, usually the original contributor. -Due to the large number of DNS providers in the world, the DNSControl -team can not support and test all providers. Test frameworks are -provided to help community members support their code independently. +Due to the large number of DNS providers in the world, the DNSControl team can not support and test all providers. Test frameworks are provided to help community members support their code independently. Expectations of maintainers: @@ -475,8 +469,7 @@ Providers in this category and their maintainers are: ### Requested providers -We have received requests for the following providers. If you would like to contribute -code to support this provider, we'd be glad to help in any way. +We have received requests for the following providers. If you would like to contribute code to support this provider, we'd be glad to help in any way. *(The list below is sorted alphabetically.)* @@ -504,18 +497,10 @@ code to support this provider, we'd be glad to help in any way. #### Q: Why are the above GitHub issues marked "closed"? -A: Following [provider requests](../developer-info/provider-request.md), the request -is closed once it is added to this list. If someone chooses to implement the -provider, they re-open the issue. +A: Following [provider requests](../developer-info/provider-request.md), the request is closed once it is added to this list. If someone chooses to implement the provider, they re-open the issue. #### Q: Would someone write a provider for me? -A: The maintainer of DNSControl does not write new providers. New providers -are contributed by the community. +A: The maintainer of DNSControl does not write new providers. New providers are contributed by the community. -DNSControl tries to make writing a provider as easy as possible. DNSControl -does most of the work for you, you only have to write code to authenticate, -download DNS records, and perform create/modify/delete operations on those -records. Please read the directions for [Writing new DNS -providers](../advanced-features/writing-providers.md). The DNS maintainers will gladly -coach you through the process. +DNSControl tries to make writing a provider as easy as possible. DNSControl does most of the work for you, you only have to write code to authenticate, download DNS records, and perform create/modify/delete operations on those records. Please read the directions for [Writing new DNS providers](../advanced-features/writing-providers.md). The DNS maintainers will gladly coach you through the process. diff --git a/documentation/provider/loopia.md b/documentation/provider/loopia.md index b1616ccea0..ee5c1f2241 100644 --- a/documentation/provider/loopia.md +++ b/documentation/provider/loopia.md @@ -1,26 +1,17 @@ -Loopia is a 💩 provider of DNS. Using DNSControl hides some of the 💩. -If you are stuck with Loopia, hopefully this will reduce the pain. +Loopia is a 💩 provider of DNS. Using DNSControl hides some of the 💩. If you are stuck with Loopia, hopefully this will reduce the pain. -They provide DNS services, both as a registrar, and a provider. -They provide support in English and other regional variants (Norwegian, Serbian, Swedish). +They provide DNS services, both as a registrar, and a provider. They provide support in English and other regional variants (Norwegian, Serbian, Swedish). -This plugin is based on API documents found at -[https://www.loopia.com/api/](https://www.loopia.com/api/) -and by observing API responses. Hat tip to GitHub @hazzeh whose code for the -LEGO Loopia implementation was helpful. +This plugin is based on API documents found at [https://www.loopia.com/api/](https://www.loopia.com/api/) and by observing API responses. Hat tip to GitHub @hazzeh whose code for the LEGO Loopia implementation was helpful. Sadly the Loopia API has some problems: -* API calls are limited to 60 calls per minute. If you go above this, - you will have to wait before you can make changes. -* When rate-limited, you will not receive a single HTTP - error: The errors propagate from the back-end, with no headers, or - Retry-After or anything useful. +* API calls are limited to 60 calls per minute. If you go above this, you will have to wait before you can make changes. +* When rate-limited, you will not receive a single HTTP error: The errors propagate from the back-end, with no headers, or Retry-After or anything useful. * There are no guarantees of idempotency from their API. ## Unimplemented API methods - * `removeDomain` is not implemented for safety reasons. Should you wish to remove -a domain, do so from the Loopia control panel. + * `removeDomain` is not implemented for safety reasons. Should you wish to remove a domain, do so from the Loopia control panel. * `addDomain` * `transferDomain` (to Loopia) @@ -35,11 +26,9 @@ HTTP Post Error: Post "https://api.loopia.se/RPCSERV": context deadline exceeded The API endpoint didn't answer. Try again. 🤷 - ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `LOOPIA` -along with your Loopia API login credentials. +To use this provider, add an entry to `creds.json` with `TYPE` set to `LOOPIA` along with your Loopia API login credentials. Example: @@ -68,9 +57,7 @@ Example: There is no test endpoint. Fly free, grasshopper. -Turning on debug will show the XML requests and responses, and include the -username and password from your `creds.json` file. If you want to share these, -like for a GitHub issue, be sure to redact those from the XML. +Turning on debug will show the XML requests and responses, and include the username and password from your `creds.json` file. If you want to share these, like for a GitHub issue, be sure to redact those from the XML. ### Fetch Apex NS Entries @@ -83,9 +70,7 @@ like for a GitHub issue, be sure to redact those from the XML. defaultNS2 = "ns2.loopia.se." ``` -API calls to loopia can be expensive time-wise. Set this to "false" (off) to -skip the API call to fetch the apex (`@`) entries, and use Loopia's default NS -servers. +API calls to loopia can be expensive time-wise. Set this to "false" (off) to skip the API call to fetch the apex (`@`) entries, and use Loopia's default NS servers. This setting defaults to "true" (on). @@ -95,25 +80,16 @@ This setting defaults to "true" (on). Setting this to "true" (on) allows you to modify NS entries. -Loopia is weird. NS entries are inaccessible in the control panel. But you can see them. -Perhaps dnscontrol added an NS that you cannot delete now? Toggle this setting to -"true" in order to treat all NS entries as any other - making them accessible -to modification. Beware the consequences of changing from default NS entries. Likely -nothing will happen since the glue records provided won't match those in the domain, -and you will need to manually inform Loopia of this so they can update the glue records. +Loopia is weird. NS entries are inaccessible in the control panel. But you can see them. Perhaps dnscontrol added an NS that you cannot delete now? Toggle this setting to "true" in order to treat all NS entries as any other - making them accessible to modification. Beware the consequences of changing from default NS entries. Likely nothing will happen since the glue records provided won't match those in the domain, and you will need to manually inform Loopia of this so they can update the glue records. -In short: enable this setting to be able to delete NS entries. No `NS()` in your -`dnsconfig.js`? Existing ones will be deleted. Have some `NS()` or `NAMESERVER()` -entries? They'll be added. +In short: enable this setting to be able to delete NS entries. No `NS()` in your `dnsconfig.js`? Existing ones will be deleted. Have some `NS()` or `NAMESERVER()` entries? They'll be added. This setting defaults to "false" (off). - ### Regions `creds.json` setting: `region` - Loopia operate in a few regions. Norway (`no`), Serbia (`rs`), Sweden (`se`). For the parameter `region`, specify one of `no`, `rs`, `se`, or omit, or leave empty for the default `se` Sweden. @@ -128,7 +104,6 @@ HTTP Post Error: Post "https://api.loopia.no/RPCSERV": x509: “*.loopia.rs” c `creds.json` setting: `rate_limit_per` - Loopia rate limits requests to 60 per minute. From their [web-site](https://www.loopia.com/api/rate_limiting/): @@ -136,22 +111,13 @@ From their [web-site](https://www.loopia.com/api/rate_limiting/): You can make up to 60 calls per minute to LoopiaAPI. Of those, a maximum of 15 can be domain searches. ``` -Depending on how many requests you make, you may encounter a limit. Modification -of each DNS record requires at least one API call. 🤦 +Depending on how many requests you make, you may encounter a limit. Modification of each DNS record requires at least one API call. 🤦 -Example: If the rate is 60/min and you make two requests every second, the 31st -request will be rejected. You will then have to wait for 29 seconds, until the -first request’s age reaches one minute. At that time, it will be dropped from -the calculation, and you can make another request. One second later, and -generally every time an old request’s age falls out of the sliding window -counting interval, you can make another request. +Example: If the rate is 60/min and you make two requests every second, the 31st request will be rejected. You will then have to wait for 29 seconds, until the first request’s age reaches one minute. At that time, it will be dropped from the calculation, and you can make another request. One second later, and generally every time an old request’s age falls out of the sliding window counting interval, you can make another request. -Your per minute quota is 60 requests and in your settings you - specified `Minute`. DNSControl will perform at most one request per second. - DNSControl will emit a warning in case it breaches the quota. +Your per minute quota is 60 requests and in your settings you specified `Minute`. DNSControl will perform at most one request per second. DNSControl will emit a warning in case it breaches the quota. -The setting `rate_limit_per` controls this behavior and accepts - a case-insensitive value of +The setting `rate_limit_per` controls this behavior and accepts a case-insensitive value of - `Hour` - `Minute` - `Second` @@ -176,10 +142,7 @@ In your `creds.json` for all `LOOPIA` provider entries: ## Usage -Here's an example DNS Configuration `dnsconfig.js` using the provider module. -Even though it shows how you use Loopia as Domain Registrar AND DNS Provider, -you're not forced to do that (thank god). - +Here's an example DNS Configuration `dnsconfig.js` using the provider module. Even though it shows how you use Loopia as Domain Registrar AND DNS Provider, you're not forced to do that (thank god). {% code title="dnsconfig.js" %} ```javascript @@ -205,11 +168,9 @@ D("example.com", REG_LOOPIA, DnsProvider(DSP_LOOPIA), ## Special notes about newer standards -Loopia does not yet support [RFC7505](https://www.rfc-editor.org/rfc/rfc7505), so null `MX` records are -currently prohibited. +Loopia does not yet support [RFC7505](https://www.rfc-editor.org/rfc/rfc7505), so null `MX` records are currently prohibited. -Until such a time when they do begin to support this, Loopias -`auditrecords.go` code prohibits this. +Until such a time when they do begin to support this, Loopias `auditrecords.go` code prohibits this. ## Metadata @@ -219,11 +180,9 @@ This provider does not recognize any special metadata fields unique to LOOPIA. `dnscontrol get-zones` is implemented for this provider. - ## New domains -If a dnszone does not exist in your LOOPIA account, DNSControl will *not* automatically add it with the `dnscontrol push` or `dnscontrol preview` command. You'll need to do that via the control panel manually or using the command `dnscontrol create-domains`. -This is because it could lead to unwanted costs on customer-side that you may want to avoid. +If a dnszone does not exist in your LOOPIA account, DNSControl will *not* automatically add it with the `dnscontrol push` or `dnscontrol preview` command. You'll need to do that via the control panel manually or using the command `dnscontrol create-domains`. This is because it could lead to unwanted costs on customer-side that you may want to avoid. ## Debug Mode diff --git a/documentation/provider/namecheap.md b/documentation/provider/namecheap.md index b3c2e1f427..fe8e2ca29e 100644 --- a/documentation/provider/namecheap.md +++ b/documentation/provider/namecheap.md @@ -2,8 +2,7 @@ This is the provider for [Namecheap](https://www.namecheap.com/). ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `NAMECHEAP` -along with your Namecheap API username and key: +To use this provider, add an entry to `creds.json` with `TYPE` set to `NAMECHEAP` along with your Namecheap API username and key: Example: @@ -19,8 +18,7 @@ Example: ``` {% endcode %} -You can optionally specify BaseURL to use a different endpoint - typically the -sandbox: +You can optionally specify BaseURL to use a different endpoint - typically the sandbox: {% code title="creds.json" %} ```json @@ -37,10 +35,8 @@ sandbox: if BaseURL is omitted, the production namecheap URL is assumed. - ## Metadata -This provider does not recognize any special metadata fields unique to -Namecheap. +This provider does not recognize any special metadata fields unique to Namecheap. ## Usage An example configuration: @@ -56,8 +52,7 @@ D("example.com", REG_NAMECHEAP, DnsProvider(DSP_BIND), ``` {% endcode %} -Namecheap provides custom redirect records URL, URL301, and FRAME. These -records can be used like any other record: +Namecheap provides custom redirect records URL, URL301, and FRAME. These records can be used like any other record: {% code title="dnsconfig.js" %} ```javascript @@ -73,7 +68,4 @@ D("example.com", REG_NAMECHEAP, DnsProvider(DSP_NAMECHEAP), {% endcode %} ## Activation -In order to activate API functionality on your Namecheap account, you must -enable it for your account and wait for their review process. More information -on enabling API access is [located -here](https://www.namecheap.com/support/api/intro.aspx). +In order to activate API functionality on your Namecheap account, you must enable it for your account and wait for their review process. More information on enabling API access is [located here](https://www.namecheap.com/support/api/intro.aspx). diff --git a/documentation/provider/namedotcom.md b/documentation/provider/namedotcom.md index 8f23c19a18..519ed58f70 100644 --- a/documentation/provider/namedotcom.md +++ b/documentation/provider/namedotcom.md @@ -6,8 +6,7 @@ it can not be easily fixed. ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `NAMEDOTCOM` -along with your name.com API username and access token: +To use this provider, add an entry to `creds.json` with `TYPE` set to `NAMEDOTCOM` along with your name.com API username and access token: Example: @@ -29,14 +28,12 @@ There is another key name `apiurl` but it is optional and defaults to the correc export NAMEDOTCOM_URL='api.name.com' - ## Metadata This provider does not recognize any special metadata fields unique to name.com. ## Usage -An example `dnsconfig.js` configuration with NAMEDOTCOM -as the registrar and DNS service provider: +An example `dnsconfig.js` configuration with NAMEDOTCOM as the registrar and DNS service provider: {% code title="dnsconfig.js" %} ```javascript @@ -49,8 +46,7 @@ D("example.com", REG_NAMECOM, DnsProvider(DSP_NAMECOM), ``` {% endcode %} -An example `dnsconfig.js` configuration with NAMEDOTCOM -as the registrar and DNS only, DNS hosted elsewhere: +An example `dnsconfig.js` configuration with NAMEDOTCOM as the registrar and DNS only, DNS hosted elsewhere: {% code title="dnsconfig.js" %} ```javascript @@ -78,32 +74,23 @@ In order to activate API functionality on your Name.com account, you must apply integration_test.go:140: api returned unexpected response: invalid character '<' looking for beginning of value ``` -This error means an invalid URL is being used to reach the API -endpoint. It usually means a setting is `api.name.com/api` when -`api.name.com` is correct (i.e. remove the `/api`). +This error means an invalid URL is being used to reach the API endpoint. It usually means a setting is `api.name.com/api` when `api.name.com` is correct (i.e. remove the `/api`). In integration tests: * Wrong: `export NAMEDOTCOM_URL='api.name.com/api'` * Right: `export NAMEDOTCOM_URL='api.name.com'` -In production, the `apiurl` setting in `creds.json` is wrong. You can -simply leave this option out and use the default, which is correct. +In production, the `apiurl` setting in `creds.json` is wrong. You can simply leave this option out and use the default, which is correct. TODO(tlim): Improve the error message. (Volunteer needed!) - ### dial tcp: lookup https: no such host ```text integration_test.go:81: Failed getting nameservers Get https://https//api.name.com/api/v4/domains/stackosphere.com?: dial tcp: lookup https: no such host ``` -When running integration tests, this error -means you included the `https://` in the `NAMEDOTCOM_URL` variable. -You meant to do something like `export NAMEDOTCOM_URL='api.name.com' instead. +When running integration tests, this error means you included the `https://` in the `NAMEDOTCOM_URL` variable. You meant to do something like `export NAMEDOTCOM_URL='api.name.com' instead. -In production, the `apiurl` setting in `creds.json` needs to be -adjusted. You can simply leave this option out and use the default, -which is correct. If you are using the EO&T system, leave the -protocol (`http://`) off the URL. +In production, the `apiurl` setting in `creds.json` needs to be adjusted. You can simply leave this option out and use the default, which is correct. If you are using the EO&T system, leave the protocol (`http://`) off the URL. diff --git a/documentation/provider/ovh.md b/documentation/provider/ovh.md index 33d9b7a47c..1ee9bb204a 100644 --- a/documentation/provider/ovh.md +++ b/documentation/provider/ovh.md @@ -1,7 +1,6 @@ ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `OVH` -along with a OVH app-key, app-secret-key, consumer-key and optionally endpoint. +To use this provider, add an entry to `creds.json` with `TYPE` set to `OVH` along with a OVH app-key, app-secret-key, consumer-key and optionally endpoint. Example: @@ -62,14 +61,11 @@ D("example.com", REG_OVH, DnsProvider(DSP_R53), ## Activation -To obtain the OVH keys, one need to register an app at OVH by following the -[OVH API Getting Started](https://help.ovhcloud.com/csm/en-gb-api-getting-started-ovhcloud-api?id=kb_article_view&sysparm_article=KB0042784) +To obtain the OVH keys, one need to register an app at OVH by following the [OVH API Getting Started](https://help.ovhcloud.com/csm/en-gb-api-getting-started-ovhcloud-api?id=kb_article_view&sysparm_article=KB0042784) -It consist in declaring the app at -which gives the `app-key` and `app-secret-key`. If your domains and zones are located in another region, see below for the correct url to use. +It consist in declaring the app at which gives the `app-key` and `app-secret-key`. If your domains and zones are located in another region, see below for the correct url to use. -Once done, to obtain the `consumer-key` it is necessary to authorize the just created app -to access the data in a specific account: +Once done, to obtain the `consumer-key` it is necessary to authorize the just created app to access the data in a specific account: ```shell curl -XPOST -H"X-Ovh-Application: " -H "Content-type: application/json" https://eu.api.ovh.com/1.0/auth/credential -d'{ @@ -116,8 +112,7 @@ It should return something akin to: } ``` -Open the "validationUrl" in a browser and log in with your OVH account. This will link the app with your account, -authorizing it to access your zones and domains. +Open the "validationUrl" in a browser and log in with your OVH account. This will link the app with your account, authorizing it to access your zones and domains. Do not forget to fill the `consumer-key` of your `creds.json`. @@ -130,9 +125,7 @@ Do not forget to fill the `endpoint` of your `creds.json` if you use an endpoint ## New domains -If a domain does not exist in your OVH account, DNSControl -will *not* automatically add it. You'll need to do that via the -control panel manually. +If a domain does not exist in your OVH account, DNSControl will *not* automatically add it. You'll need to do that via the control panel manually. ## Dual providers scenario @@ -146,8 +139,6 @@ OVH now allows to host DNS zone for a domain that is not registered in their reg ## Caveats -* OVH doesn't allow resetting the zone to the OVH DNS through the API. If for any reasons OVH NS entries were -removed the only way to add them back is by using the OVH Control Panel (in the DNS Servers tab, click on the "Reset the -DNS servers" button. +* OVH doesn't allow resetting the zone to the OVH DNS through the API. If for any reasons OVH NS entries were removed the only way to add them back is by using the OVH Control Panel (in the DNS Servers tab, click on the "Reset the DNS servers" button. * There may be a slight delay (1-10 minutes) before your modifications appear in the OVH Control Panel. However it seems that it's only cosmetic - the changes are indeed available at the DNS servers. You can confirm that the changes are taken into account by OVH by choosing "Change in text format", and see in the BIND compatible format that your changes are indeed there. And you can confirm by directly asking the DNS servers (e.g. with `dig`). * OVH enforces the [Restrictions on valid hostnames](https://en.wikipedia.org/wiki/Hostname#Syntax). A hostname with an underscore ("_") will cause the following error `FAILURE! OVHcloud API error (status code 400): Client::BadRequest: "Invalid domain name, underscore not allowed"` diff --git a/documentation/provider/route53.md b/documentation/provider/route53.md index 9445fce566..45c493aa9d 100644 --- a/documentation/provider/route53.md +++ b/documentation/provider/route53.md @@ -1,7 +1,6 @@ ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `ROUTE53` -along with API credentials. +To use this provider, add an entry to `creds.json` with `TYPE` set to `ROUTE53` along with API credentials. Example: @@ -98,8 +97,7 @@ D("example.com", REG_NONE, DnsProvider(DSP_R53), This provider supports split horizons using the [`R53_ZONE()`](../language-reference/record-modifiers/R53_ZONE.md) domain function. -In this example the domain `testzone.net` appears in the same account twice, -each with different zone IDs specified using [`R53_ZONE()`](../language-reference/record-modifiers/R53_ZONE.md). +In this example the domain `testzone.net` appears in the same account twice, each with different zone IDs specified using [`R53_ZONE()`](../language-reference/record-modifiers/R53_ZONE.md). {% code title="dnsconfig.js" %} ```javascript @@ -170,8 +168,7 @@ aws route53 create-reusable-delegation-set --caller-reference "foo" } ``` -You can then reference the DelegationSet.Id in your `r53_main` block (with your other credentials) to have all created domains placed in that -delegation set. Note that you you only want the portion of the `Id` after the `/delegationset/` (the `12312312123` in the example above). +You can then reference the DelegationSet.Id in your `r53_main` block (with your other credentials) to have all created domains placed in that delegation set. Note that you you only want the portion of the `Id` after the `/delegationset/` (the `12312312123` in the example above). > Delegation sets only apply during `create-domains` at the moment. Further work needs to be done to have them apply during `push`. @@ -179,13 +176,10 @@ delegation set. Note that you you only want the portion of the `Id` after the ` ### Route53 errors if it is not the DnsProvider -This code may not function properly if a domain has R53 as a Registrar -but not as a DnsProvider. The situation is described in -[PR#155](https://github.com/DNSControl/dnscontrol/pull/155). +This code may not function properly if a domain has R53 as a Registrar but not as a DnsProvider. The situation is described in [PR#155](https://github.com/DNSControl/dnscontrol/pull/155). In this situation you will see a message like: (This output assumes the `--full` flag) - ```text ----- Registrar: r53_main Error getting corrections: AccessDeniedException: User: arn:aws:iam::868399730840:user/dnscontrol is not authorized to perform: route53domains:GetDomainDetail @@ -202,12 +196,7 @@ You will see some weirdness if: 1. A CNAME was created using the web UI 2. The CNAME's target does NOT end with a dot. -What you will see: When DNSControl tries to update such records, R53 -only updates the first one. For example if DNSControl is updating 3 -such records, you will need to run `dnscontrol push` three times for -all three records to update. Each time DNSControl is sending three -modify requests but only the first is executed. After all such -records are modified by DNSControl, everything works as expected. +What you will see: When DNSControl tries to update such records, R53 only updates the first one. For example if DNSControl is updating 3 such records, you will need to run `dnscontrol push` three times for all three records to update. Each time DNSControl is sending three modify requests but only the first is executed. After all such records are modified by DNSControl, everything works as expected. We believe this is a bug with R53. @@ -225,7 +214,6 @@ this problem disappears. More info is available in [#891](https://github.com/DNSControl/dnscontrol/issues/891). - ## Error messages ### Creds key mismatch @@ -236,8 +224,7 @@ Creating r53 dns provider: NoCredentialProviders: no valid providers in chain. D For verbose messaging see aws.Config.CredentialsChainVerboseErrors ``` -This means that the `creds.json` entry isn't found. Either there is no entry, or the entry name doesn't match the first parameter in the `NewDnsProvider()` call. In the above example, note -that the string `r53_main` is specified in `NewDnsProvider("r53_main")` and that is the exact key used in the creds file above. +This means that the `creds.json` entry isn't found. Either there is no entry, or the entry name doesn't match the first parameter in the `NewDnsProvider()` call. In the above example, note that the string `r53_main` is specified in `NewDnsProvider("r53_main")` and that is the exact key used in the creds file above. ### Invalid KeyId diff --git a/documentation/provider/sakuracloud.md b/documentation/provider/sakuracloud.md index f7fb2bf1d6..61204af8e4 100644 --- a/documentation/provider/sakuracloud.md +++ b/documentation/provider/sakuracloud.md @@ -1,8 +1,7 @@ This is the provider for [Sakura Cloud](https://cloud.sakura.ad.jp/). ## Configuration -To use this provider, add an entry to `creds.json` with `TYPE` set to `SAKURACLOUD` -along with API credentials. +To use this provider, add an entry to `creds.json` with `TYPE` set to `SAKURACLOUD` along with API credentials. Example: @@ -27,8 +26,7 @@ Endpoints are as follows: * `https://secure.sakura.ad.jp/cloud/zone/tk1a/api/cloud/1.1` (Tokyo first Zone) * `https://secure.sakura.ad.jp/cloud/zone/tk1b/api/cloud/1.1` (Tokyo second Zone) -DNS service is independent of zones, so you can use any of these endpoints. -The default is the Ishikari first Zone. +DNS service is independent of zones, so you can use any of these endpoints. The default is the Ishikari first Zone. Alternatively you can also use environment variables. @@ -50,8 +48,7 @@ export SAKURACLOUD_ACCESS_TOKEN_SECRET="your-access-token-secret" {% endcode %} ## Metadata -This provider does not recognize any special metadata fields unique to -Sakura Cloud. +This provider does not recognize any special metadata fields unique to Sakura Cloud. ## Usage An example configuration: @@ -67,19 +64,14 @@ D("example.com", REG_NONE, DnsProvider(DSP_SAKURACLOUD), ``` {% endcode %} -`NAMESERVER` does not need to be set as the name servers for the -Sakura Cloud provider cannot be changed. +`NAMESERVER` does not need to be set as the name servers for the Sakura Cloud provider cannot be changed. `SOA` cannot be set as SOA record of Sakura Cloud provider cannot be changed. ## Activation Sakura Cloud depends on an [API Key](https://manual.sakura.ad.jp/cloud/api/apikey.html). -When creating an API key, select "can modify settings" as "Access level". -if you plan to create zones, select "can create and delete resources" as -"Access level". -None of the options in the "Allow access to other services" field need -to be checked. +When creating an API key, select "can modify settings" as "Access level". if you plan to create zones, select "can create and delete resources" as "Access level". None of the options in the "Allow access to other services" field need to be checked. ## Caveats The limitations of the Sakura Cloud DNS service are described in [the DNS manual](https://manual.sakura.ad.jp/cloud/appliance/dns/index.html), which is written in Japanese. diff --git a/documentation/release/release-engineering.md b/documentation/release/release-engineering.md index af0e489327..835422bc4d 100644 --- a/documentation/release/release-engineering.md +++ b/documentation/release/release-engineering.md @@ -4,8 +4,7 @@ These are the instructions for producing a release. GitHub Actions (GHA) will do most of the work for you. You will need to edit the draft release notes and click a button to make the release public. -Please change the version number as appropriate. Substitute (for example) -`v4.2.0` any place you see `$VERSION` in this doc. +Please change the version number as appropriate. Substitute (for example) `v4.2.0` any place you see `$VERSION` in this doc. ## Step 0. Update dependencies @@ -40,16 +39,13 @@ git tag -m "Release $VERSION" -a $VERSION git push origin HEAD --tags ``` -Soon after -GitHub will start an [Action](https://github.com/DNSControl/dnscontrol/actions) Workflow called "draft release" which will build all release binaries and write the draft release notes. +Soon after GitHub will start an [Action](https://github.com/DNSControl/dnscontrol/actions) Workflow called "draft release" which will build all release binaries and write the draft release notes. ## Step 3. Create the release notes The draft release notes are created for you. In this step you'll edit them. -The GHA workflow uses [GoReleaser](https://goreleaser.com/) which produces the [GitHub Release](https://github.com/DNSControl/dnscontrol/releases) with Release Notes derived from the commit history between now and the last tag. -These notes are just a draft and needs considerable editing. -These release notes are used elsewhere, in particular the email step. +The GHA workflow uses [GoReleaser](https://goreleaser.com/) which produces the [GitHub Release](https://github.com/DNSControl/dnscontrol/releases) with Release Notes derived from the commit history between now and the last tag. These notes are just a draft and needs considerable editing. These release notes are used elsewhere, in particular the email step. Release notes style guide: @@ -89,9 +85,7 @@ If you are at Stack Overflow: ## Tip: How to bump the major version -If you bump the major version, you need to change all the source -files. The last time this was done (v3 -> v4) these two commands -were used. They're included her for reference. +If you bump the major version, you need to change all the source files. The last time this was done (v3 -> v4) these two commands were used. They're included her for reference. ```shell # Make all the changes: @@ -123,8 +117,7 @@ GHA is configured to run an integration test for any provider listed in the "pro 1. Edit `.github/workflows/pr_test.yml` 2. Add the `FOO_DOMAIN` variable name of the provider to the "PROVIDERS" list. 3. Set the `FOO_DOMAIN` variables in GHA via https://github.com/DNSControl/dnscontrol/settings/variables/actions -4. All other variables should be stored as secrets (for consistency). Add them to the `integration-tests` section. -Set them in GHA via https://github.com/DNSControl/dnscontrol/settings/secrets/actions +4. All other variables should be stored as secrets (for consistency). Add them to the `integration-tests` section. Set them in GHA via https://github.com/DNSControl/dnscontrol/settings/secrets/actions ### How do I add a "bring your own keys" integration test? @@ -140,7 +133,6 @@ Overview: You will fork the repo and add any secrets to your fork. For security 5. Start a build - ## Tip: How to rebuild flattener Rebuilding flatter requires go1.17.1 and the gopherjs compiler. diff --git a/documentation/release/v316.md b/documentation/release/v316.md index d14cea7310..f82c8b5b17 100644 --- a/documentation/release/v316.md +++ b/documentation/release/v316.md @@ -2,21 +2,15 @@ **Feel free to skip to "How do I convert?" if you don't care about the details.** -Starting in v3.16 the "provider type identifier" (PTI) will be located in -`creds.json` instead of `dnsconfig.js`. The PTI is the all caps string like -`ROUTE53` or `CLOUDFLAREAPI` used to identify a provider's type. +Starting in v3.16 the "provider type identifier" (PTI) will be located in `creds.json` instead of `dnsconfig.js`. The PTI is the all caps string like `ROUTE53` or `CLOUDFLAREAPI` used to identify a provider's type. -V3.16 will enable a syntax that is backwards and forwards compatible. The old -syntax will be removed in v4.0. There's no planned release date for v4.0 but -it is expected to be after Dec 31, 2022. +V3.16 will enable a syntax that is backwards and forwards compatible. The old syntax will be removed in v4.0. There's no planned release date for v4.0 but it is expected to be after Dec 31, 2022. -The change was discussed -in [Request for Comments: Include the provider type in creds.json, remove it from dnsconfig.js](https://github.com/DNSControl/dnscontrol/issues/1457) where we decided "Plan A" would be selected. +The change was discussed in [Request for Comments: Include the provider type in creds.json, remove it from dnsconfig.js](https://github.com/DNSControl/dnscontrol/issues/1457) where we decided "Plan A" would be selected. # What does this mean to you? -In a nutshell, `NewRegistrar()` and `NewDnsProvider()` will lose the 2nd -parameter: +In a nutshell, `NewRegistrar()` and `NewDnsProvider()` will lose the 2nd parameter: {% code title="dnsconfig.js" %} ```diff @@ -33,9 +27,7 @@ var DSP_CF = NewDnsProvider( ``` {% endcode %} -The second parameter (`GANDI_V5` and `CLOUDFLAREAPI` in the -above examples) has moved to `creds.json` instead. It will be in a `TYPE` -field, which all providers have. It can appear in both places for backwards compatibility for now. +The second parameter (`GANDI_V5` and `CLOUDFLAREAPI` in the above examples) has moved to `creds.json` instead. It will be in a `TYPE` field, which all providers have. It can appear in both places for backwards compatibility for now. {% code title="creds.json" %} ```diff @@ -76,15 +68,11 @@ The following subcommands require the PTI a parameter on the command line: * `get-zones` * `check-creds` -In 3.16, that parameter can be changed to `-` as a placeholder, or removed -entirely if it is the last parameter on the command line. When you omit this -parameter, DNSControl will find the value in `creds.json` instead. +In 3.16, that parameter can be changed to `-` as a placeholder, or removed entirely if it is the last parameter on the command line. When you omit this parameter, DNSControl will find the value in `creds.json` instead. In 4.0, that parameter will be removed, though a `-` is permitted for backwards compatibility. -In other words, if you add the `TYPE` field to `creds.json`, you no longer need -to specify it on the command line. You can specify `-` instead, or leave it -out entirely starting in v4.0. +In other words, if you add the `TYPE` field to `creds.json`, you no longer need to specify it on the command line. You can specify `-` instead, or leave it out entirely starting in v4.0. For check-creds: @@ -145,16 +133,13 @@ dnscontrol get-zones --format=djs --out=draft.js glcoud - example.com ## Step 1: Upgrade -Upgrade to v3.16 or later. If DNSControl is installed in many places, do not -continue until they are all at v3.16 or later. +Upgrade to v3.16 or later. If DNSControl is installed in many places, do not continue until they are all at v3.16 or later. ## Step 2: Edit creds.json Now that all uses of DNSControl are on v3.16 or later... -For each `creds.json` entry, add a field "TYPE" set to the provider type -identifier. This is the all-caps name such as `ROUTE53`, `GCLOUD`, or -`CLOUDFLAREAPI`. +For each `creds.json` entry, add a field "TYPE" set to the provider type identifier. This is the all-caps name such as `ROUTE53`, `GCLOUD`, or `CLOUDFLAREAPI`. For example, here is a new-style `creds.json` file with `TYPE` fields added: @@ -192,7 +177,6 @@ WARNING: For future compatibility, update the "namedotcom_main" entry in `creds. ...it means that the TYPE field is missing from that entry in `creds.json`. - If you see something like... ```text @@ -201,7 +185,6 @@ ERROR: Mismatch found! creds.json entry "namedotcom_main" has "TYPE" set to "ROU ...it means your `dnsconfig.js` and `creds.json` specify mismatched values. Fix one or the other. - After you correct some warnings, you may receive information messages like... ```text @@ -233,13 +216,9 @@ Again, run `dnscontrol preview` to verify you setup still works as expected. ## Step 5: Update any shell scripts -Any shell scripts or documentation that uses the subcommands `get-zone`, -`get-zones` or `check-creds` should be updated. The "provider type" parameter -should be changed to `-`. If it is the last parameter on the command, it can -be removed. +Any shell scripts or documentation that uses the subcommands `get-zone`, `get-zones` or `check-creds` should be updated. The "provider type" parameter should be changed to `-`. If it is the last parameter on the command, it can be removed. -It's unlikely you have scripts that use these commands. However you may have -documentation that refers to them and needs to be updated. +It's unlikely you have scripts that use these commands. However you may have documentation that refers to them and needs to be updated. ## Step 4: Test