Report abuse

#!/usr/ruby
#
# loosely based on (Tangerine ALPHA ) by Isam M (r0cketjump YAHOO COM)  [his code was useful :-)]
#
# ZoneParser was created by Ben Congleton from Hab.la (http://www.hab.la) and Nethernet Consulting (http://www.nethernet.com)
#
#
# I recommend using Zone Parser to import your zones from your normal DNS server,
# and then Isam's Tangerine to deal with them once their in slicehost.


require 'rubygems'
require 'activeresource'

API_PASSWORD = 'API_KEY_HERE' 
API_ADDRESS = "https://#{API_PASSWORD}@api.slicehost.com/" 
NAMESERVERS = ["ns1.slicehost.com", "ns2.slicehost.com", "ns3.slicehost.com"]
VERBOSE = true
DEBUG   = false

class Zone < ActiveResource::Base
    self.site = API_ADDRESS
end

class Record < ActiveResource::Base
    self.site = API_ADDRESS
end



class ZoneParser
  attr_accessor :records
  attr_accessor :domain
  def initialize(filename, domain)
    @records = Array.new
    @domain  = domain

    File.open(filename, 'r').each_line do |line|
      next if (line =~ /SOA/)
      next if (line =~ /^\s*\;/)
      parts = line.split(/\s\s*/)
      next if (parts.size == 0)
      next if ( (parts.first == "" or parts.first == "@") && !parts[1].match(/^\D\D*$/) )
      next if (parts[1] == "NS") # no need for NS records
      p line if (DEBUG)

      if(parts.first == "" or parts.first == "@" )
        parts[0] = domain + "."
      end

      if(parts[1] == "IN")
        parts = [parts[0], parts[2], parts[3], parts[4..parts.size].join(" ")]
      end

      ap = {
        :record_type => parts[1], 
        :name => parts[0], 
        :data => parts.last, 
        :ttl => 8000, 
        :active => 'Y', 
        :aux => 0
      }
      if(parts.size == 4)
        ap[:aux] = parts[2]
      end
      p ap if(DEBUG)

      #p parts
      #p ap
      #p line
      @records << ap
    end
  end

  def sync(clear = true)
    # syncronizes the web-based zone from the file-based zone.
    z = Zone.find(:first, :params => {'origin' => @domain + "."})
    p z if(DEBUG)

    if( not z):
      z = Zone.new({ 
          :origin => @domain, 
          :ttl => 8000, 
          :active => 'Y' 
      })
      z.save unless z.nil? 
    end

    if(not z)
      raise Exception.new("Error finding/creating zone for #{@domain}")
    elsif(VERBOSE)
      print "Syncing Zone: #{@domain}\n"
    end

    p z if(DEBUG)

    # ok at this point we have a zone.
    # wipe it
    if(clear)
      print "\nRemoving all records for zone: #{@domain}\n" if(VERBOSE)
      Record.find(:all, :params => {:zone_id => z.id}).each do |r|
        r.destroy unless r.nil? 
        p r if (DEBUG)
        print "\t- #{r.name} #{r.record_type} #{r.data}\n" if(VERBOSE)
      end
    end
    print "\nAdding records to zone: #{@domain}\n" if(VERBOSE)

    # add the Nameservers:
    base = {
      :record_type => "NS", 
      :name => @domain + ".", 
      :ttl => 8000, 
      :active => 'Y', 
      :aux => 0
    }
    NAMESERVERS.each do |ns|
      base[:data] = ns  
      @records << base.dup
    end

    # add the zones
    @records.each do |r|
      r[:zone_id] = z.id
      rec = Record.new(r)
      rec.save unless rec.nil?

      if(not rec or rec.errors.size > 0)
        print "\t* ERROR ADDING #{r[:name]} #{r[:record_type]} #{r[:data]}\n"
        p rec
      elsif(rec && VERBOSE)
        p rec if(DEBUG)
        print "\t+ #{r[:name]} #{r[:record_type]} #{r[:data]}\n" 
      end     



    end

  end

end #end class



z = ZoneParser.new("test_zone.txt", "hab.la")

z.sync



=begin
;
;This is an example test zone
;
@        IN SOA    ns1.netherweb.com. ben.nethernet.com. (
                2008102701
              3600   ; refresh [1h]
              3600   ; retry   [1h]
              6H   ; expire  [2h]
             3H)  ; minimum [1d]

                NS      ns1.netherweb.com.
                NS      ns2.netherweb.com.

@               A       216.9.83.199
                MX      1 ASPMX.L.GOOGLE.COM.
                MX      5 ALT1.ASPMX.L.GOOGLE.COM.
                MX      5 ALT2.ASPMX.L.GOOGLE.COM.
                MX      10 ASPMX2.GOOGLEMAIL.COM.
                MX      10 ASPMX3.GOOGLEMAIL.COM.
                MX      10 ASPMX4.GOOGLEMAIL.COM.
                MX      10 ASPMX5.GOOGLEMAIL.COM.                                                              
www             A       216.9.83.199
*.async         A       216.9.83.197
*.aync          A       216.9.83.197

_jabber._tcp.staging       IN SRV   0 0 18269   staging.hab.la.
_xmpp-server._tcp.staging  IN SRV   0 0 18269   staging.hab.la.
_xmpp-client._tcp.staging  IN SRV   0 0 18222   staging.hab.la.


=end