Adding gandi to integration suite. Fixing bugs. (#57)

* Adding gandi to integration suite. Fixing bugs.
Fixes #35
Fixes #36

* small fixes

* gandi docs
This commit is contained in:
Craig Peterson 2017-03-27 16:03:01 -06:00 committed by GitHub
parent efb8e9bbf4
commit d205c8b4ed
6 changed files with 104 additions and 27 deletions

View file

@ -26,7 +26,8 @@ This provider does not recognize any special metadata fields unique to DNSimple.
Example javascript:
{% highlight js %}
var DNSIMPLE = NewDnsProvider("dnsimple", DNSIMPLE);
var REG_DNSIMPLE = NewRegistrar("dnsimple", "DNSIMPLE");
var DNSIMPLE = NewDnsProvider("dnsimple", "DNSIMPLE");
D("example.tld", REG_DNSIMPLE, DnsProvider(DNSIMPLE),
A("test","1.2.3.4")

38
docs/_providers/gandi.md Normal file
View file

@ -0,0 +1,38 @@
---
name: Gandi
layout: default
jsId: GANDI
---
# Gandi Provider
Gandi provides bot a registrar and a dns provider implementation.
## Configuration
In your providers config json file you must provide your Gandi.net api key:
{% highlight json %}
{
"gandi":{
"apikey": "your-gandi-key"
}
}
{% endhighlight %}
## Metadata
This provider does not recognize any special metadata fields unique to DNSimple.
## Usage
Example javascript:
{% highlight js %}
var REG_GANDI = NewRegistrar("gandi", "GANDI");
var GANDI = NewDnsProvider("gandi", "GANDI");
D("example.tld", REG_GANDI, DnsProvider(GANDI),
A("test","1.2.3.4")
);
{% endhighlight %}

View file

@ -3,11 +3,18 @@
"domain": "example.com"
},
"DNSIMPLE": {
//16/17: no ns records managable. Not even for subdomains.
"knownFailures": "16,17",
"domain": "$DNSIMPLE_DOMAIN",
"token": "$DNSIMPLE_TOKEN",
"baseurl": "https://api.sandbox.dnsimple.com"
},
"GANDI":{
//5: gandi does not accept ttls less than 300
"knownFailures": "5",
"domain": "$GANDI_DOMAIN",
"apikey": "$GANDI_KEY"
},
"GCLOUD": {
"domain": "$GCLOUD_DOMAIN",
"project_id": "$GCLOUD_PROJECT",

View file

@ -191,6 +191,17 @@ func (dc *DomainConfig) Punycode() error {
return nil
}
// CombineMXs will merge the priority into the target field for all mx records.
// Useful for providers that desire them as one field.
func (dc *DomainConfig) CombineMXs() {
for _, rec := range dc.Records {
if rec.Type == "MX" {
rec.Target = fmt.Sprintf("%d %s", rec.Priority, rec.Target)
rec.Priority = 0
}
}
}
func copyObj(input interface{}, output interface{}) error {
buf := &bytes.Buffer{}
enc := gob.NewEncoder(buf)

View file

@ -3,11 +3,14 @@ package gandi
import (
"encoding/json"
"fmt"
"log"
"github.com/StackExchange/dnscontrol/models"
"github.com/StackExchange/dnscontrol/providers"
"github.com/StackExchange/dnscontrol/providers/diff"
"strings"
gandidomain "github.com/prasmussen/gandi-api/domain"
gandirecord "github.com/prasmussen/gandi-api/domain/zone/record"
)
@ -56,48 +59,63 @@ func (c *GandiApi) GetNameservers(domain string) ([]*models.Nameserver, error) {
}
func (c *GandiApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
dc.Punycode()
dc.CombineMXs()
domaininfo, err := c.getDomainInfo(dc.Name)
if err != nil {
return nil, err
}
foundRecords, err := c.getZoneRecords(domaininfo.ZoneId)
foundRecords, err := c.getZoneRecords(domaininfo.ZoneId, dc.Name)
if err != nil {
return nil, err
}
expectedRecordSets := make([]gandirecord.RecordSet, len(dc.Records))
for i, rec := range dc.Records {
if rec.Type == "MX" {
rec.Target = fmt.Sprintf("%d %s", rec.Priority, rec.Target)
expectedRecordSets := make([]gandirecord.RecordSet, 0, len(dc.Records))
recordsToKeep := make([]*models.RecordConfig, 0, len(dc.Records))
for _, rec := range dc.Records {
if rec.TTL < 300 {
log.Printf("WARNING: Gandi does not support ttls < 300. %s will not be set to %d.", rec.NameFQDN, rec.TTL)
rec.TTL = 300
}
if rec.Type == "TXT" {
rec.Target = "\"" + rec.Target + "\"" // FIXME(tlim): Should do proper quoting.
}
expectedRecordSets[i] = gandirecord.RecordSet{}
expectedRecordSets[i]["type"] = rec.Type
expectedRecordSets[i]["name"] = rec.Name
expectedRecordSets[i]["value"] = rec.Target
expectedRecordSets[i]["ttl"] = rec.TTL
if rec.Type == "NS" && rec.Name == "@" {
if !strings.HasSuffix(rec.Target, ".gandi.net.") {
log.Printf("WARNING: Gandi does not support changing apex NS records. %s will not be added.", rec.Target)
}
continue
}
rs := gandirecord.RecordSet{
"type": rec.Type,
"name": rec.Name,
"value": rec.Target,
"ttl": rec.TTL,
}
expectedRecordSets = append(expectedRecordSets, rs)
recordsToKeep = append(recordsToKeep, rec)
}
dc.Records = recordsToKeep
differ := diff.New(dc)
_, create, del, mod := differ.IncrementalDiff(foundRecords)
// Print a list of changes. Generate an actual change that is the zone
changes := false
desc := ""
for _, i := range create {
changes = true
fmt.Println(i)
desc += "\n" + i.String()
}
for _, i := range del {
changes = true
fmt.Println(i)
desc += "\n" + i.String()
}
for _, i := range mod {
changes = true
fmt.Println(i)
desc += "\n" + i.String()
}
msg := fmt.Sprintf("GENERATE_ZONE: %s (%d records)", dc.Name, len(dc.Records))
msg := fmt.Sprintf("GENERATE_ZONE: %s (%d records)%s", dc.Name, len(dc.Records), desc)
corrections := []*models.Correction{}
if changes {
corrections = append(corrections,

View file

@ -10,6 +10,7 @@ import (
gandiversion "github.com/prasmussen/gandi-api/domain/zone/version"
"github.com/StackExchange/dnscontrol/models"
"github.com/miekg/dns/dnsutil"
)
// fetchDomainList gets list of domains for account. Cache ids for easy lookup.
@ -39,7 +40,7 @@ func (c *GandiApi) fetchDomainInfo(fqdn string) (*gandidomain.DomainInfo, error)
}
// getRecordsForDomain returns a list of records for a zone.
func (c *GandiApi) getZoneRecords(zoneid int64) ([]*models.RecordConfig, error) {
func (c *GandiApi) getZoneRecords(zoneid int64, origin string) ([]*models.RecordConfig, error) {
gc := gandiclient.New(c.ApiKey, gandiclient.Production)
record := gandirecord.New(gc)
recs, err := record.List(zoneid, 0)
@ -48,7 +49,7 @@ func (c *GandiApi) getZoneRecords(zoneid int64) ([]*models.RecordConfig, error)
}
rcs := make([]*models.RecordConfig, 0, len(recs))
for _, r := range recs {
rcs = append(rcs, convert(r))
rcs = append(rcs, convert(r, origin))
}
return rcs, nil
}
@ -133,37 +134,37 @@ func (c *GandiApi) activateVersion(zone_id, version_id int64) (bool, error) {
return version.Set(zone_id, version_id)
}
func (c *GandiApi) createGandiZone(domainname string, zone_id int64, records []gandirecord.RecordSet) error {
func (c *GandiApi) createGandiZone(domainname string, zoneID int64, records []gandirecord.RecordSet) error {
// Get the zone_id of the zone we'll be updating.
zoneinfo, err := c.getZoneInfo(zone_id)
zoneinfo, err := c.getZoneInfo(zoneID)
if err != nil {
return err
}
//fmt.Println("ZONEINFO:", zoneinfo)
zone_id, err = c.getEditableZone(domainname, zoneinfo)
zoneID, err = c.getEditableZone(domainname, zoneinfo)
if err != nil {
return err
}
// Get the version_id of the zone we're updating.
version_id, err := c.makeEditableZone(zone_id)
// Get the versionID of the zone we're updating.
versionID, err := c.makeEditableZone(zoneID)
if err != nil {
return err
}
// Update the new version.
_, err = c.setZoneRecords(zone_id, version_id, records)
_, err = c.setZoneRecords(zoneID, versionID, records)
if err != nil {
return err
}
// Activate zone version
_, err = c.activateVersion(zone_id, version_id)
_, err = c.activateVersion(zoneID, versionID)
if err != nil {
return err
}
_, err = c.setZones(domainname, zone_id)
_, err = c.setZones(domainname, zoneID)
if err != nil {
return err
}
@ -171,9 +172,10 @@ func (c *GandiApi) createGandiZone(domainname string, zone_id int64, records []g
return nil
}
func convert(r *gandirecord.RecordInfo) *models.RecordConfig {
func convert(r *gandirecord.RecordInfo, origin string) *models.RecordConfig {
return &models.RecordConfig{
NameFQDN: r.Name,
NameFQDN: dnsutil.AddOrigin(r.Name, origin),
Name: r.Name,
Type: r.Type,
Original: r,
Target: r.Value,