From e0763033e497fdb7956aa62534b5f8bee0f83a12 Mon Sep 17 00:00:00 2001
From: elijah <elijah@riseup.net>
Date: Wed, 26 Jun 2013 21:39:23 -0700
Subject: added command `leap compile zone`

---
 lib/leap_cli/commands/compile.rb | 93 ++++++++++++++++++++++++++++++++++++++--
 lib/leap_cli/commands/test.rb    |  3 +-
 lib/leap_cli/config/manager.rb   | 11 +++++
 3 files changed, 102 insertions(+), 5 deletions(-)

(limited to 'lib/leap_cli')

diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb
index 3cdd5dd..0fc95ca 100644
--- a/lib/leap_cli/commands/compile.rb
+++ b/lib/leap_cli/commands/compile.rb
@@ -2,13 +2,27 @@
 module LeapCli
   module Commands
 
-    desc 'Compiles node configuration files into hiera files used for deployment.'
+    desc "Compile generated files."
     command :compile do |c|
-      c.action do |global_options,options,args|
-        compile_hiera_files
+      c.desc 'Compiles node configuration files into hiera files used for deployment.'
+      c.command :all do |all|
+        all.action do |global_options,options,args|
+          compile_hiera_files
+        end
       end
+
+      c.desc "Compile a DNS zone file for your provider."
+      c.command :zone do |zone|
+        zone.action do |global_options, options, args|
+          compile_zone_file
+        end
+      end
+
+      c.default_command :all
     end
 
+    protected
+
     def compile_hiera_files(nodes=nil)
       # these must come first
       update_compiled_ssh_configs
@@ -23,5 +37,78 @@ module LeapCli
       update_known_hosts
     end
 
+    ##
+    ## ZONE FILE
+    ##
+
+    def relative_hostname(fqdn)
+      @domain_regexp ||= /\.?#{Regexp.escape(provider.domain)}$/
+      fqdn.sub(@domain_regexp, '')
+    end
+
+    #
+    # serial is any number less than 2^32 (4294967296)
+    #
+    def compile_zone_file
+      f = $stdout
+
+      f.puts ZONE_HEADER % [provider.domain, provider.domain, provider.domain]
+
+      max_width = manager.nodes.values.inject(0) {|max, node| [max, relative_hostname(node.domain.full).length].max }
+      put_line = lambda {|host, line| f.puts("%-#{max_width}s %s" % [host, line])}
+
+      if provider['dns'] && provider.dns['nameservers']
+        provider.dns.nameservers.each do |ns|
+          put_line.call "", "IN NS #{ns}."
+        end
+      end
+
+      manager.environments.each do |env|
+        next if env == 'local'
+        nodes = manager.nodes[:environment => env]
+        next unless nodes.any?
+        f.puts ENV_HEADER % (env.nil? ? 'default' : env)
+        nodes.each_node do |node|
+          if node.dns.public
+            hostname = relative_hostname(node.domain.full)
+            put_line.call relative_hostname(node.domain.full), "IN A      #{node.ip_address}"
+          end
+          if node['dns']['aliases']
+            node['dns']['aliases'].each do |host_alias|
+              if host_alias != node.domain.full
+                put_line.call relative_hostname(host_alias), "IN CNAME  #{relative_hostname(node.domain.full)}"
+              end
+            end
+          end
+          if node.services.include? 'mx'
+            put_line.call relative_hostname(node.domain.full_suffix), "IN MX 10  #{relative_hostname(node.domain.full)}"
+          end
+        end
+      end
+    end
+
+    ENV_HEADER = %[
+;;
+;; ENVIRONMENT %s
+;;
+
+]
+
+    ZONE_HEADER = %[
+;;
+;; BIND data file for %s
+;;
+
+$TTL 600
+
+@ IN SOA %s. %s. (
+  0000          ; serial
+  7200          ; refresh (  24 hours)
+  3600          ; retry   (   2 hours)
+  1209600       ; expire  (1000 hours)
+  600 )         ; minimum (   2 days)
+;
+]
+
   end
 end
\ No newline at end of file
diff --git a/lib/leap_cli/commands/test.rb b/lib/leap_cli/commands/test.rb
index 8fe6e11..c240a70 100644
--- a/lib/leap_cli/commands/test.rb
+++ b/lib/leap_cli/commands/test.rb
@@ -28,8 +28,7 @@ module LeapCli; module Commands
     assert_config! 'provider.ca.client_certificates.unlimited_prefix'
     assert_config! 'provider.ca.client_certificates.limited_prefix'
     template = read_file! Path.find_file(:test_client_openvpn_template)
-    environments = [nil] + manager.tags.collect {|name, tag| tag['environment']}.compact
-    environments.each do |env|
+    manager.environments.each do |env|
       vpn_nodes = manager.nodes[:environment => env][:services => 'openvpn']['openvpn.allow_limited' => true]
       if vpn_nodes.any?
         generate_test_client_cert(provider.ca.client_certificates.limited_prefix) do |key, cert|
diff --git a/lib/leap_cli/config/manager.rb b/lib/leap_cli/config/manager.rb
index 05df22f..f34566c 100644
--- a/lib/leap_cli/config/manager.rb
+++ b/lib/leap_cli/config/manager.rb
@@ -19,10 +19,21 @@ module LeapCli
       attr_reader :services, :tags, :nodes, :provider, :common, :secrets
       attr_reader :base_services, :base_tags, :base_provider, :base_common
 
+      #
+      # returns the Hash of the contents of facts.json
+      #
       def facts
         @facts ||= JSON.parse(Util.read_file(:facts) || "{}")
       end
 
+      #
+      # returns an Array of all the environments defined for this provider.
+      # the returned array includes nil (for the default environment)
+      #
+      def environments
+        @environments ||= [nil] + self.tags.collect {|name, tag| tag['environment']}.compact
+      end
+
       ##
       ## IMPORT EXPORT
       ##
-- 
cgit v1.2.3