aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2014-05-20 23:37:44 -0700
committerelijah <elijah@riseup.net>2014-05-20 23:37:44 -0700
commit7f89d03d68f96e692da2653db30f8aae2ac1729b (patch)
treee94c3a76bdee6f4f1fc84c86a837321c868ccd58
parent16a202b173ca6389e66e523b8e88d417d01d3db8 (diff)
downloadleap_cli-7f89d03d68f96e692da2653db30f8aae2ac1729b.tar.gz
leap_cli-7f89d03d68f96e692da2653db30f8aae2ac1729b.tar.bz2
added support for environmentally scoped services and tags (e.g. services/webapp.production.json). requires latest platform.
-rw-r--r--lib/leap_cli/commands/compile.rb2
-rw-r--r--lib/leap_cli/commands/test.rb2
-rw-r--r--lib/leap_cli/config/macros.rb2
-rw-r--r--lib/leap_cli/config/manager.rb132
-rw-r--r--lib/leap_cli/version.rb4
-rw-r--r--test/leap_platform/platform.rb18
6 files changed, 103 insertions, 57 deletions
diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb
index 11e6e35..e96cb6a 100644
--- a/lib/leap_cli/commands/compile.rb
+++ b/lib/leap_cli/commands/compile.rb
@@ -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?
diff --git a/lib/leap_cli/commands/test.rb b/lib/leap_cli/commands/test.rb
index 024ca25..2584a69 100644
--- a/lib/leap_cli/commands/test.rb
+++ b/lib/leap_cli/commands/test.rb
@@ -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|
diff --git a/lib/leap_cli/config/macros.rb b/lib/leap_cli/config/macros.rb
index c6938fe..63dce97 100644
--- a/lib/leap_cli/config/macros.rb
+++ b/lib/leap_cli/config/macros.rb
@@ -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
#
diff --git a/lib/leap_cli/config/manager.rb b/lib/leap_cli/config/manager.rb
index 7969d40..1a66bff 100644
--- a/lib/leap_cli/config/manager.rb
+++ b/lib/leap_cli/config/manager.rb
@@ -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
diff --git a/lib/leap_cli/version.rb b/lib/leap_cli/version.rb
index 9f8e381..7c39e05 100644
--- a/lib/leap_cli/version.rb
+++ b/lib/leap_cli/version.rb
@@ -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']
diff --git a/test/leap_platform/platform.rb b/test/leap_platform/platform.rb
index 9f63b4c..52bb8df 100644
--- a/test/leap_platform/platform.rb
+++ b/test/leap_platform/platform.rb
@@ -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