Skip to content

Instantly share code, notes, and snippets.

@Luzifer
Last active February 7, 2018 04:35
Show Gist options
  • Save Luzifer/a261ebc81d364ac67f0fd73f6a9e86c7 to your computer and use it in GitHub Desktop.
Save Luzifer/a261ebc81d364ac67f0fd73f6a9e86c7 to your computer and use it in GitHub Desktop.
Script to fetch resource records from DNSimple and write corresponding Terraform configs for them

DNSimple to Terraform

When migrating from an existing infrastructure to an infrastructure managed by Terraform it's possible to import the present configuration. The only thing the importer does not do: It does not write the configuration for you.

This script is intended to access a DNSimple account through the APIv2 and fetch all resource records for all domains in that account. The records are written into a Terraform configuration file using one file per domain.

Usage

  1. Create an APIv2 token in the DNSimple web interface
  2. Get your account ID for the account you want to export
  3. Let the script create your configuration:
    # export token=<your token>
    # export account=<your account id>
    # python fetch.py
    Fetching records for domain "example.com"...
    ...
  4. Review the configuration written by the script (Manual review, terraform validate, ...)
  5. Remove all resource records you don't want to manage through Terraform
  6. Import all the references from your account (remove the echo after reviewing the script):
    IFS=$'\n'
    for i in $(grep -h 'terraform import' dnsimple* | sed 's/^# //'); do 
      echo eval $i
    done
  7. Execute a terraform plan to ensure everything is in sync

Now you do have a copy of your existing DNSimple infrastructure inside your Terraform folder and you can start to work on it.

import os
import re
import requests
import sys
account = os.environ['account']
token = os.environ['token']
base_url = 'https://api.dnsimple.com/v2/{}'.format(account)
tpl_prio = '''# terraform import dnsimple_record.{slug} {zone_id}_{id}
resource "dnsimple_record" "{slug}" {{
domain = "{zone_id}"
name = "{name}"
type = "{type}"
value = "{content}"
ttl = {ttl}
priority = {priority}
}}
'''
tpl_noprio = '''# terraform import dnsimple_record.{slug} {zone_id}_{id}
resource "dnsimple_record" "{slug}" {{
domain = "{zone_id}"
name = "{name}"
type = "{type}"
value = "{content}"
ttl = {ttl}
}}
'''
def get(path):
global token
return requests.get('/'.join([base_url, path]), headers={
'Authorization': 'Bearer {}'.format(token),
'Accept': 'application/json',
}).json()
def slugify(domain):
return '_'.join(domain.split('.')[::-1]).strip('_').replace('*', 'WILDCARD')
def main(domains):
for domain in [i['name'] for i in get('domains')['data']]:
if len(domains) > 0 and domain not in domains:
continue
sys.stderr.write(
'Fetching records for domain "{}"...\n'.format(domain))
with open('dnsimple_{}.tf'.format(domain.replace('.', '_')), 'w') as tffile:
seen_slugs = []
for record in get('/'.join(['zones', domain, 'records?per_page=100&sort=name:asc,type:asc']))['data']:
if record['system_record']:
continue
tpl = tpl_prio
slug = '{}-{}'.format(
slugify('{name}.{zone_id}'.format(**record)),
record['type'],
)
if slug in seen_slugs:
i = 1
while '{}-{}'.format(slug, i) in seen_slugs:
i += 1
slug = '{}-{}'.format(slug, i)
record['slug'] = re.sub(r"_+", "_", slug)
record['content'] = record['content'].replace('"', '\\"')
if record['priority'] is None:
tpl = tpl_noprio
tffile.write(tpl.format(**record))
seen_slugs.append(slug)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
requests==2.18.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment