]> gitweb.fluxo.info Git - leap/leap_cli.git/commitdiff
added support for environmentally scoped services and tags (e.g. services/webapp...
authorelijah <elijah@riseup.net>
Wed, 21 May 2014 06:37:44 +0000 (23:37 -0700)
committerelijah <elijah@riseup.net>
Wed, 21 May 2014 06:37:44 +0000 (23:37 -0700)
lib/leap_cli/commands/compile.rb
lib/leap_cli/commands/test.rb
lib/leap_cli/config/macros.rb
lib/leap_cli/config/manager.rb
lib/leap_cli/version.rb
test/leap_platform/platform.rb

index 11e6e353efbd6af4b86d4a161e3fed6b12ebb5d8..e96cb6a6054557d4dab7ab347efefc98e0e1317a 100644 (file)
@@ -125,7 +125,7 @@ module LeapCli
       end
 
       # all other records
-      manager.environments.each do |env|
+      manager.environment_names.each do |env|
         next if env == 'local'
         nodes = manager.nodes[:environment => env]
         next unless nodes.any?
index 024ca25a030476c6a6cbb6c1effa5d660a7fe8af..2584a6990122b499ba927c14a32a5ba1d52133fe 100644 (file)
@@ -46,7 +46,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)
-    manager.environments.each do |env|
+    manager.environment_names.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|
index c6938fe71515f7d43a723e02634ec58e60496893..63dce9724c33f7f0ddfc72290e651c9cdbc02bec 100644 (file)
@@ -23,7 +23,7 @@ module LeapCli; module Config
     # grab an environment appropriate provider
     #
     def provider
-      global.providers[@node.environment] || global.provider
+      global.env(@node.environment).provider
     end
 
     #
index 7969d40c229d84676a192363c77be8e6033d1db7..1a66bff236840ce8f11866d696b1e745758b40c4 100644 (file)
@@ -9,16 +9,24 @@ end
 module LeapCli
   module Config
 
+    class Environment
+      attr_accessor :services, :tags, :provider
+    end
+
     #
     # A class to manage all the objects in all the configuration files.
     #
     class Manager
 
+      def initialize
+        @environments = {} # hash of `Environment` objects, keyed by name.
+      end
+
       ##
       ## ATTRIBUTES
       ##
 
-      attr_reader :services, :tags, :nodes, :provider, :providers, :common, :secrets
+      attr_reader :nodes, :common, :secrets
       attr_reader :base_services, :base_tags, :base_provider, :base_common
 
       #
@@ -32,10 +40,24 @@ module LeapCli
       # 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
+      def environment_names
+        @environment_names ||= [nil] + env.tags.collect {|name, tag| tag['environment']}.compact
       end
 
+      #
+      # Returns the appropriate environment variable
+      #
+      def env(env=nil)
+        env ||= 'default'
+        e = @environments[env] ||= Environment.new
+        yield e if block_given?
+        e
+      end
+
+      def services; env('default').services; end
+      def tags; env('default').tags; end
+      def provider; env('default').provider; end
+
       ##
       ## IMPORT EXPORT
       ##
@@ -48,34 +70,43 @@ module LeapCli
 
         # load base
         @base_services = load_all_json(Path.named_path([:service_config, '*'], Path.provider_base), Config::Tag)
-        @base_tags     = load_all_json(Path.named_path([:tag_config, '*'], Path.provider_base), Config::Tag)
-        @base_common   = load_json(Path.named_path(:common_config, Path.provider_base), Config::Object)
-        @base_provider = load_json(Path.named_path(:provider_config, Path.provider_base), Config::Provider)
+        @base_tags     = load_all_json(Path.named_path([:tag_config, '*'],     Path.provider_base), Config::Tag)
+        @base_common   = load_json(    Path.named_path(:common_config,         Path.provider_base), Config::Object)
+        @base_provider = load_json(    Path.named_path(:provider_config,       Path.provider_base), Config::Provider)
 
         # load provider
