mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-12 18:37:54 +08:00
2f83aa9302
* Switched to v2 go.mod Also set GO111MODULE=on in build stuff to always use Go modules even when in GOPATH. * Ensure go.mod, go.sum, and vendor are up to date * Attempt to fix Azure pipelines * Add set -e to properly fail on exit (it didn't seem to be propagating properly before). * Set workingDirectory for GoFmt and GoGen (this might be why it fails unlike compile and unitests). * Another attempt to fix Azure Pipelines * Use the Go env template for all go-related jobs. * Completely fixed Azure Pipelines * Added a display name to GoFmt for consistency. * Fixed diffs for GoFmt and GoGen. * Show git status for checks. * Drop GOPATH for tests TODO: Do the same for integration tests. * Drop GOPATH for integration tests * Show more diffs * Regenerate provider support matrix This wasn't done in #590...
170 lines
4.6 KiB
Go
170 lines
4.6 KiB
Go
package octodns
|
|
|
|
/*
|
|
|
|
octodns -
|
|
Generate zonefiles suitiable for OctoDNS.
|
|
|
|
The zonefiles are read and written to the directory octoconfig
|
|
|
|
If the old octoconfig files are readable, we read them to determine
|
|
if an update is actually needed.
|
|
|
|
The YAML input and output code is extremely complicated because
|
|
the format does not fit well with a statically typed language.
|
|
The YAML format changes drastically if the label has single
|
|
or multiple rtypes associated with it, and if there is a single
|
|
or multiple rtype data.
|
|
|
|
*/
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/StackExchange/dnscontrol/v2/models"
|
|
"github.com/StackExchange/dnscontrol/v2/providers"
|
|
"github.com/StackExchange/dnscontrol/v2/providers/diff"
|
|
"github.com/StackExchange/dnscontrol/v2/providers/octodns/octoyaml"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var features = providers.DocumentationNotes{
|
|
//providers.CanUseCAA: providers.Can(),
|
|
providers.CanUsePTR: providers.Can(),
|
|
providers.CanUseSRV: providers.Can(),
|
|
//providers.CanUseTXTMulti: providers.Can(),
|
|
providers.DocCreateDomains: providers.Cannot("Driver just maintains list of OctoDNS config files. You must manually create the master config files that refer these."),
|
|
providers.DocDualHost: providers.Cannot("Research is needed."),
|
|
}
|
|
|
|
func initProvider(config map[string]string, providermeta json.RawMessage) (providers.DNSServiceProvider, error) {
|
|
// config -- the key/values from creds.json
|
|
// meta -- the json blob from NewReq('name', 'TYPE', meta)
|
|
api := &Provider{
|
|
directory: config["directory"],
|
|
}
|
|
if api.directory == "" {
|
|
api.directory = "config"
|
|
}
|
|
if len(providermeta) != 0 {
|
|
err := json.Unmarshal(providermeta, api)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
//api.nameservers = models.StringsToNameservers(api.DefaultNS)
|
|
return api, nil
|
|
}
|
|
|
|
func init() {
|
|
providers.RegisterDomainServiceProviderType("OCTODNS", initProvider, features)
|
|
}
|
|
|
|
// Provider is the provider handle for the OctoDNS driver.
|
|
type Provider struct {
|
|
//DefaultNS []string `json:"default_ns"`
|
|
//DefaultSoa SoaInfo `json:"default_soa"`
|
|
//nameservers []*models.Nameserver
|
|
directory string
|
|
}
|
|
|
|
// GetNameservers returns the nameservers for a domain.
|
|
func (c *Provider) GetNameservers(string) ([]*models.Nameserver, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// GetDomainCorrections returns a list of corrections to update a domain.
|
|
func (c *Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
|
dc.Punycode()
|
|
// Phase 1: Copy everything to []*models.RecordConfig:
|
|
// expectedRecords < dc.Records[i]
|
|
// foundRecords < zonefile
|
|
//
|
|
// Phase 2: Do any manipulations:
|
|
// add NS
|
|
// manipulate SOA
|
|
//
|
|
// Phase 3: Convert to []diff.Records and compare:
|
|
// expectedDiffRecords < expectedRecords
|
|
// foundDiffRecords < foundRecords
|
|
// diff.Inc...(foundDiffRecords, expectedDiffRecords )
|
|
|
|
// Read foundRecords:
|
|
var foundRecords models.Records
|
|
zoneFileFound := true
|
|
zoneFileName := filepath.Join(c.directory, strings.Replace(strings.ToLower(dc.Name), "/", "_", -1)+".yaml")
|
|
foundFH, err := os.Open(zoneFileName)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
zoneFileFound = false
|
|
} else {
|
|
return nil, errors.Wrapf(err, "can't open %s:", zoneFileName)
|
|
}
|
|
} else {
|
|
foundRecords, err = octoyaml.ReadYaml(foundFH, dc.Name)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "can not get corrections")
|
|
}
|
|
}
|
|
|
|
// Normalize
|
|
models.PostProcessRecords(foundRecords)
|
|
|
|
differ := diff.New(dc)
|
|
_, create, del, mod := differ.IncrementalDiff(foundRecords)
|
|
|
|
buf := &bytes.Buffer{}
|
|
// Print a list of changes. Generate an actual change that is the zone
|
|
changes := false
|
|
for _, i := range create {
|
|
changes = true
|
|
fmt.Fprintln(buf, i)
|
|
}
|
|
for _, i := range del {
|
|
changes = true
|
|
fmt.Fprintln(buf, i)
|
|
}
|
|
for _, i := range mod {
|
|
changes = true
|
|
fmt.Fprintln(buf, i)
|
|
}
|
|
msg := fmt.Sprintf("GENERATE_CONFIGFILE: %s", dc.Name)
|
|
if zoneFileFound {
|
|
msg += "\n"
|
|
msg += buf.String()
|
|
} else {
|
|
msg += fmt.Sprintf(" (%d records)\n", len(create))
|
|
}
|
|
corrections := []*models.Correction{}
|
|
if changes {
|
|
corrections = append(corrections,
|
|
&models.Correction{
|
|
Msg: msg,
|
|
F: func() error {
|
|
fmt.Printf("CREATING CONFIGFILE: %v\n", zoneFileName)
|
|
zf, err := os.Create(zoneFileName)
|
|
if err != nil {
|
|
log.Fatalf("Could not create zonefile: %v", err)
|
|
}
|
|
//err = WriteZoneFile(zf, dc.Records, dc.Name)
|
|
err = octoyaml.WriteYaml(zf, dc.Records, dc.Name)
|
|
if err != nil {
|
|
log.Fatalf("WriteZoneFile error: %v\n", err)
|
|
}
|
|
err = zf.Close()
|
|
if err != nil {
|
|
log.Fatalf("Closing: %v", err)
|
|
}
|
|
return nil
|
|
},
|
|
})
|
|
}
|
|
|
|
return corrections, nil
|
|
}
|