aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/leap11
-rw-r--r--lib/core_ext/boolean.rb14
-rw-r--r--lib/core_ext/hash.rb74
-rw-r--r--lib/core_ext/nil.rb5
-rw-r--r--lib/leap_cli.rb17
-rw-r--r--lib/leap_cli/commands/compile.rb1
-rw-r--r--lib/leap_cli/commands/deploy.rb2
-rw-r--r--lib/leap_cli/commands/list.rb8
-rw-r--r--lib/leap_cli/config.rb119
-rw-r--r--lib/leap_cli/config/base.rb149
-rw-r--r--lib/leap_cli/config/list.rb81
-rw-r--r--lib/leap_cli/config/manager.rb219
-rw-r--r--lib/leap_cli/config/node.rb19
-rw-r--r--lib/leap_cli/config/tag.rb19
-rw-r--r--lib/leap_cli/config_list.rb77
-rw-r--r--lib/leap_cli/config_manager.rb200
-rw-r--r--test/provider/common.json4
-rw-r--r--test/provider/files/public-definitions/provider.json.erb1
-rw-r--r--test/provider/hiera/couch1.yaml (renamed from test/provider/hiera/couch1.rewire.yaml)5
-rw-r--r--test/provider/hiera/couch2.yaml (renamed from test/provider/hiera/couch2.rewire.yaml)5
-rw-r--r--test/provider/hiera/ns1.rewire.yaml25
-rw-r--r--test/provider/hiera/ns1.yaml26
-rw-r--r--test/provider/hiera/ns2.rewire.yaml25
-rw-r--r--test/provider/hiera/ns2.yaml26
-rw-r--r--test/provider/hiera/vpn1.rewire.yaml158
-rw-r--r--test/provider/hiera/vpn1.yaml160
-rw-r--r--test/provider/hiera/web1.rewire.yaml16
-rw-r--r--test/provider/hiera/web1.yaml19
-rw-r--r--test/provider/nodes/vpn1.json3
-rw-r--r--test/provider/services/webapp.json5
30 files changed, 855 insertions, 638 deletions
diff --git a/bin/leap b/bin/leap
index 4155b58..af37986 100755
--- a/bin/leap
+++ b/bin/leap
@@ -50,6 +50,17 @@ module LeapCli::Commands
def_delegator :@terminal, :say, 'self.say'
#
+ # make config manager available as 'manager'
+ #
+ def self.manager
+ @manager ||= begin
+ manager = LeapCli::Config::Manager.new
+ manager.load(LeapCli::Path.provider)
+ manager
+ end
+ end
+
+ #
# info about leap command line suite
#
program_desc 'LEAP platform command line interface'
diff --git a/lib/core_ext/boolean.rb b/lib/core_ext/boolean.rb
new file mode 100644
index 0000000..9b617b2
--- /dev/null
+++ b/lib/core_ext/boolean.rb
@@ -0,0 +1,14 @@
+#
+# make is_a?(Boolean) possible.
+#
+
+module Boolean
+end
+
+class TrueClass
+ include Boolean
+end
+
+class FalseClass
+ include Boolean
+end \ No newline at end of file
diff --git a/lib/core_ext/hash.rb b/lib/core_ext/hash.rb
new file mode 100644
index 0000000..a9e5c9e
--- /dev/null
+++ b/lib/core_ext/hash.rb
@@ -0,0 +1,74 @@
+#
+#
+# We modify Hash to add a few features we need:
+#
+# * sorted output of keys to in yaml.
+# * reference values either with hsh[key] or hsh.key
+# * deep merge
+# * select fields
+#
+# Because the json parsing code we use doesn't support setting a custom class, it is easier for us to just modify Hash.
+#
+
+require 'yaml'
+
+class Hash
+
+ ##
+ ## YAML
+ ##
+
+ #
+ # make the type appear to be a normal Hash in yaml, even for subclasses.
+ #
+ def to_yaml_type
+ "!map"
+ end
+
+ #
+ # just like Hash#to_yaml, but sorted
+ #
+ def to_yaml(opts = {})
+ YAML::quick_emit(self, opts) do |out|
+ out.map(taguri, to_yaml_style) do |map|
+ keys.sort.each do |k|
+ v = self[k]
+ map.add(k, v)
+ end
+ end
+ end
+ end
+
+ ##
+ ## CONVERTING
+ ##
+
+ #
+ # convert self into a plain hash, but only include the specified keys
+ #
+ def pick(*keys)
+ keys.map(&:to_s).inject({}) do |hsh, key|
+ if has_key?(key)
+ hsh[key] = self[key]
+ end
+ hsh
+ end
+ end
+
+ #
+ # recursive merging (aka deep merge)
+ # taken from ActiveSupport::CoreExtensions::Hash::DeepMerge
+ #
+ # def deep_merge(other_hash)
+ # self.merge(other_hash) do |key, oldval, newval|
+ # oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
+ # newval = newval.to_hash if newval.respond_to?(:to_hash)
+ # oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
+ # end
+ # end
+
+ # def deep_merge!(other_hash)
+ # replace(deep_merge(other_hash))
+ # end
+
+end
diff --git a/lib/core_ext/nil.rb b/lib/core_ext/nil.rb
new file mode 100644
index 0000000..05ca98f
--- /dev/null
+++ b/lib/core_ext/nil.rb
@@ -0,0 +1,5 @@
+class NilClass
+ def any?
+ false
+ end
+end \ No newline at end of file
diff --git a/lib/leap_cli.rb b/lib/leap_cli.rb
index b935e35..6fb91a2 100644
--- a/lib/leap_cli.rb
+++ b/lib/leap_cli.rb
@@ -5,15 +5,24 @@ unless defined?(LeapCli::VERSION)
require 'leap_cli/version.rb'
end
+require 'core_ext/hash'
+require 'core_ext/boolean'
+require 'core_ext/nil'
+
require 'leap_cli/init'
require 'leap_cli/path'
require 'leap_cli/log'
-require 'leap_cli/config'
-require 'leap_cli/config_list'
-require 'leap_cli/config_manager'
+require 'leap_cli/config/base'
+require 'leap_cli/config/node'
+require 'leap_cli/config/tag'
+require 'leap_cli/config/manager'
+require 'leap_cli/config/list'
+#
+# make 1.8 act like ruby 1.9
+#
unless String.method_defined?(:to_a)
class String
def to_a; [self]; end
end
-end \ No newline at end of file
+end
diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb
index 6b38de5..8764e52 100644
--- a/lib/leap_cli/commands/compile.rb
+++ b/lib/leap_cli/commands/compile.rb
@@ -4,7 +4,6 @@ module LeapCli
desc 'Compile json files to hiera configs'
command :compile do |c|
c.action do |global_options,options,args|
- manager = ConfigManager.new
manager.load(Path.provider)
Path.ensure_dir(Path.hiera)
manager.export(Path.hiera)
diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb
index 3694a38..9ec984c 100644
--- a/lib/leap_cli/commands/deploy.rb
+++ b/lib/leap_cli/commands/deploy.rb
@@ -6,7 +6,7 @@ module LeapCli
arg_name '<node filter>'
command :deploy do |c|
c.action do |global_options,options,args|
- nodes = ConfigManager.filter(args)
+ nodes = manager.filter(args)
say "Deploying to these nodes: #{nodes.keys.join(', ')}"
if agree "Continue? "
say "deploy not yet implemented"
diff --git a/lib/leap_cli/commands/list.rb b/lib/leap_cli/commands/list.rb
index a186049..166ed2a 100644
--- a/lib/leap_cli/commands/list.rb
+++ b/lib/leap_cli/commands/list.rb
@@ -48,11 +48,11 @@ module LeapCli
command :list do |c|
c.action do |global_options,options,args|
if args.any?
- print_config_table(:nodes, ConfigManager.filter(args))
+ print_config_table(:nodes, manager.filter(args))
else
- print_config_table(:services, ConfigManager.services)
- print_config_table(:tags, ConfigManager.tags)
- print_config_table(:nodes, ConfigManager.nodes)
+ print_config_table(:services, manager.services)
+ print_config_table(:tags, manager.tags)
+ print_config_table(:nodes, manager.nodes)
end
end
end
diff --git a/lib/leap_cli/config.rb b/lib/leap_cli/config.rb
deleted file mode 100644
index 44e66be..0000000
--- a/lib/leap_cli/config.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-module LeapCli
- #
- # This class represents the configuration for a single node, service, or tag.
- #
- class Config < Hash
-
- def initialize(config_type, manager)
- @manager = manager
- @type = config_type
- end
-
- #
- # lazily eval dynamic values when we encounter them.
- #
- def [](key)
- value = fetch(key, nil)
- if value.is_a? Array
- value
- elsif value.nil?
- nil
- else
- if value =~ /^= (.*)$/
- value = eval($1)
- self[key] = value
- end
- value
- end
- end
-
- #
- # make the type appear to be a normal Hash in yaml.
- #
- def to_yaml_type
- "!map"
- end
-
- #
- # just like Hash#to_yaml, but sorted
- #
- def to_yaml(opts = {})
- YAML::quick_emit(self, opts) do |out|
- out.map(taguri, to_yaml_style) do |map|
- keys.sort.each do |k|
- v = self.fetch(k)
- map.add(k, v)
- end
- end
- end
- end
-
- #
- # make obj['name'] available as obj.name
- #
- def method_missing(method, *args, &block)
- if has_key?(method.to_s)
- self[method.to_s]
- else
- super
- end
- end
-
- #
- # convert self into a plain hash, but only include the specified keys
- #
- def to_h(*keys)
- keys.map(&:to_s).inject({}) do |hsh, key|
- if has_key?(key)
- hsh[key] = self[key]
- end
- hsh
- end
- end
-
- def nodes
- if @type == :node
- @manager.nodes
- else
- @nodes ||= ConfigList.new
- end
- end
-
- def services
- if @type == :node
- self['services'] || []
- else
- @manager.services
- end
- end
-
- def tags
- if @type == :node
- self['tags'] || []
- else
- @manager.tags
- end
- end
-
- private
-
- ##
- ## MACROS
- ## these are methods used when eval'ing a value in the .json configuration
- ##
-
- #
- # inserts the contents of a file
- #
- def file(filename)
- filepath = Path.find_file(name, filename)
- if filepath
- File.read(filepath)
- else
- log0('no such file, "%s"' % filename)
- ""
- end
- end
-
- end # class
-end # module \ No newline at end of file
diff --git a/lib/leap_cli/config/base.rb b/lib/leap_cli/config/base.rb
new file mode 100644
index 0000000..c7f4bc9
--- /dev/null
+++ b/lib/leap_cli/config/base.rb
@@ -0,0 +1,149 @@
+module LeapCli
+ module Config
+ #
+ # This class represents the configuration for a single node, service, or tag.
+ #
+ class Base < Hash
+
+ def initialize(manager=nil, node=nil)
+ @manager = manager
+ @node = node || self
+ end
+
+ ##
+ ## FETCHING VALUES
+ ##
+
+ #
+ # lazily eval dynamic values when we encounter them.
+ #
+ def [](key)
+ value = fetch(key, nil)
+ if value.is_a? Array
+ value
+ elsif value.nil?
+ nil
+ else
+ if value =~ /^= (.*)$/
+ begin
+ value = eval($1)
+ self[key] = value
+ rescue Exception => exc
+ puts "Eval error in '#{name}'"
+ puts " string: #{$1}"
+ puts " error: #{exc}"
+ end
+ end
+ value
+ end
+ end
+
+ def name
+ @node['name']
+ end
+
+ #
+ # make hash addressable like an object (e.g. obj['name'] available as obj.name)
+ #
+ def method_missing(method, *args, &block)
+ method = method.to_s
+ if self.has_key?(method)
+ self[method]
+ elsif @node != self
+ @node.send(method) # send call up the tree...
+ else
+ raise NoMethodError.new(method)
+ end
+ end
+
+ #
+ # a deep (recursive) merge with another hash or node.
+ #
+ def deep_merge!(hsh)
+ hsh.each do |key,new_value|
+ old_value = self[key]
+ if old_value.is_a?(Hash) || new_value.is_a?(Hash)
+ # merge hashes
+ value = Base.new(@manager, @node)
+ old_value.is_a?(Hash) ? value.deep_merge!(old_value) : (value[key] = old_value if old_value.any?)
+ new_value.is_a?(Hash) ? value.deep_merge!(new_value) : (value[key] = new_value if new_value.any?)
+ elsif old_value.is_a?(Array) || new_value.is_a?(Array)
+ # merge arrays
+ value = []
+ old_value.is_a?(Array) ? value += old_value : value << old_value
+ new_value.is_a?(Array) ? value += new_value : value << new_value
+ value.compact!
+ elsif new_value.nil?
+ value = old_value
+ elsif old_value.nil?
+ value = new_value
+ elsif old_value.is_a?(Boolean) && new_value.is_a?(Boolean)
+ value = new_value
+ elsif old_value.class != new_value.class
+ raise 'Type mismatch. Cannot merge %s with %s. Key value is %s, name is %s.' % [old_value.class, new_value.class, key, name]
+ else
+ value = new_value
+ end
+ self[key] = value
+ end
+ self
+ end
+
+ #def deep_merge!(new_node)
+ # new_node.each do |key, value|
+ # if value.is_a? self.class
+ # value = Base.new(@manager, @node).deep_merge!(value)
+ # self[key] = new_node[key]
+ # end
+ # self
+ #end
+
+ #
+ # like a normal deep_merge, but replace any hash it encounters with a Config::Base
+ #
+ #def deep_merge(other_hash)
+ # p [self['name'], other_hash['name']]
+ # self.merge(other_hash) do |key, oldval, newval|
+ # oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
+ # newval = newval.to_hash if newval.respond_to?(:to_hash)
+ # p key
+ # p oldval.class
+ # p newval.class
+ # if oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash'
+ # oldval.deep_merge(newval)
+ # elsif newval.class.to_s == 'Hash'
+ # p key
+ # Base.new(@manager, node).replace(newval)
+ # else
+ # newval
+ # end
+ # end
+ #end
+ #
+ #def deep_merge!(other_hash)
+ # replace(deep_merge(other_hash))
+ #end
+
+ private
+
+ ##
+ ## MACROS
+ ## these are methods used when eval'ing a value in the .json configuration
+ ##
+
+ #
+ # inserts the contents of a file
+ #
+ def file(filename)
+ filepath = Path.find_file(name, filename)
+ if filepath
+ File.read(filepath)
+ else
+ log0('no such file, "%s"' % filename)
+ ""
+ end
+ end
+
+ end # class
+ end # module
+end # module \ No newline at end of file
diff --git a/lib/leap_cli/config/list.rb b/lib/leap_cli/config/list.rb
new file mode 100644
index 0000000..28ef499
--- /dev/null
+++ b/lib/leap_cli/config/list.rb
@@ -0,0 +1,81 @@
+module LeapCli
+ module Config
+ class List < Hash
+
+ def initialize(config=nil)
+ if config
+ self << config
+ end
+ end
+
+ #
+ # if the key is a hash, we treat it as a condition and filter all the configs using the condition
+ #
+ # for example:
+ #
+ # nodes[:public_dns => true]
+ #
+ # will return a ConfigList with node configs that have public_dns set to true
+ #
+ def [](key)
+ if key.is_a? Hash
+ results = List.new
+ field, match_value = key.to_a.first
+ field = field.is_a?(Symbol) ? field.to_s : field
+ match_value = match_value.is_a?(Symbol) ? match_value.to_s : match_value
+ each do |name, config|
+ value = config[field]
+ if !value.nil?
+ if value.is_a? Array
+ if value.includes?(match_value)
+ results[name] = config
+ end
+ else
+ if value == match_value
+ results[name] = config
+ end
+ end
+ end
+ end
+ results
+ else
+ super
+ end
+ end
+
+ def <<(config)
+ if config.is_a? Config::List
+ self.deep_merge!(config)
+ elsif config['name']
+ self[config['name']] = config
+ else
+ raise ArgumentError.new('argument must be a Config::Base or a Config::List')
+ end
+ end
+
+ #
+ # converts the hash of configs into an array of hashes, with ONLY the specified fields
+ #
+ def fields(*fields)
+ result = []
+ keys.sort.each do |name|
+ result << self[name].pick(*fields)
+ end
+ result
+ end
+
+ #
+ # like fields(), but returns an array of values instead of an array of hashes.
+ #
+ def field(field)
+ field = field.to_s
+ result = []
+ keys.sort.each do |name|
+ result << self[name][field]
+ end
+ result
+ end
+
+ end
+ end
+end
diff --git a/lib/leap_cli/config/manager.rb b/lib/leap_cli/config/manager.rb
new file mode 100644
index 0000000..b1ea68c
--- /dev/null
+++ b/lib/leap_cli/config/manager.rb
@@ -0,0 +1,219 @@
+require 'oj'
+require 'yaml'
+
+module LeapCli
+ module Config
+ class Manager
+
+ attr_reader :services, :tags, :nodes
+
+ ##
+ ## IMPORT EXPORT
+ ##
+
+ #
+ # load .json configuration files
+ #
+ def load(dir)
+ @services = load_all_json("#{dir}/services/*.json", :tag)
+ @tags = load_all_json("#{dir}/tags/*.json", :tag)
+ @common = load_all_json("#{dir}/common.json", :tag)['common']
+ @nodes = load_all_json("#{dir}/nodes/*.json", :node)
+ @nodes.each do |name, node|
+ @nodes[name] = apply_inheritance(node)
+ end
+ end
+
+ #
+ # save compiled hiera .yaml files
+ #
+ def export(dir)
+ Dir.glob(dir + '/*.yaml').each do |f|
+ File.unlink(f)
+ end
+ @nodes.each do |name, node|
+ File.open("#{dir}/#{name}.#{node.domain_internal}.yaml", 'w') do |f|
+ f.write node.to_yaml
+ end
+ end
+ end
+
+ ##
+ ## FILTERING
+ ##
+
+ #
+ # returns a node list consisting only of nodes that satisfy the filter criteria.
+ #
+ # filter: condition [condition] [condition] [+condition]
+ # condition: [node_name | service_name | tag_name]
+ #
+ # if conditions is prefixed with +, then it works like an AND. Otherwise, it works like an OR.
+ #
+ def filter(filters)
+ if filters.empty?
+ return nodes
+ end
+ if filters[0] =~ /^\+/
+ # don't let the first filter have a + prefix
+ filters[0] = filters[0][1..-1]
+ end
+
+ node_list = Config::List.new
+ filters.each do |filter|
+ if filter =~ /^\+/
+ keep_list = nodes_for_name(filter[1..-1])
+ node_list.delete_if do |name, node|
+ if keep_list[name]
+ false
+ else
+ true
+ end
+ end
+ else
+ node_list << nodes_for_name(filter)
+ end
+ end
+ return node_list
+ end
+
+ ##
+ ## CLASS METHODS
+ ##
+
+ #def self.manager
+ # @manager ||= begin
+ # manager = ConfigManager.new
+ # manager.load(Path.provider)
+ # manager
+ # end
+ #end
+
+ #def self.filter(filters); manager.filter(filters); end
+ #def self.nodes; manager.nodes; end
+ #def self.services; manager.services; end
+ #def self.tags; manager.tags; end
+
+ private
+
+ def load_all_json(pattern, config_type = :class)
+ results = Config::List.new
+ Dir.glob(pattern).each do |filename|
+ obj = load_json(filename, config_type)
+ if obj
+ name = File.basename(filename).sub(/\.json$/,'')
+ obj['name'] = name
+ results[name] = obj
+ end
+ end
+ results
+ end
+
+ def load_json(filename, config_type)
+ log2 { filename.sub(/^#{Regexp.escape(Path.root)}/,'') }
+
+ #
+ # read file, strip out comments
+ # (File.read(filename) would be faster, but we like ability to have comments)
+ #
+ buffer = StringIO.new
+ File.open(filename) do |f|
+ while (line = f.gets)
+ next if line =~ /^\s*#/
+ buffer << line
+ end
+ end
+
+ # parse json, and flatten hash
+ begin
+ hash = Oj.load(buffer.string) || {}
+ rescue SyntaxError => exc
+ log0 'Error in file "%s":' % filename
+ log0 exc.to_s
+ return nil
+ end
+ config = config_type == :node ? Node.new(self) : Tag.new(self)
+ config.deep_merge!(hash)
+ return config
+ end
+
+ #
+ # remove all the nesting from a hash.
+ #
+ # def flatten_hash(input = {}, output = {}, options = {})
+ # input.each do |key, value|
+ # key = options[:prefix].nil? ? "#{key}" : "#{options[:prefix]}#{options[:delimiter]||"_"}#{key}"
+ # if value.is_a? Hash
+ # flatten_hash(value, output, :prefix => key, :delimiter => options[:delimiter])
+ # else
+ # output[key] = value
+ # end
+ # end
+ # output.replace(input)
+ # output
+ # end
+
+ #
+ # makes this node inherit options from the common, service, and tag json files.
+ #
+ # - takes a hash
+ # - returns a Node object.
+ #
+ def apply_inheritance(node)
+ new_hash = Node.new(self)
+ #new_node = Node.new(self)
+
+ # inherit from common
+ new_hash.deep_merge!(@common)
+
+ # inherit from services
+ if node['services']
+ node['services'].sort.each do |node_service|
+ service = @services[node_service]
+ if service.nil?
+ log0('Error in node "%s": the service "%s" does not exist.' % [node['name'], node_service])
+ else
+ new_hash.deep_merge!(service)
+ service.nodes << new_hash
+ end
+ end
+ end
+
+ # inherit from tags
+ if node['tags']
+ node['tags'].sort.each do |node_tag|
+ tag = @tags[node_tag]
+ if tag.nil?
+ log0('Error in node "%s": the tag "%s" does not exist.' % [node['name'], node_tag])
+ else
+ new_hash.deep_merge!(tag)
+ tag.nodes << new_hash
+ end
+ end
+ end
+
+ # inherit from node
+ new_hash.deep_merge!(node)
+
+ # typecast full hash tree to type Node
+ #new_node.clone_from_plain_hash!(new_hash)
+
+ return new_hash
+ end
+
+ #
+ # returns a set of nodes corresponding to a single name, where name could be a node name, service name, or tag name.
+ #
+ def nodes_for_name(name)
+ if node = self.nodes[name]
+ Config::List.new(node)
+ elsif service = self.services[name]
+ service.nodes
+ elsif tag = self.tags[name]
+ tag.nodes
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/leap_cli/config/node.rb b/lib/leap_cli/config/node.rb
new file mode 100644
index 0000000..5389b44
--- /dev/null
+++ b/lib/leap_cli/config/node.rb
@@ -0,0 +1,19 @@
+module LeapCli
+ module Config
+ class Node < Base
+
+ def nodes
+ @manager.nodes
+ end
+
+ def services
+ self['services'] || []
+ end
+
+ def tags
+ self['tags'] || []
+ end
+
+ end
+ end
+end
diff --git a/lib/leap_cli/config/tag.rb b/lib/leap_cli/config/tag.rb
new file mode 100644
index 0000000..25c7246
--- /dev/null
+++ b/lib/leap_cli/config/tag.rb
@@ -0,0 +1,19 @@
+module LeapCli
+ module Config
+ class Tag < Base
+
+ def nodes
+ @nodes ||= Config::List.new
+ end
+
+ def services
+ @manager.services
+ end
+
+ def tags
+ @manager.tags
+ end
+
+ end
+ end
+end
diff --git a/lib/leap_cli/config_list.rb b/lib/leap_cli/config_list.rb
deleted file mode 100644
index c8ff23b..0000000
--- a/lib/leap_cli/config_list.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-module LeapCli
- class ConfigList < Hash
-
- def initialize(config=nil)
- if config
- self << config
- end
- end
-
- #
- # if the key is a hash, we treat it as a condition and filter all the configs using the condition
- #
- # for example:
- #
- # nodes[:public_dns => true]
- #
- # will return a ConfigList with node configs that have public_dns set to true
- #
- def [](key)
- if key.is_a? Hash
- results = ConfigList.new
- field, match_value = key.to_a.first
- field = field.is_a?(Symbol) ? field.to_s : field
- match_value = match_value.is_a?(Symbol) ? match_value.to_s : match_value
- each do |name, config|
- value = config[field]
- if !value.nil?
- if value.is_a? Array
- if value.includes?(match_value)
- results[name] = config
- end
- else
- if value == match_value
- results[name] = config
- end
- end
- end
- end
- results
- else
- super
- end
- end
-
- def <<(config)
- if config.is_a? ConfigList
- self.merge!(config)
- else
- self[config['name']] = config
- end
- end
-
- #
- # converts the hash of configs into an array of hashes, with ONLY the specified fields
- #
- def fields(*fields)
- result = []
- keys.sort.each do |name|
- result << self[name].to_h(*fields)
- end
- result
- end
-
- #
- # like fields(), but returns an array of values instead of an array of hashes.
- #
- def field(field)
- field = field.to_s
- result = []
- keys.sort.each do |name|
- result << self[name][field]
- end
- result
- end
-
- end
-end
diff --git a/lib/leap_cli/config_manager.rb b/lib/leap_cli/config_manager.rb
deleted file mode 100644
index d383cc1..0000000
--- a/lib/leap_cli/config_manager.rb
+++ /dev/null
@@ -1,200 +0,0 @@
-require 'oj'
-require 'yaml'
-
-module LeapCli
-
- class ConfigManager
-
- attr_reader :services, :tags, :nodes
-
- ##
- ## IMPORT EXPORT
- ##
-
- #
- # load .json configuration files
- #
- def load(dir)
- @services = load_all_json("#{dir}/services/*.json")
- @tags = load_all_json("#{dir}/tags/*.json")
- @common = load_all_json("#{dir}/common.json")['common']
- @nodes = load_all_json("#{dir}/nodes/*.json", :node)
- @nodes.each do |name, node|
- apply_inheritance(node)
- end
- @nodes.each do |name, node|
- node.each {|key,value| node[key] } # force evaluation of dynamic values
- end
- end
-
- #
- # save compiled hiera .yaml files
- #
- def export(dir)
- Dir.glob(dir + '/*.yaml').each do |f|
- File.unlink(f)
- end
- @nodes.each do |name, node|
- File.open("#{dir}/#{name}.#{node.domain_internal}.yaml", 'w') do |f|
- f.write node.to_yaml
- end
- end
- end
-
- ##
- ## FILTERING
- ##
-
- #
- # returns a node list consisting only of nodes that satisfy the filter criteria.
- #
- # filter: condition [condition] [condition] [+condition]
- # condition: [node_name | service_name | tag_name]
- #
- # if conditions is prefixed with +, then it works like an AND. Otherwise, it works like an OR.
- #
- def filter(filters)
- if filters.empty?
- return nodes
- end
- if filters[0] =~ /^\+/
- # don't let the first filter have a + prefix
- filters[0] = filters[0][1..-1]
- end
-
- node_list = ConfigList.new
- filters.each do |filter|
- if filter =~ /^\+/
- keep_list = nodes_for_filter(filter[1..-1])
- node_list.delete_if do |name, node|
- if keep_list[name]
- false
- else
- true
- end
- end
- else
- node_list << nodes_for_filter(filter)
- end
- end
- return node_list
- end
-
- ##
- ## CLASS METHODS
- ##
-
- def self.manager
- @manager ||= begin
- manager = ConfigManager.new
- manager.load(Path.provider)
- manager
- end
- end
-
- def self.filter(filters); manager.filter(filters); end
- def self.nodes; manager.nodes; end
- def self.services; manager.services; end
- def self.tags; manager.tags; end
-
- private
-
- def load_all_json(pattern, config_type = :class)
- results = ConfigList.new
- Dir.glob(pattern).each do |filename|
- obj = load_json(filename, config_type)
- if obj
- name = File.basename(filename).sub(/\.json$/,'')
- obj['name'] = name
- results[name] = obj
- end
- end
- results
- end
-
- def load_json(filename, config_type)
- log2 { filename.sub(/^#{Regexp.escape(Path.root)}/,'') }
-
- #
- # read file, strip out comments
- # (File.read(filename) would be faster, but we like ability to have comments)
- #
- buffer = StringIO.new
- File.open(filename) do |f|
- while (line = f.gets)
- next if line =~ /^\s*#/
- buffer << line
- end
- end
-
- # parse json, and flatten hash
- begin
- hash = Oj.load(buffer.string) || {}
- rescue SyntaxError => exc
- log0 'Error in file "%s":' % filename
- log0 exc.to_s
- return nil
- end
- return flatten_hash(hash, Config.new(config_type, self))
- end
-
- #
- # remove all the nesting from a hash.
- #
- def flatten_hash(input = {}, output = {}, options = {})
- input.each do |key, value|
- key = options[:prefix].nil? ? "#{key}" : "#{options[:prefix]}#{options[:delimiter]||"_"}#{key}"
- if value.is_a? Hash
- flatten_hash(value, output, :prefix => key, :delimiter => options[:delimiter])
- else
- output[key] = value
- end
- end
- output
- end
-
- #
- # makes this node inherit options from the common, service, and tag json files.
- #
- def apply_inheritance(node)
- new_node = Config.new(:node, self)
- new_node.merge!(@common)
- if node['services']
- node['services'].sort.each do |node_service|
- service = @services[node_service]
- if service.nil?
- log0('Error in node "%s": the service "%s" does not exist.' % [node['name'], node_service])
- else
- new_node.merge!(service)
- service.nodes << node # this is odd, but we want the node pointer, not new_node pointer.
- end
- end
- end
- if node['tags']
- node['tags'].sort.each do |node_tag|
- tag = @tags[node_tag]
- if tag.nil?
- log0('Error in node "%s": the tag "%s" does not exist.' % [node['name'], node_tag])
- else
- new_node.merge!(tag)
- tag.nodes << node
- end
- end
- end
- new_node.merge!(node)
- node.replace(new_node)
- end
-
- def nodes_for_filter(filter)
- if node = self.nodes[filter]
- ConfigList.new(node)
- elsif service = self.services[filter]
- service.nodes
- elsif tag = self.tags[filter]
- tag.nodes
- end
- end
-
- end
-
-end
diff --git a/test/provider/common.json b/test/provider/common.json
index ead9d68..e8f5519 100644
--- a/test/provider/common.json
+++ b/test/provider/common.json
@@ -1,11 +1,11 @@
#
# Options put here are inherited by all nodes.
-#
+# # "fqdn": "= name + '.' + (public_dns ? domain_public : domain_internal)"
{
"domain": {
"public": "rewire.co",
"internal": "rewire"
},
"public_dns": true,
- "fqdn": "= name + '.' + (public_dns ? domain_public : domain_internal)"
+ "fqdn": "= name + '.' + (public_dns ? domain['public'] : domain['internal'])"
}
diff --git a/test/provider/files/public-definitions/provider.json.erb b/test/provider/files/public-definitions/provider.json.erb
index e69de29..0b8eeb6 100644
--- a/test/provider/files/public-definitions/provider.json.erb
+++ b/test/provider/files/public-definitions/provider.json.erb
@@ -0,0 +1 @@
+todo: implement template support. \ No newline at end of file
diff --git a/test/provider/hiera/couch1.rewire.yaml b/test/provider/hiera/couch1.yaml
index 2c731ce..a954a14 100644
--- a/test/provider/hiera/couch1.rewire.yaml
+++ b/test/provider/hiera/couch1.yaml
@@ -1,6 +1,7 @@
---
-domain_internal: rewire
-domain_public: rewire.co
+domain:
+ internal: rewire
+ public: rewire.co
fqdn: couch1.rewire
ip_address: 245.2.45.42
name: couch1
diff --git a/test/provider/hiera/couch2.rewire.yaml b/test/provider/hiera/couch2.yaml
index a835c79..208e64c 100644
--- a/test/provider/hiera/couch2.rewire.yaml
+++ b/test/provider/hiera/couch2.yaml
@@ -1,6 +1,7 @@
---
-domain_internal: rewire
-domain_public: rewire.co
+domain:
+ internal: rewire
+ public: rewire.co
fqdn: couch2.rewire
ip_address: 73.45.87.11
name: couch2
diff --git a/test/provider/hiera/ns1.rewire.yaml b/test/provider/hiera/ns1.rewire.yaml
deleted file mode 100644
index 264dd52..0000000
--- a/test/provider/hiera/ns1.rewire.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-domain_internal: rewire
-domain_public: rewire.co
-fqdn: ns1.rewire.co
-hosts_private:
-- ip_address: 245.2.45.42
- fqdn: couch1.rewire
-- ip_address: 73.45.87.11
- fqdn: couch2.rewire
-hosts_public:
-- ip_address: 1.1.1.1
- fqdn: ns1.rewire.co
-- ip_address: 1.1.1.2
- fqdn: ns2.rewire.co
-- ip_address: 2.2.2.2
- fqdn: vpn1.rewire.co
-- ip_address: 6.6.7.7
- fqdn: web1.rewire.co
- dns_alias: user.rewire.co
-ip_address: 1.1.1.1
-name: ns1
-production: true
-public_dns: true
-services: dns
-tags: production
diff --git a/test/provider/hiera/ns1.yaml b/test/provider/hiera/ns1.yaml
new file mode 100644
index 0000000..721e721
--- /dev/null
+++ b/test/provider/hiera/ns1.yaml
@@ -0,0 +1,26 @@
+---
+domain:
+ internal: rewire
+ public: rewire.co
+fqdn: ns1.rewire.co
+hosts:
+ private:
+ - fqdn: couch1.rewire
+ ip_address: 245.2.45.42
+ - fqdn: couch2.rewire
+ ip_address: 73.45.87.11
+ public:
+ - fqdn: ns1.rewire.co
+ ip_address: 1.1.1.1
+ - fqdn: ns2.rewire.co
+ ip_address: 1.1.1.2
+ - fqdn: vpn1.rewire.co
+ ip_address: 2.2.2.2
+ - fqdn: web1.rewire.co
+ ip_address: 6.6.7.7
+ip_address: 1.1.1.1
+name: ns1
+production: true
+public_dns: true
+services: dns
+tags: production
diff --git a/test/provider/hiera/ns2.rewire.yaml b/test/provider/hiera/ns2.rewire.yaml
deleted file mode 100644
index 2885424..0000000
--- a/test/provider/hiera/ns2.rewire.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-domain_internal: rewire
-domain_public: rewire.co
-fqdn: ns2.rewire.co
-hosts_private:
-- ip_address: 245.2.45.42
- fqdn: couch1.rewire
-- ip_address: 73.45.87.11
- fqdn: couch2.rewire
-hosts_public:
-- ip_address: 1.1.1.1
- fqdn: ns1.rewire.co
-- ip_address: 1.1.1.2
- fqdn: ns2.rewire.co
-- ip_address: 2.2.2.2
- fqdn: vpn1.rewire.co
-- ip_address: 6.6.7.7
- fqdn: web1.rewire.co
- dns_alias: user.rewire.co
-ip_address: 1.1.1.2
-name: ns2
-production: true
-public_dns: true
-services: dns
-tags: production
diff --git a/test/provider/hiera/ns2.yaml b/test/provider/hiera/ns2.yaml
new file mode 100644
index 0000000..b64a238
--- /dev/null
+++ b/test/provider/hiera/ns2.yaml
@@ -0,0 +1,26 @@
+---
+domain:
+ internal: rewire
+ public: rewire.co
+fqdn: ns2.rewire.co
+hosts:
+ private:
+ - fqdn: couch1.rewire
+ ip_address: 245.2.45.42
+ - fqdn: couch2.rewire
+ ip_address: 73.45.87.11
+ public:
+ - fqdn: ns1.rewire.co
+ ip_address: 1.1.1.1
+ - fqdn: ns2.rewire.co
+ ip_address: 1.1.1.2
+ - fqdn: vpn1.rewire.co
+ ip_address: 2.2.2.2
+ - fqdn: web1.rewire.co
+ ip_address: 6.6.7.7
+ip_address: 1.1.1.2
+name: ns2
+production: true
+public_dns: true
+services: dns
+tags: production
diff --git a/test/provider/hiera/vpn1.rewire.yaml b/test/provider/hiera/vpn1.rewire.yaml
deleted file mode 100644
index 158bb1b..0000000
--- a/test/provider/hiera/vpn1.rewire.yaml
+++ /dev/null
@@ -1,158 +0,0 @@
----
-domain_internal: rewire
-domain_public: rewire.co
-fqdn: vpn1.rewire.co
-ip_address: 2.2.2.2
-name: vpn1
-openvpn_ca_crt: |
- -----BEGIN CERTIFICATE-----
- MIIECzCCAl2gAwIBAgIEUFDp9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU
- RVNUMB4XDTEyMDkxMjIwMDA1M1oXDTEzMDkxMjIwMDA1M1owDzENMAsGA1UEAxME
- VEVTVDCCAbgwDQYJKoZIhvcNAQEBBQADggGlADCCAaACggGXANsoS1m9wj9iv+UV
- BXfeq14SR94gSot96eJu7PZVRrcGlGe/PRfbmfxF3j/gXM9B8sIkyM2L46OMtOKw
- 1iOTKtYYdMhtnUSd3FRshWGtYeuy+OCe9umU0jfZDBZ2pXlUmSqCNqfD0OPkksYL
- GDjQUKjaEd1oURwpCG8uEU+3tjBNCMuEwhcMEoUYmI8t4vss2hdFb+LKefVMPTzz
- oiNM/o8Z/ANzWCC0qSW5FsB4wGhUS5HKLDOr4tACgdxaJSWtAqFFAnyMeG9g8aqe
- PTM+URlqVnzzGckrJwBbd4y0zEpv/R7SAiSAP725cnB1GKptwdrcNIIHnQjOdAOl
- uNg6JlRXrv6fV1gApka4INfJAf1yMf+fA0WdZ22UJQ9Up7tdzi8lL+3HsEpEx4Pz
- NyzuqzEw9LJ6SUmMcE/VP00t4RjTOVoncwcLjvURY8jt2DQ9E36JEPwUoyALq/De
- bGBjeK2KGzBZcOu1HZAwWLLWR2++WKuCEXbRbahwSIlbMfmAe8xGx4bbHol0D1A+
- wmu0uxjAze6FvUkCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E
- BQMDBwQAMB0GA1UdDgQWBBT/PX8XZ0Y2jDkppz6PHs23IgzQEDANBgkqhkiG9w0B
- AQsFAAOCAZcAMfi+HLbcFaB0/Mv8/GkIdjpThUBVEeFrIiDy9GmGWUDOXgP1Skld
- 5H4eY5inE5lFfB69yacHIGS4OiZIBuBKfKNl5d6XO+ztJEJpG3yrbF4MtGV/aHEp
- OlbJCncnk3fspBk6tFGrv4Inak4gza6SQPfBEZj29ciwfwrqrtuWZ7km+og0Clcd
- pIB0g+DK0K//NtaDZDK0havQw2AFJKyXlNfI8XZ2jsNmQYR1wtiMci+UfGQr7bjn
- Kw9yyVCf0ohXvnSK4ortz/bDQbcMWkK0m/VCCEK8PSldk+XFzPWFWn5ndKCczcvd
- 1BQc392n12ZstEuzm6+d9A0D3kCxralJUXUC+4kThq4Rtjey/gBjyZQnZ+5tIxMF
- 5ZFAStEglNxqm6HB17q7owJqTvIg9Cf9GATsvoFFQDJrBXewRX7cWVeSr0zNSQB4
- ydIlSUOkyE3AyfLN+lx8NVS/I7gp4fWDuHrh27NKKDtMxalxPL5pTGO7l4uTybLY
- 4aVzQYGvzA5HVS++VAtcTQ6TP9p4HURL2cllEU9u9A==
- -----END CERTIFICATE-----
-
-openvpn_ca_key: |
- -----BEGIN RSA PRIVATE KEY-----
- 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
- -----END RSA PRIVATE KEY-----
-
-openvpn_filter_dns: false
-openvpn_gateway_address: 3.3.3.3
-openvpn_nat: true
-openvpn_ports:
-- "80"
-- "443"
-- "53"
-- "1194"
-openvpn_server_crt: |
- -----BEGIN CERTIFICATE-----
- MIIEWjCCAqygAwIBAgIEUFDqXzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU
- RVNUMB4XDTEyMDkxMjIwMDIzOVoXDTEzMDkxMjIwMDIzOVowKzEPMA0GA1UEChMG
- eHgub3JnMRgwFgYDVQQDEw9ob3N0bmFtZS54eC5vcmcwggG4MA0GCSqGSIb3DQEB
- AQUAA4IBpQAwggGgAoIBlwCvGqkXry509EWGAqbFUB5nqvsvA3kSIh0prgzaPYCg
- MMst58ZB89eTgiuM+U3jSF7LZr+CuE1DAb4m2U2f8D8IfViwK1yCa5AohG+LCmwe
- 4w4bgXtxwEBDac4u23JZ4AKE/EcKMeBbXe2d3o1S3P3XdN1ZVP0DVw04+H8cdh+0
- ggvhAA+9W/NvAQCAffL8sospj9nbl2OhRnrlFAzMWECyEyySPK5TEchU0hnFBRys
- DuYso5klLC6QXfSOkCSCOg9WQgjoyYBndTYxS3GwBnwyM+5V4TNtdc+P4vkkj+ZB
- D9R9oMpamUuuRQvk5/hJa7i8AaBy7ZmOO9QtL3866ONa6cLUN/QfBUkgM5iS6oQt
- X/qKxZFFYZPZUGBJqavuT+n4FB8XlIwcnqunK7rLD9OZwumYuZlHDtdAsgQ9Fd2z
- 06e7sDp28jcrk6gmpOapLqNPtPHVOGNA6mCZza4LonDMOSQKTfb6ZEXty+a8f2ig
- zErhHvmyCvREytDc9pIf2bL+Sz4ULTq62GDKf1Y3tRi2uHFjhKLTAgMBAAGjdjB0
- MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUD
- AwegADAdBgNVHQ4EFgQUmQ5YZjESlkYq2FBaYqGp2HAnSfAwHwYDVR0jBBgwFoAU
- /z1/F2dGNow5Kac+jx7NtyIM0BAwDQYJKoZIhvcNAQELBQADggGXAHiaPMSeIzac
- rRZQ/dJA7VDgvuFcY67zj9531zsDVi848kBkpSZ+9UyZOdhy5b9Din/IAVvd/XUP
- +VWwVsvKPbrWK79T/w8wj5nQR0uYfLdpMu7ZGjPhNes+/DnMX8Are2eb012g1km/
- HhOUxNg8/YpOJI4ZRnZls7j+u5kmHhc47sOQH9sY1FkHcWJ+K/lVhTk8Fmcm1vbN
- p7rjO4BItPVDxle0XF6bItwF1ahsK9MTzJIEO9ulHQnKYdhT9BcJbcwA3vhcn8nN
- uPN/RbDcWZTjONy58LVr7GxDQ267nZs5/wj4Cv3vDVq83kQJ7lCsYGTvxOejHWeQ
- QjcXREdBih9CPO3f86TOI8GRipIGvDcEll4DzgGRi+uTSWG69uC9yud/7+rnLd9Z
- WlobzAzRwljnR3aNACq0adYv1Wl05Fi2ab+QqL/C5ySrF5jL4OFUMpBu7nDPjty0
- KjQSmI9t6By6ORx14XT6piSlvSFn5phdMexXx1AYZEtdPSQduh2OquIPjN/qSdHO
- J+ZXOqDL1Jv+a89ghE8=
- -----END CERTIFICATE-----
-
-openvpn_server_key: |
- -----BEGIN RSA PRIVATE KEY-----
- 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
- -----END RSA PRIVATE KEY-----
-
-production: true
-public_dns: true
-services: openvpn
-tags: production
diff --git a/test/provider/hiera/vpn1.yaml b/test/provider/hiera/vpn1.yaml
new file mode 100644
index 0000000..d21d4f6
--- /dev/null
+++ b/test/provider/hiera/vpn1.yaml
@@ -0,0 +1,160 @@
+---
+domain:
+ internal: rewire
+ public: rewire.co
+fqdn: vpn1.rewire.co
+ip_address: 2.2.2.2
+name: vpn1
+openvpn:
+ ca_crt: |
+ -----BEGIN CERTIFICATE-----
+ MIIECzCCAl2gAwIBAgIEUFDp9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU
+ RVNUMB4XDTEyMDkxMjIwMDA1M1oXDTEzMDkxMjIwMDA1M1owDzENMAsGA1UEAxME
+ VEVTVDCCAbgwDQYJKoZIhvcNAQEBBQADggGlADCCAaACggGXANsoS1m9wj9iv+UV
+ BXfeq14SR94gSot96eJu7PZVRrcGlGe/PRfbmfxF3j/gXM9B8sIkyM2L46OMtOKw
+ 1iOTKtYYdMhtnUSd3FRshWGtYeuy+OCe9umU0jfZDBZ2pXlUmSqCNqfD0OPkksYL
+ GDjQUKjaEd1oURwpCG8uEU+3tjBNCMuEwhcMEoUYmI8t4vss2hdFb+LKefVMPTzz
+ oiNM/o8Z/ANzWCC0qSW5FsB4wGhUS5HKLDOr4tACgdxaJSWtAqFFAnyMeG9g8aqe
+ PTM+URlqVnzzGckrJwBbd4y0zEpv/R7SAiSAP725cnB1GKptwdrcNIIHnQjOdAOl
+ uNg6JlRXrv6fV1gApka4INfJAf1yMf+fA0WdZ22UJQ9Up7tdzi8lL+3HsEpEx4Pz
+ NyzuqzEw9LJ6SUmMcE/VP00t4RjTOVoncwcLjvURY8jt2DQ9E36JEPwUoyALq/De
+ bGBjeK2KGzBZcOu1HZAwWLLWR2++WKuCEXbRbahwSIlbMfmAe8xGx4bbHol0D1A+
+ wmu0uxjAze6FvUkCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E
+ BQMDBwQAMB0GA1UdDgQWBBT/PX8XZ0Y2jDkppz6PHs23IgzQEDANBgkqhkiG9w0B
+ AQsFAAOCAZcAMfi+HLbcFaB0/Mv8/GkIdjpThUBVEeFrIiDy9GmGWUDOXgP1Skld
+ 5H4eY5inE5lFfB69yacHIGS4OiZIBuBKfKNl5d6XO+ztJEJpG3yrbF4MtGV/aHEp
+ OlbJCncnk3fspBk6tFGrv4Inak4gza6SQPfBEZj29ciwfwrqrtuWZ7km+og0Clcd
+ pIB0g+DK0K//NtaDZDK0havQw2AFJKyXlNfI8XZ2jsNmQYR1wtiMci+UfGQr7bjn
+ Kw9yyVCf0ohXvnSK4ortz/bDQbcMWkK0m/VCCEK8PSldk+XFzPWFWn5ndKCczcvd
+ 1BQc392n12ZstEuzm6+d9A0D3kCxralJUXUC+4kThq4Rtjey/gBjyZQnZ+5tIxMF
+ 5ZFAStEglNxqm6HB17q7owJqTvIg9Cf9GATsvoFFQDJrBXewRX7cWVeSr0zNSQB4
+ ydIlSUOkyE3AyfLN+lx8NVS/I7gp4fWDuHrh27NKKDtMxalxPL5pTGO7l4uTybLY
+ 4aVzQYGvzA5HVS++VAtcTQ6TP9p4HURL2cllEU9u9A==
+ -----END CERTIFICATE-----
+
+ ca_key: |
+ -----BEGIN RSA PRIVATE KEY-----
+ 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
+ -----END RSA PRIVATE KEY-----
+
+ filter_dns: true
+ gateway_address: 3.3.3.3
+ nat: true
+ ports:
+ - "80"
+ - "443"
+ - "53"
+ - "1194"
+ server_crt: |
+ -----BEGIN CERTIFICATE-----
+ MIIEWjCCAqygAwIBAgIEUFDqXzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU
+ RVNUMB4XDTEyMDkxMjIwMDIzOVoXDTEzMDkxMjIwMDIzOVowKzEPMA0GA1UEChMG
+ eHgub3JnMRgwFgYDVQQDEw9ob3N0bmFtZS54eC5vcmcwggG4MA0GCSqGSIb3DQEB
+ AQUAA4IBpQAwggGgAoIBlwCvGqkXry509EWGAqbFUB5nqvsvA3kSIh0prgzaPYCg
+ MMst58ZB89eTgiuM+U3jSF7LZr+CuE1DAb4m2U2f8D8IfViwK1yCa5AohG+LCmwe
+ 4w4bgXtxwEBDac4u23JZ4AKE/EcKMeBbXe2d3o1S3P3XdN1ZVP0DVw04+H8cdh+0
+ ggvhAA+9W/NvAQCAffL8sospj9nbl2OhRnrlFAzMWECyEyySPK5TEchU0hnFBRys
+ DuYso5klLC6QXfSOkCSCOg9WQgjoyYBndTYxS3GwBnwyM+5V4TNtdc+P4vkkj+ZB
+ D9R9oMpamUuuRQvk5/hJa7i8AaBy7ZmOO9QtL3866ONa6cLUN/QfBUkgM5iS6oQt
+ X/qKxZFFYZPZUGBJqavuT+n4FB8XlIwcnqunK7rLD9OZwumYuZlHDtdAsgQ9Fd2z
+ 06e7sDp28jcrk6gmpOapLqNPtPHVOGNA6mCZza4LonDMOSQKTfb6ZEXty+a8f2ig
+ zErhHvmyCvREytDc9pIf2bL+Sz4ULTq62GDKf1Y3tRi2uHFjhKLTAgMBAAGjdjB0
+ MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUD
+ AwegADAdBgNVHQ4EFgQUmQ5YZjESlkYq2FBaYqGp2HAnSfAwHwYDVR0jBBgwFoAU
+ /z1/F2dGNow5Kac+jx7NtyIM0BAwDQYJKoZIhvcNAQELBQADggGXAHiaPMSeIzac
+ rRZQ/dJA7VDgvuFcY67zj9531zsDVi848kBkpSZ+9UyZOdhy5b9Din/IAVvd/XUP
+ +VWwVsvKPbrWK79T/w8wj5nQR0uYfLdpMu7ZGjPhNes+/DnMX8Are2eb012g1km/
+ HhOUxNg8/YpOJI4ZRnZls7j+u5kmHhc47sOQH9sY1FkHcWJ+K/lVhTk8Fmcm1vbN
+ p7rjO4BItPVDxle0XF6bItwF1ahsK9MTzJIEO9ulHQnKYdhT9BcJbcwA3vhcn8nN
+ uPN/RbDcWZTjONy58LVr7GxDQ267nZs5/wj4Cv3vDVq83kQJ7lCsYGTvxOejHWeQ
+ QjcXREdBih9CPO3f86TOI8GRipIGvDcEll4DzgGRi+uTSWG69uC9yud/7+rnLd9Z
+ WlobzAzRwljnR3aNACq0adYv1Wl05Fi2ab+QqL/C5ySrF5jL4OFUMpBu7nDPjty0
+ KjQSmI9t6By6ORx14XT6piSlvSFn5phdMexXx1AYZEtdPSQduh2OquIPjN/qSdHO
+ J+ZXOqDL1Jv+a89ghE8=
+ -----END CERTIFICATE-----
+
+ server_key: |
+ -----BEGIN RSA PRIVATE KEY-----
+ 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
+ -----END RSA PRIVATE KEY-----
+
+production: true
+public_dns: true
+services: openvpn
+tags: production
diff --git a/test/provider/hiera/web1.rewire.yaml b/test/provider/hiera/web1.rewire.yaml
deleted file mode 100644
index 6fc76d9..0000000
--- a/test/provider/hiera/web1.rewire.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-dns_alias: user.rewire.co
-domain_internal: rewire
-domain_public: rewire.co
-fqdn: web1.rewire.co
-ip_address: 6.6.7.7
-name: web1
-public_dns: true
-services: webapp
-webapp_couchdb_hosts:
-- couch1.rewire
-- couch2.rewire
-webapp_modules:
-- user
-- billing
-- help
diff --git a/test/provider/hiera/web1.yaml b/test/provider/hiera/web1.yaml
new file mode 100644
index 0000000..88c75d5
--- /dev/null
+++ b/test/provider/hiera/web1.yaml
@@ -0,0 +1,19 @@
+---
+definition_files:
+ provider: <%= {:hi => 'yes'}.to_json %>
+domain:
+ internal: rewire
+ public: rewire.co
+fqdn: web1.rewire.co
+ip_address: 6.6.7.7
+name: web1
+public_dns: true
+services: webapp
+webapp:
+ couchdb_hosts:
+ - couch1.rewire
+ - couch2.rewire
+ modules:
+ - user
+ - billing
+ - help
diff --git a/test/provider/nodes/vpn1.json b/test/provider/nodes/vpn1.json
index 10859ac..1c58a1b 100644
--- a/test/provider/nodes/vpn1.json
+++ b/test/provider/nodes/vpn1.json
@@ -3,6 +3,7 @@
"ip_address": "2.2.2.2",
"tags": "production",
"openvpn": {
- "gateway_address": "3.3.3.3"
+ "gateway_address": "3.3.3.3",
+ "filter_dns": true
}
} \ No newline at end of file
diff --git a/test/provider/services/webapp.json b/test/provider/services/webapp.json
index 1513d6f..5a045b2 100644
--- a/test/provider/services/webapp.json
+++ b/test/provider/services/webapp.json
@@ -1,7 +1,10 @@
+# "dns_alias": "= 'user.' + domain_public",
{
- "dns_alias": "= 'user.' + domain_public",
"webapp": {
"modules": ["user", "billing", "help"],
"couchdb_hosts": "= nodes[:services => :couchdb].field(:fqdn)"
+ },
+ "definition_files": {
+ "provider": "= file('public-definitions/provider.json.erb')"
}
} \ No newline at end of file