-        provider_path = Path.named_path(:provider_config, @provider_dir)
-        common_path = Path.named_path(:common_config, @provider_dir)
-        Util::assert_files_exist!(provider_path, common_path)
-        @services = load_all_json(Path.named_path([:service_config, '*'], @provider_dir), Config::Tag)
-        @tags     = load_all_json(Path.named_path([:tag_config, '*'],     @provider_dir), Config::Tag)
-        @nodes    = load_all_json(Path.named_path([:node_config, '*'],    @provider_dir), Config::Node)
-        @common   = load_json(common_path, Config::Object)
-        @provider = load_json(provider_path, Config::Provider)
-        @secrets  = load_json(Path.named_path(:secrets_config,  @provider_dir), Config::Secrets)
-
-        ### BEGIN HACK
-        ### remove this after it is likely that no one has any old-style secrets.json
-        if @secrets['webapp_secret_token']
-          @secrets = Config::Secrets.new
-          Util::log :warning, "Creating all new secrets.json (new version is scoped by environment). Make sure to do a full deploy so that new secrets take effect."
+        @nodes    = load_all_json(Path.named_path([:node_config, '*'],  @provider_dir), Config::Node)
+        @common   = load_json(    Path.named_path(:common_config,       @provider_dir), Config::Object)
+        @secrets  = load_json(    Path.named_path(:secrets_config,      @provider_dir), Config::Secrets)
+        @common.inherit_from! @base_common
+
+        # load provider services, tags, and provider.json, DEFAULT environment
+        log 3, :loading, 'default environment.........'
+        env('default') do |e|
+          e.services = load_all_json(Path.named_path([:service_config, '*'], @provider_dir), Config::Tag, :no_dots => true)
+          e.tags     = load_all_json(Path.named_path([:tag_config, '*'],     @provider_dir), Config::Tag, :no_dots => true)
+          e.provider = load_json(    Path.named_path(:provider_config,       @provider_dir), Config::Provider, :assert => true)
+          e.services.inherit_from! @base_services
+          e.tags.inherit_from!     @base_tags
+          e.provider.inherit_from! @base_provider
+          validate_provider(e.provider)
+        end
+
+        # load provider services, tags, and provider.json, OTHER environments
+        environment_names.each do |ename|
+          next unless ename
+          log 3, :loading, '%s environment.........' % ename
+          env(ename) do |e|
+            e.services = load_all_json(Path.named_path([:service_env_config, '*', ename], @provider_dir), Config::Tag)
+            e.tags     = load_all_json(Path.named_path([:tag_env_config, '*', ename],     @provider_dir), Config::Tag)
+            e.provider = load_json(    Path.named_path([:provider_env_config, ename],     @provider_dir), Config::Provider)
+            e.services.inherit_from! env.services
+            e.tags.inherit_from!     env.tags
+            e.provider.inherit_from! env.provider
+            validate_provider(e.provider)
+          end
         end
-        ### END HACK
 
-        # inherit
-        @services.inherit_from! base_services
-        @tags.inherit_from!     base_tags
-        @common.inherit_from!   base_common
-        @provider.inherit_from! base_provider
         @nodes.each do |name, node|
           Util::assert! name =~ /^[0-9a-z-]+$/, "Illegal character(s) used in node name '#{name}'"
           @nodes[name] = apply_inheritance(node)
@@ -84,19 +115,6 @@ module LeapCli
         unless options[:include_disabled]
           remove_disabled_nodes
         end
-
-        # load optional environment specific providers
-        validate_provider(@provider)
-        @providers = {}
-        environments.each do |env|
-          if Path.defined?(:provider_env_config)
-            provider_path = Path.named_path([:provider_env_config, env], @provider_dir)
-            providers[env] = load_json(provider_path, Config::Provider)
-            providers[env].inherit_from! @provider
-            validate_provider(providers[env])
-          end
-        end
-
       end
 
       #
@@ -232,12 +250,13 @@ module LeapCli
 
       private
 
-      def load_all_json(pattern, object_class)
+      def load_all_json(pattern, object_class, options={})
         results = Config::ObjectList.new
         Dir.glob(pattern).each do |filename|
+          next if options[:no_dots] && File.basename(filename) !~ /^[^\.]*\.json$/
           obj = load_json(filename, object_class)
           if obj
-            name = File.basename(filename).force_encoding('utf-8').sub(/\.json$/,'')
+            name = File.basename(filename).force_encoding('utf-8').sub(/^([^\.]+).*\.json$/,'\1')
             obj['name'] ||= name
             results[name] = obj
           end
@@ -245,7 +264,10 @@ module LeapCli
         results
       end
 
-      def load_json(filename, object_class)
+      def load_json(filename, object_class, options={})
+        if options[:assert]
+          Util::assert_files_exist!(filename)
+        end
         if !File.exists?(filename)
           return object_class.new(self)
         end
@@ -311,20 +333,32 @@ module LeapCli
         new_node = Config::Node.new(self)
         name = node.name
 
+        # Guess the environment of the node from the tag names.
+        # (Technically, this is wrong: a tag that sets the environment might not be
+        #  named the same as the environment. This code assumes that it is).
+        node_env = self.env
+        if node['tags']
+          node['tags'].to_a.each do |tag|
+            if self.environment_names.include?(tag)
+              node_env = self.env(tag)
+            end
+          end
+        end
+
         # inherit from common
         new_node.deep_merge!(@common)
 
         # inherit from services
         if node['services']
           node['services'].to_a.each do |node_service|
