mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-30 19:41:13 +08:00
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:
parent
efb8e9bbf4
commit
d205c8b4ed
6 changed files with 104 additions and 27 deletions
|
@ -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
38
docs/_providers/gandi.md
Normal 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 %}
|
||||
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue