From 73a1eafef418cf10df58acda2e528891553f1489 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Thu, 16 Mar 2017 17:20:46 -0700 Subject: [PATCH 1/4] Quick pass at a doc about records support & config. --- docs/records.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 docs/records.md diff --git a/docs/records.md b/docs/records.md new file mode 100644 index 0000000..21ba49b --- /dev/null +++ b/docs/records.md @@ -0,0 +1,84 @@ +# OctoDNS records + +## Record types + +OctoDNS supports the following record types: + +* `A` +* `AAAA` +* `CNAME` +* `MX` +* `NAPTR` +* `NS` +* `PTR` +* `SSHFP` +* `SPF` +* `SRV` +* `TXT` + +Underlying provider support for each of these varies and some providers have extra requirements or limitations. In cases where a record type is not supported by a provider OctoDNS will ignore it there and continue to manage the record elsewhere. For example `SSHFP` is supported by Dyn, but not Route53. If your source data includes an SSHFP record OctoDNS will keep it in sync on Dyn, but not consider it when evaluating the state of Route53. The best way to find out what types are supported by a provider is to look for its `supports` method. If that method exists the logic will drive which records are supported and which are ignored. If the provide does not implement the method it will fall back to `BaseProvider.supports` which indicates full support. + +Adding new record types to OctoDNS is relatively straightforward, but will require careful evaluation of each provider to determine whether or not it will be supported and the addition of code in each to handle the new type. + +## GeoDNS support + +GeoDNS is currently supported for `A` and `AAAA` records on the Dyn (via Traffic Directors) and Route53 providers. Records with geo information pushed to providers without support for them will be managed as plain records using the base values and ignoring the `geo` section. + +Configuring GeoDNS is complex and the details of the functionality vary widely from provider to provider. OctoDNS has an opinionated view of how GeoDNS should be set up and does its best to map that to each providers offering in a way that will result in similar behavior. It may not fit your needs or use cases, in which case please open an issue for discussion. We expect this functionality to grow and evolve over time as others evaluate and use it. + +## Config (`YamlProvider`) + +OctoDNS records and `YamlProvider`'s schema is essentially a 1:1 match. Properties on the objects will match keys in the config. + +### Names + +Each top-level key in the yaml file is a record name. Two common special cases are the root record `''`, and a wildcard `'*'`. + +``` +--- +'': + type: A + values: + - 1.2.3.4 + - 1.2.3.5 +'*': + type: CNAME + value: www.example.com. +www: + type: A + values: + - 1.2.3.4 + - 1.2.3.5 +www.sub: + type: A + values: + - 1.2.3.6 + - 1.2.3.7 +``` + +The above config lays out 4 records, `A`s for `example.com.`, `www.example.com.`, and `www.sub.example.com` and a wildcard `CNAME` mapping `*.example.com.` to `www.example.com.`. + +### Multiple records + +In the above example each name had a single record, but there are cases where a name will need to have multiple records associated with it. This can be accomplished by using a list. + +``` +--- +'': + - type: A + values: + - 1.2.3.4 + - 1.2.3.5 + - type: MX + values: + - priority: 10 + value: mx1.example.com. + - priority: 10 + value: mx2.example.com. +``` + +### Record data + +Each record type has a corresponding set of required data. The easiest way to determine what's required is probably to create a partial record and use `octodns-validate` which will throw errors about what's missing. + +`type` is required for all records. `ttl` is optional. When TTL is not specified the provider default will be used. In any situation where an array of `values` can be used you can opt to go with `value` as a single item if there's only one. From c34bdbb4f57cbff220ab065793a8297ac9aab931 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Fri, 17 Mar 2017 09:08:24 -0700 Subject: [PATCH 2/4] Correct CODE_OF_CONDUCT email --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d05f4bc..5b0ae4d 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -55,7 +55,7 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [INSERT EMAIL ADDRESS]. All +reported by contacting the project team at opensource@github.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. From 8fa2ddee09929aadcb3b8db4ce98cc672c889b8e Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Fri, 17 Mar 2017 09:20:05 -0700 Subject: [PATCH 3/4] Pass of edits & cleanup to records.md --- docs/records.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/records.md b/docs/records.md index 21ba49b..2642470 100644 --- a/docs/records.md +++ b/docs/records.md @@ -16,15 +16,15 @@ OctoDNS supports the following record types: * `SRV` * `TXT` -Underlying provider support for each of these varies and some providers have extra requirements or limitations. In cases where a record type is not supported by a provider OctoDNS will ignore it there and continue to manage the record elsewhere. For example `SSHFP` is supported by Dyn, but not Route53. If your source data includes an SSHFP record OctoDNS will keep it in sync on Dyn, but not consider it when evaluating the state of Route53. The best way to find out what types are supported by a provider is to look for its `supports` method. If that method exists the logic will drive which records are supported and which are ignored. If the provide does not implement the method it will fall back to `BaseProvider.supports` which indicates full support. +Underlying provider support for each of these varies and some providers have extra requirements or limitations. In cases where a record type is not supported by a provider OctoDNS will ignore it there and continue to manage the record elsewhere. For example `SSHFP` is supported by Dyn, but not Route53. If your source data includes an SSHFP record OctoDNS will keep it in sync on Dyn, but not consider it when evaluating the state of Route53. The best way to find out what types are supported by a provider is to look for its `supports` method. If that method exists the logic will drive which records are supported and which are ignored. If the provider does not implement the method it will fall back to `BaseProvider.supports` which indicates full support. -Adding new record types to OctoDNS is relatively straightforward, but will require careful evaluation of each provider to determine whether or not it will be supported and the addition of code in each to handle the new type. +Adding new record types to OctoDNS is relatively straightforward, but will require careful evaluation of each provider to determine whether or not it will be supported and the addition of code in each to handle and test the new type. ## GeoDNS support -GeoDNS is currently supported for `A` and `AAAA` records on the Dyn (via Traffic Directors) and Route53 providers. Records with geo information pushed to providers without support for them will be managed as plain records using the base values and ignoring the `geo` section. +GeoDNS is currently supported for `A` and `AAAA` records on the Dyn (via Traffic Directors) and Route53 providers. Records with geo information pushed to providers without support for them will be managed as non-geo records using the base values. -Configuring GeoDNS is complex and the details of the functionality vary widely from provider to provider. OctoDNS has an opinionated view of how GeoDNS should be set up and does its best to map that to each providers offering in a way that will result in similar behavior. It may not fit your needs or use cases, in which case please open an issue for discussion. We expect this functionality to grow and evolve over time as others evaluate and use it. +Configuring GeoDNS is complex and the details of the functionality vary widely from provider to provider. OctoDNS has an opinionated view of how GeoDNS should be set up and does its best to map that to each provider's offering in a way that will result in similar behavior. It may not fit your needs or use cases, in which case please open an issue for discussion. We expect this functionality to grow and evolve over time as it's more widely used. ## Config (`YamlProvider`) @@ -79,6 +79,6 @@ In the above example each name had a single record, but there are cases where a ### Record data -Each record type has a corresponding set of required data. The easiest way to determine what's required is probably to create a partial record and use `octodns-validate` which will throw errors about what's missing. +Each record type has a corresponding set of required data. The easiest way to determine what's required is probably to look at the record object in [`octodns/records.py`](/octodns/records.py). You may also utilize `octodns-validate` which will throw errors about what's missing when run. -`type` is required for all records. `ttl` is optional. When TTL is not specified the provider default will be used. In any situation where an array of `values` can be used you can opt to go with `value` as a single item if there's only one. +`type` is required for all records. `ttl` is optional. When TTL is not specified the `YamlProvider`'s default will be used. In any situation where an array of `values` can be used you can opt to go with `value` as a single item if there's only one. From da4632fb7cfb533c6b65e6b53675ef5c7b95f0dc Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Fri, 17 Mar 2017 10:03:27 -0700 Subject: [PATCH 4/4] docstrings for each provider showing config --- README.md | 4 ++++ octodns/provider/cloudflare.py | 10 ++++++++++ octodns/provider/dnsimple.py | 10 ++++++++++ octodns/provider/dyn.py | 15 +++++++++++++++ octodns/provider/powerdns.py | 19 +++++++++++++++++++ octodns/provider/route53.py | 12 ++++++++++++ octodns/provider/yaml.py | 11 +++++++++++ octodns/source/tinydns.py | 14 +++++++++++--- 8 files changed, 92 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9f5ad37..70357cd 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ zones: `class` is a special key that tells OctoDNS what python class should be loaded. Any other keys will be passed as configuration values to that provider. In general any sensitive or frequently rotated values should come from environmental variables. When OctoDNS sees a value that starts with `env/` it will look for that value in the process's environment and pass the result along. +Further information can be found in the `docstring` of each source and provider class. + Now that we have something to tell OctoDNS about our providers & zones we need to tell it about or records. We'll keep it simple for now and just create a single `A` record at the top-level of the domain. `config/example.com.yaml` @@ -70,6 +72,8 @@ Now that we have something to tell OctoDNS about our providers & zones we need t - 1.2.3.5 ``` +Further information can be found in [Records Documentation](/docs/records.md`). + ### Noop We're ready to do a dry-run with our new setup to see what changes it would make. Since we're pretending here we'll act like there are no existing records for `example.com.` in our accounts on either provider. diff --git a/octodns/provider/cloudflare.py b/octodns/provider/cloudflare.py index 95df47a..a67db66 100644 --- a/octodns/provider/cloudflare.py +++ b/octodns/provider/cloudflare.py @@ -24,6 +24,16 @@ class CloudflareAuthenticationError(Exception): class CloudflareProvider(BaseProvider): + ''' + Cloudflare DNS provider + + cloudflare: + class: octodns.provider.cloudflare.CloudflareProvider + # Your Cloudflare account email address (required) + email: dns-manager@example.com + # The api key (required) + token: foo + ''' SUPPORTS_GEO = False # TODO: support SRV UNSUPPORTED_TYPES = ('NAPTR', 'PTR', 'SOA', 'SRV', 'SSHFP') diff --git a/octodns/provider/dnsimple.py b/octodns/provider/dnsimple.py index 4c9663c..7ed4fe7 100644 --- a/octodns/provider/dnsimple.py +++ b/octodns/provider/dnsimple.py @@ -80,6 +80,16 @@ class DnsimpleClient(object): class DnsimpleProvider(BaseProvider): + ''' + Dnsimple provider using API v2 + + dnsimple: + class: octodns.provider.dnsimple.DnsimpleProvider + # API v2 account access token (required) + token: letmein + # Your account number (required) + account: 42 + ''' SUPPORTS_GEO = False def __init__(self, id, token, account, *args, **kwargs): diff --git a/octodns/provider/dyn.py b/octodns/provider/dyn.py index e0a86fa..321bad5 100644 --- a/octodns/provider/dyn.py +++ b/octodns/provider/dyn.py @@ -81,6 +81,21 @@ class _CachingDynZone(DynZone): class DynProvider(BaseProvider): + ''' + Dynect Managed DNS provider + + dyn: + class: octodns.provider.dyn.DynProvider + # Your dynect customer name (required) + customer: cust + # Your dynect username (required) + username: user + # Your dynect password (required) + password: pass + # Whether or not to support TrafficDirectors and enable GeoDNS + # (optional, default is false) + traffic_directors_enabled: true + ''' RECORDS_TO_TYPE = { 'a_records': 'A', 'aaaa_records': 'AAAA', diff --git a/octodns/provider/powerdns.py b/octodns/provider/powerdns.py index 25e7313..0f9190b 100644 --- a/octodns/provider/powerdns.py +++ b/octodns/provider/powerdns.py @@ -337,6 +337,25 @@ class PowerDnsBaseProvider(BaseProvider): class PowerDnsProvider(PowerDnsBaseProvider): + ''' + PowerDNS API v4 Provider + + powerdns: + class: octodns.provider.powerdns.PowerDnsProvider + # The host on which PowerDNS api is listening (required) + host: fqdn + # The api key that grans access (required) + api_key: api-key + # The port on which PowerDNS api is listening (optional, default 8081) + port: 8081 + # The nameservers to use for this provider (optional, + # default unmanaged) + nameserver_values: + - 1.2.3.4. + - 1.2.3.5. + # The nameserver record TTL when managed, (optional, default 600) + nameserver_ttl: 600 + ''' def __init__(self, id, host, api_key, port=8081, nameserver_values=None, nameserver_ttl=600, *args, **kwargs): diff --git a/octodns/provider/route53.py b/octodns/provider/route53.py index 634c526..5415a2d 100644 --- a/octodns/provider/route53.py +++ b/octodns/provider/route53.py @@ -140,6 +140,18 @@ def _octal_replace(s): class Route53Provider(BaseProvider): + ''' + AWS Route53 Provider + + route53: + class: octodns.provider.route53.Route53Provider + # The AWS access key id (required) + access_key_id: + # The AWS secret access key (required) + secret_access_key: + + In general the account used will need full permissions on Route53. + ''' SUPPORTS_GEO = True # This should be bumped when there are underlying changes made to the diff --git a/octodns/provider/yaml.py b/octodns/provider/yaml.py index d335d85..1089f02 100644 --- a/octodns/provider/yaml.py +++ b/octodns/provider/yaml.py @@ -16,6 +16,17 @@ from .base import BaseProvider class YamlProvider(BaseProvider): + ''' + Core provider for records configured in yaml files on disk. + + config: + class: octodns.provider.yaml.YamlProvider + # The location of yaml config files (required) + directory: ./config + # The ttl to use for records when not specified in the data + # (optional, default 3600) + default_ttl: 3600 + ''' SUPPORTS_GEO = True def __init__(self, id, directory, default_ttl=3600, *args, **kwargs): diff --git a/octodns/source/tinydns.py b/octodns/source/tinydns.py index 7d66998..70f0145 100644 --- a/octodns/source/tinydns.py +++ b/octodns/source/tinydns.py @@ -17,13 +17,13 @@ from ..zone import DuplicateRecordException, SubzoneRecordException from .base import BaseSource -class TinyDnsSource(BaseSource): +class TinyDnsBaseSource(BaseSource): SUPPORTS_GEO = False split_re = re.compile(r':+') def __init__(self, id, default_ttl=3600): - super(TinyDnsSource, self).__init__(id) + super(TinyDnsBaseSource, self).__init__(id) self.default_ttl = default_ttl def _data_for_A(self, _type, records): @@ -177,10 +177,18 @@ class TinyDnsSource(BaseSource): 'skipping'.format(addr)) -class TinyDnsFileSource(TinyDnsSource): +class TinyDnsFileSource(TinyDnsBaseSource): ''' A basic TinyDNS zonefile importer created to import legacy data. + tinydns: + class: octodns.source.tinydns.TinyDnsFileSource + # The location of the TinyDNS zone files + directory: ./zones + # The ttl to use for records when not specified in the data + # (optional, default 3600) + default_ttl: 3600 + NOTE: timestamps & lo fields are ignored if present. ''' def __init__(self, id, directory, default_ttl=3600):