-            service = @services[node_service]
+            service = node_env.services[node_service]
             if service.nil?
               msg = 'in node "%s": the service "%s" does not exist.' % [node['name'], node_service]
               log 0, :error, msg
               raise LeapCli::ConfigError.new(node, "error " + msg) if throw_exceptions
             else
               new_node.deep_merge!(service)
-              service.node_list.add(name, new_node)
+              self.services[node_service].node_list.add(name, new_node)
             end
           end
         end
@@ -335,14 +369,14 @@ module LeapCli
         end
         if node['tags']
           node['tags'].to_a.each do |node_tag|
-            tag = @tags[node_tag]
+            tag = node_env.tags[node_tag]
             if tag.nil?
               msg = 'in node "%s": the tag "%s" does not exist.' % [node['name'], node_tag]
               log 0, :error, msg
               raise LeapCli::ConfigError.new(node, "error " + msg) if throw_exceptions
             else
               new_node.deep_merge!(tag)
-              tag.node_list.add(name, new_node)
+              self.tags[node_tag].node_list.add(name, new_node)
             end
           end
         end
@@ -365,12 +399,12 @@ module LeapCli
             @disabled_nodes[name] = node
             if node['services']
               node['services'].to_a.each do |node_service|
-                @services[node_service].node_list.delete(node.name)
+                self.services[node_service].node_list.delete(node.name)
               end
             end
             if node['tags']
               node['tags'].to_a.each do |node_tag|
-                @tags[node_tag].node_list.delete(node.name)
+                self.tags[node_tag].node_list.delete(node.name)
               end
             end
           end
index 9f8e3811ae2201cd6238a3a01407f08023992f64..7c39e05ddb5a7507c3b56a10f6a46bf71f19ec17 100644 (file)
@@ -1,7 +1,7 @@
 module LeapCli
   unless defined?(LeapCli::VERSION)
-    VERSION = '1.5.3'
-    COMPATIBLE_PLATFORM_VERSION = '0.3.0'..'1.99'
+    VERSION = '1.5.4'
+    COMPATIBLE_PLATFORM_VERSION = '0.5.2'..'1.99'
     SUMMARY = 'Command line interface to the LEAP platform'
     DESCRIPTION = 'The command "leap" can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.'
     LOAD_PATHS = ['lib', 'vendor/certificate_authority/lib', 'vendor/rsync_command/lib']
index 9f63b4cab06c977869c4886269df949247116311..52bb8df9da02d6639c6f1dc8d7c63d48c1a888f3 100644 (file)
@@ -1,15 +1,16 @@
+# encoding: utf-8
 #
 # These are variables defined by this leap_platform and used by leap_cli.
 #
 
 Leap::Platform.define do
-  self.version = "1.1.2"
-  self.compatible_cli = "1.1.2".."1.99"
+  self.version = "0.5.2"
+  self.compatible_cli = "1.5.4".."1.99"
 
   #
   # the facter facts that should be gathered
   #
-  self.facts = ["ec2_local_ipv4"]
+  self.facts = ["ec2_local_ipv4", "ec2_public_ipv4"]
 
   #
   # the named paths for this platform
@@ -31,6 +32,11 @@ Leap::Platform.define do
     :service_config   => 'services/#{arg}.json',
     :tag_config       => 'tags/#{arg}.json',
 
+    # input config files, environmentally scoped
+    :provider_env_config  => 'provider.#{arg}.json',
+    :service_env_config   => 'services/#{arg}.#{arg}.json',
+    :tag_env_config       => 'tags/#{arg}.#{arg}.json',
+
     # input templates
     :provider_json_template        => 'files/service-definitions/provider.json.erb',
     :eip_service_json_template     => 'files/service-definitions/#{arg}/eip-service.json.erb',
@@ -43,6 +49,8 @@ Leap::Platform.define do
     :user_pgp         => 'users/#{arg}/#{arg}_pgp.pub',
     :known_hosts      => 'files/ssh/known_hosts',
     :authorized_keys  => 'files/ssh/authorized_keys',
+    :monitor_pub_key  => 'files/ssh/monitor_ssh.pub',
+    :monitor_priv_key => 'files/ssh/monitor_ssh',
     :ca_key           => 'files/ca/ca.key',
     :ca_cert          => 'files/ca/ca.crt',
     :client_ca_key    => 'files/ca/client_ca.key',
@@ -73,5 +81,9 @@ Leap::Platform.define do
   self.node_files = [
     :node_config, :hiera, :node_x509_cert, :node_x509_key, :node_ssh_pub_key
   ]
+
+  self.monitor_username = 'monitor'
+
+  self.reserved_usernames = ['monitor']
 end