1
0
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:
Chris Hunt
2022-08-11 13:09:23 -04:00
4 changed files with 38 additions and 326 deletions

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -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)
}
}
}