mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
Merge branch 'master' into fix/cci
This commit is contained in:
@ -11,6 +11,40 @@ parameters:
|
||||
description: Go Version to use
|
||||
|
||||
jobs:
|
||||
|
||||
build-docker-image:
|
||||
docker:
|
||||
- image: jdrouet/docker-with-buildx:stable
|
||||
|
||||
environment:
|
||||
DOCKER_IMAGE_NAME: stackexchange/dnscontrol
|
||||
DOCKER_IMAGE_VERSION: 3.18.1
|
||||
DOCKER_IMAGE_PLATFORM: linux/amd64,linux/386
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: 20.10.14 # https://circleci.com/docs/building-docker-images#docker-version
|
||||
docker_layer_caching: true
|
||||
- run:
|
||||
name: Docker login
|
||||
command: |
|
||||
docker login \
|
||||
--username "$DOCKERHUB_USERNAME" \
|
||||
--password "$DOCKERHUB_ACCESS_TOKEN"
|
||||
- deploy:
|
||||
name: Build multi-arch Docker images and push to Docker Hub
|
||||
command: |
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
docker context create multi-arch-build
|
||||
docker buildx create \
|
||||
--use multi-arch-build \
|
||||
--platform $DOCKER_IMAGE_PLATFORM
|
||||
docker buildx build \
|
||||
--push \
|
||||
--platform $DOCKER_IMAGE_PLATFORM \
|
||||
--tag $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_VERSION .
|
||||
|
||||
build:
|
||||
|
||||
docker:
|
||||
@ -173,3 +207,6 @@ workflows:
|
||||
only: [master, main, fix/cci]
|
||||
tags:
|
||||
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
|
||||
|
||||
- build-docker-image:
|
||||
context: DNSControl
|
||||
|
@ -187,6 +187,7 @@ See [dnscontrol-action](https://github.com/koenrh/dnscontrol-action)
|
||||
|
||||
* **Call for new volunteer maintainers for NAMEDOTCOM, and SOFTLAYER.** These providers have no maintainer. Maintainers respond to PRs and fix bugs in a timely manner, and try to stay on top of protocol changes.
|
||||
* **ACME/Let's Encrypt support is frozen and will be removed after December 31, 2022.** The `get-certs` command (renews certs via Let's Encrypt) has no maintainer. There are other projects that do a better job. If you don't use this feature, please do not start. If you do use this feature, please plan on migrating to something else. See discussion in https://github.com/StackExchange/dnscontrol/issues/1400
|
||||
* **Provider OCTODNS is frozen and will be removed after Nov 1, 2022.** It was written as a joke and nobody laughed. It's time to remove the code and move on.
|
||||
* **convertzone is frozen and will be removed after June 30, 2022.** The `convertzone` stand-alone program is replaced by the `get-zone` subcommand of DNSControl. It does everything `convertzone` did and more.
|
||||
* **Provider ACTIVEDIRECTORY_PS is frozen and will be removed after June 30, 2022.** It is replaced by MSDNS which is 100% feature compatible and works better. (We believe nobody uses it.)
|
||||
* **get-zones syntax changes in v3.16** Starting in v3.16, the command line arguments for `dnscontrol get-zones` changes. For backwards compatibility change `provider` to `-`. See documentation for details.
|
||||
|
@ -1,105 +0,0 @@
|
||||
|
||||
!!! NOTE: This command has been replaced by the "dnscontrol get-zones"
|
||||
!!! subcommand. It can do everything convertzone does and more, with
|
||||
!!! fewer bugs. This command will be removed from the distribution soon.
|
||||
|
||||
# convertzone -- Converts a standard DNS zonefile into tsv, pretty, or DSL
|
||||
|
||||
This is a crude hack we put together to read a couple common zonefile
|
||||
formats and output them in a few different formats. Current input
|
||||
formats are BIND zonefiles and OctoDNS "config" YAML files. Current
|
||||
output formats as BIND zonefiles, tab separated records, or a draft
|
||||
DNSControl dnsconfig.js file. For dnsconfig.js, it does about 90%
|
||||
of the work, but should be manually verified.
|
||||
|
||||
The primary purpose of this program is to convert BIND-style
|
||||
zonefiles to DNSControl dnsconfig.js files. Nearly all DNS Service
|
||||
providers include the ability to export records as a BIND-style zonefile.
|
||||
This makes it easy to import DNS data from other systems into DNSControl.
|
||||
Later OctoDNS input was added because we had the parser (as part of
|
||||
the OctoDNS provider), so why not use it?
|
||||
|
||||
## Building the software
|
||||
|
||||
Build the software and install in your personal bin:
|
||||
|
||||
```bash
|
||||
cd cmd/convertzone
|
||||
go build
|
||||
cp convertzone ~/bin/.
|
||||
```
|
||||
|
||||
## Usage Overview
|
||||
|
||||
convertzone: Read and write DNS zone files.
|
||||
|
||||
convertzone [-in=INPUT] [-out=OUTPUT] zonename [filename]
|
||||
|
||||
Input format:
|
||||
-in=bind BIND-style zonefiles (DEFAULT)
|
||||
-in=octodns OctoDNS YAML "config" files.
|
||||
|
||||
Output format:
|
||||
|
||||
-out=dsl DNSControl DSL language (dnsconfig.js) (DEFAULT)
|
||||
-out=tsv TAB-separated values
|
||||
-out=pretty pretty-printed (BIND-style zonefiles)
|
||||
|
||||
zonename The FQDN of the zone name.
|
||||
filename File to read (optional. Defaults to stdin)
|
||||
|
||||
The DSL output format is useful for creating the first
|
||||
draft of your dnsconfig.js when importing zones from
|
||||
other services.
|
||||
|
||||
The TSV format makes it easy to process a zonefile with
|
||||
shell tools.
|
||||
|
||||
The PRETTY format is just a nice way to clean up a zonefile.
|
||||
|
||||
If no filename is specified, stdin is assumed.
|
||||
Output is sent to stdout.
|
||||
|
||||
The zonename is required as it can not be guessed automatically from the input.
|
||||
|
||||
Example:
|
||||
|
||||
convertzone stackoverflow.com zone.stackoverflow.com >new/draft.js
|
||||
|
||||
|
||||
### -out=tsv:
|
||||
|
||||
This is useful for `awk` and other systems that expect a very
|
||||
uniform set of input.
|
||||
|
||||
Example: Print all CNAMEs:
|
||||
|
||||
convertzone -out=tsv foo.com <zone.foo.com | awk '$4 == "CNAME" { print $1 " -> " $5 }'
|
||||
|
||||
|
||||
### -out=pretty:
|
||||
|
||||
This is useful for cleaning up a zonefile. It sorts the records,
|
||||
moving SOA and NS records to the top of the zone; all other records
|
||||
are alphabetically sorted; if a label has mutiple records, they are
|
||||
listed in a logical (not numeric) order, multiple A records are
|
||||
listed sorted by IP address, MX records are sorted by priority,
|
||||
etc. Use `-ttl` to set a default TTL.
|
||||
|
||||
Example: Clean up a zone file:
|
||||
|
||||
convertzone -out=pretty foo.com <old/zone.foo.com >new/zone.foo.com
|
||||
|
||||
|
||||
### -out=dsl:
|
||||
|
||||
This is useful for generating your draft `dnsconfig.js` configuration.
|
||||
The output can be appended to the `dnsconfig.js` file as a good first draft.
|
||||
|
||||
Example: Generate statements for a dnsconfig.js file:
|
||||
|
||||
convertzone -out=dsl foo.com <old/zone.foo.com >first-draft.js
|
||||
|
||||
Note: The conversion is not perfect. You'll need to manually clean
|
||||
it up and insert it into `dnsconfig.js`. More instructions in the
|
||||
DNSControl [migration doc]({site.github.url}}/migration).
|
@ -1,221 +0,0 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
convertzone: Read and write DNS zone files.
|
||||
|
||||
convertzone [-in=INPUT] [-out=OUTPUT] zonename [filename]
|
||||
|
||||
Input format:
|
||||
-in=bind BIND-style zonefiles (DEFAULT)
|
||||
-in=octodns OctoDNS YAML "config" files.
|
||||
|
||||
Output format:
|
||||
|
||||
-out=dsl DNSControl DSL language (dnsconfig.js) (DEFAULT)
|
||||
-out=tsv TAB-separated values
|
||||
-out=pretty pretty-printed (BIND-style zonefiles)
|
||||
|
||||
zonename The FQDN of the zone name.
|
||||
filename File to read (optional. Defaults to stdin)
|
||||
|
||||
The DSL output format is useful for creating the first
|
||||
draft of your dnsconfig.js when importing zones from
|
||||
other services.
|
||||
|
||||
The TSV format makes it easy to process a zonefile with
|
||||
shell tools. `awk -F"\t" $2 = "A" { print $3 }`
|
||||
|
||||
The PRETTY format is just a nice way to clean up a zonefile.
|
||||
|
||||
If no filename is specified, stdin is assumed.
|
||||
Output is sent to stdout.
|
||||
|
||||
The zonename is required as it can not be guessed automatically from the input.
|
||||
*/
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/prettyzone"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers/octodns/octoyaml"
|
||||
)
|
||||
|
||||
var flagInfmt = flag.String("in", "zone", "zone|octodns")
|
||||
var flagOutfmt = flag.String("out", "dsl", "dsl|tsv|pretty")
|
||||
var flagDefaultTTL = flag.Uint("ttl", 300, "Default TTL")
|
||||
var flagRegText = flag.String("registrar", "REG_FILL_IN", "registrar text")
|
||||
var flagProviderText = flag.String("provider", "DNS_FILL_IN", "provider text")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
zonename, filename, reader, err := parseargs(flag.Args())
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %v\n\n", err)
|
||||
fmt.Println("convertzone [-flags] ZONENAME FILENAME")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
defTTL := uint32(*flagDefaultTTL)
|
||||
|
||||
var recs []dns.RR
|
||||
|
||||
// Read it in:
|
||||
|
||||
switch *flagInfmt {
|
||||
case "zone":
|
||||
recs = readZone(zonename, reader, filename)
|
||||
case "oct", "octo", "octodns":
|
||||
recs = readOctodns(zonename, reader, filename)
|
||||
}
|
||||
|
||||
// Write it out:
|
||||
|
||||
switch *flagOutfmt {
|
||||
case "pretty":
|
||||
prettyzone.WriteZoneFileRR(os.Stdout, recs, zonename)
|
||||
case "dsl":
|
||||
fmt.Printf(`D("%s", %s, DnsProvider(%s)`, zonename, *flagRegText, *flagProviderText)
|
||||
rrFormat(zonename, filename, recs, defTTL, true)
|
||||
fmt.Println("\n)")
|
||||
case "tsv":
|
||||
rrFormat(zonename, filename, recs, defTTL, false)
|
||||
default:
|
||||
fmt.Println("convertzone [-flags] ZONENAME FILENAME")
|
||||
flag.Usage()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// parseargs parses the non-flag arguments.
|
||||
func parseargs(args []string) (zonename string, filename string, r io.Reader, err error) {
|
||||
// 1 args: first arg is the zonename. Read stdin.
|
||||
// 2 args: first arg is the zonename. 2nd is the filename.
|
||||
// Anything else returns an error.
|
||||
|
||||
if len(args) < 2 {
|
||||
return "", "", nil, fmt.Errorf("no command line parameters. Zone name required")
|
||||
}
|
||||
|
||||
zonename = args[0]
|
||||
|
||||
if len(args) == 1 {
|
||||
filename = "stdin"
|
||||
r = bufio.NewReader(os.Stdin)
|
||||
} else if len(args) == 2 {
|
||||
filename = flag.Arg(1)
|
||||
r, err = os.Open(filename)
|
||||
if err != nil {
|
||||
return "", "", nil, fmt.Errorf("could not open file: %s: %w", filename, err)
|
||||
}
|
||||
} else {
|
||||
return "", "", nil, fmt.Errorf("too many command line parameters")
|
||||
}
|
||||
|
||||
return zonename, filename, r, nil
|
||||
}
|
||||
|
||||
func readZone(zonename string, r io.Reader, filename string) []dns.RR {
|
||||
|
||||
zp := dns.NewZoneParser(r, zonename, filename)
|
||||
|
||||
var parsed []dns.RR
|
||||
for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
|
||||
parsed = append(parsed, rr)
|
||||
}
|
||||
if err := zp.Err(); err != nil {
|
||||
log.Fatalf("Error in zonefile: %v", err)
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
func readOctodns(zonename string, r io.Reader, filename string) []dns.RR {
|
||||
var l []dns.RR
|
||||
|
||||
foundRecords, err := octoyaml.ReadYaml(r, zonename)
|
||||
if err != nil {
|
||||
log.Println(fmt.Errorf("can not get corrections: %w", err))
|
||||
}
|
||||
|
||||
for _, x := range foundRecords {
|
||||
l = append(l, x.ToRR())
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// rrFormat outputs the zonefile in either DSL or TSV format.
|
||||
func rrFormat(zonename string, filename string, recs []dns.RR, defaultTTL uint32, dsl bool) {
|
||||
zonenamedot := zonename + "."
|
||||
|
||||
for _, x := range recs {
|
||||
|
||||
// Skip comments. Parse the formatted version.
|
||||
line := x.String()
|
||||
if line[0] == ';' {
|
||||
continue
|
||||
}
|
||||
items := strings.SplitN(line, "\t", 5)
|
||||
if len(items) < 5 {
|
||||
log.Fatalf("Too few items in: %v", line)
|
||||
}
|
||||
|
||||
target := items[4]
|
||||
|
||||
hdr := x.Header()
|
||||
nameFqdn := hdr.Name
|
||||
name := dnsutil.TrimDomainName(nameFqdn, zonenamedot)
|
||||
ttl := strconv.FormatUint(uint64(hdr.Ttl), 10)
|
||||
classStr := dns.ClassToString[hdr.Class]
|
||||
typeStr := dns.TypeToString[hdr.Rrtype]
|
||||
|
||||
// MX records should split out the prio vs. target.
|
||||
if hdr.Rrtype == dns.TypeMX {
|
||||
target = strings.Replace(target, " ", "\t", 1)
|
||||
}
|
||||
|
||||
var ttlop string
|
||||
if hdr.Ttl == defaultTTL {
|
||||
ttlop = ""
|
||||
} else {
|
||||
ttlop = fmt.Sprintf(", TTL(%d)", hdr.Ttl)
|
||||
}
|
||||
|
||||
// NS records at the apex should be NAMESERVER() records.
|
||||
if hdr.Rrtype == dns.TypeNS && name == "@" {
|
||||
fmt.Printf(",\n\tNAMESERVER('%s'%s)", target, ttlop)
|
||||
continue
|
||||
}
|
||||
|
||||
if !dsl { // TSV format:
|
||||
fmt.Printf("%s\t%s\t%s\t%s\t%s\n", name, ttl, classStr, typeStr, target)
|
||||
} else { // DSL format:
|
||||
switch hdr.Rrtype { // #rtype_variations
|
||||
case dns.TypeMX:
|
||||
m := strings.SplitN(target, "\t", 2)
|
||||
target = m[0] + ", '" + m[1] + "'"
|
||||
case dns.TypeSOA:
|
||||
continue
|
||||
case dns.TypeTXT:
|
||||
if len(x.(*dns.TXT).Txt) == 1 {
|
||||
target = `'` + x.(*dns.TXT).Txt[0] + `'`
|
||||
} else {
|
||||
target = `['` + strings.Join(x.(*dns.TXT).Txt, `', '`) + `']`
|
||||
}
|
||||
default:
|
||||
target = "'" + target + "'"
|
||||
}
|
||||
fmt.Printf(",\n\t%s('%s', %s%s)", typeStr, name, target, ttlop)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user