jerakia 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e7a0ffdcc717ef8705465da1d89d701353e31a4d
4
+ data.tar.gz: a40d224bb84863097b2b1e4d877aa5b8bfbed9c7
5
+ SHA512:
6
+ metadata.gz: a1e2f422baea90e6bc37df8bd5ed1b9717b41a3968b4eb44ad50dfa80eb1defdc11461da6f57e749fd074d4a986a9f135ea9ddee6797fcd9a73ef14dcca0e9b5
7
+ data.tar.gz: a6f211698de9b7286b674e76285f9720bc7c50a70f5bb9d9d121610592fae36ecf5d0bb858fdaf54ea7268d3108f93f322514a5f4cefbe8d963b02ac9c61d931
data/bin/jerakia ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'jerakia'
4
+ require 'json'
5
+ require 'optparse'
6
+
7
+ options = {
8
+ :policy => "default",
9
+ :config => "/etc/jerakia/jerakia.yml",
10
+ :scope => nil,
11
+ :key => nil,
12
+ :merge => "array",
13
+ :lookup_type => "first",
14
+ :namespace => nil,
15
+ :metadata => {},
16
+ }
17
+
18
+ OptionParser.new do |opts|
19
+
20
+ opts.on("--config CONFIG","-c","Config file") do |c|
21
+ options[:config] = c
22
+ end
23
+
24
+ opts.on("--key KEY", "-k", "Lookup key") do |k|
25
+ options[:key] = k
26
+ end
27
+
28
+ opts.on("--policy POLICY", "-p", "Policy") do |p|
29
+ options[:policy] = p.to_sym
30
+ end
31
+
32
+ opts.on("--namespace NAMESPACE", "-n", "Namespace") do |n|
33
+ options[:namespace] = n.split(/::/)
34
+ end
35
+
36
+ opts.on("--type TYPE", "-t", "Lookup type") do |t|
37
+ options[:lookup_type] = t.to_sym
38
+ end
39
+
40
+ opts.on("--scope SCOPE", "-s", "Scope handler") do |s|
41
+ options[:scope] = s.to_sym
42
+ end
43
+
44
+ opts.on("--merge MERGE", "-m", "Merge type") do |m|
45
+ options[:merge] = m.to_sym
46
+ end
47
+ end.parse!
48
+
49
+ unless ARGV.empty?
50
+ ARGV.each do |arg|
51
+ meta=arg.split(':')
52
+ options[:metadata][meta[0]] = meta[1]
53
+ end
54
+ end
55
+
56
+
57
+
58
+ jac = Jerakia.new({:config => options[:config]})
59
+ req = Jerakia::Request.new(
60
+ :key => options[:key],
61
+ :namespace => options[:namespace],
62
+ :policy => options[:policy].to_sym,
63
+ :lookup_type => options[:lookup_type].to_sym,
64
+ :merge => options[:merge].to_sym,
65
+ :loglevel => 'debug',
66
+ :metadata => options[:metadata]
67
+ )
68
+
69
+
70
+ answer = jac.lookup(req)
71
+ puts answer.payload.to_json
@@ -0,0 +1,67 @@
1
+ class Hiera
2
+ module Backend
3
+ class Jerakia_backend
4
+
5
+ def initialize
6
+ require 'jerakia'
7
+ @config = Config[:jerakia] || {}
8
+ @policy = @config[:policy] || 'default'
9
+ @jerakia = ::Jerakia.new(Config[:jerakia] || {})
10
+ Jerakia.log.debug("[hiera] hiera backend loaded with policy #{@policy}")
11
+
12
+ end
13
+
14
+
15
+ def lookup(key, scope, order_override, resolution_type)
16
+
17
+
18
+ lookup_type = :first
19
+ merge_type = :none
20
+
21
+ case resolution_type
22
+ when :array
23
+ lookup_type = :cascade
24
+ merge_type = :array
25
+ when :hash
26
+ lookup_type = :cascade
27
+ merge_type = :hash
28
+ end
29
+
30
+ namespace = []
31
+
32
+ if key.include?('::')
33
+ lookup_key = key.split('::')
34
+ namespace << lookup_key.shift
35
+ key = lookup_key.join('::')
36
+ end
37
+
38
+ Jerakia.log.debug("[hiera] backend invoked for key #{key} using namespace #{namespace}")
39
+
40
+ metadata={}
41
+ if scope.is_a?(Hash)
42
+ metadata=scope
43
+ else
44
+ metadata = scope.real.to_hash
45
+ end
46
+
47
+
48
+ request = Jerakia::Request.new(
49
+ :key => key,
50
+ :namespace => namespace,
51
+ :policy => @policy,
52
+ :lookup_type => lookup_type,
53
+ :merge => merge_type,
54
+ :metadata => metadata,
55
+ )
56
+
57
+ answer = @jerakia.lookup(request)
58
+ answer.payload
59
+
60
+
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+
@@ -0,0 +1,36 @@
1
+ class Jerakia::Answer
2
+
3
+ attr_accessor :payload
4
+ attr_accessor :datatype
5
+ attr_reader :lookup_type
6
+
7
+ def initialize(lookup_type = :first)
8
+ case lookup_type
9
+ when :first
10
+ @payload=nil
11
+ when :cascade
12
+ @payload=[]
13
+ @datatype="array"
14
+ end
15
+ end
16
+
17
+ def flatten_payload!
18
+ @payload.flatten!
19
+ end
20
+
21
+ def merge_payload!
22
+ payload_hash={}
23
+ @payload.each do |p|
24
+ if p.is_a?(Hash)
25
+ payload_hash.merge!(p)
26
+ end
27
+ end
28
+ @payload=payload_hash
29
+ set_data_type
30
+ end
31
+
32
+ def set_data_type
33
+ @data_type=@payload.class.to_s.downcase
34
+ end
35
+ end
36
+
@@ -0,0 +1,24 @@
1
+ #
2
+ # Very primitive form of cache - but we'll make this smarter
3
+ #
4
+ #
5
+ class Jerakia::Cache
6
+
7
+ def initialize
8
+ @@bucket = {}
9
+ end
10
+
11
+ def bucket_add(index,data)
12
+ @@bucket[index] = data
13
+ data
14
+ end
15
+
16
+ def in_bucket?(index)
17
+ @@bucket.has_key?(index)
18
+ end
19
+
20
+ def bucket
21
+ @@bucket
22
+ end
23
+ end
24
+
@@ -0,0 +1,25 @@
1
+ class Jerakia::Config
2
+
3
+ require 'yaml'
4
+ attr_reader :policydir
5
+ attr_reader :server_url
6
+
7
+ def initialize(config='/etc/jerakia/jerakia.yml')
8
+ unless File.exists?(config)
9
+ Jerakia.crit("Config file #{config} not found")
10
+ end
11
+ rawdata=File.read(config)
12
+ ymldata=YAML.load(rawdata)
13
+ @policydir=ymldata['policydir']
14
+ @server_url=ymldata['server_url']
15
+ @configdata=ymldata
16
+ end
17
+
18
+ def [](key)
19
+ @configdata[key.to_s]
20
+ end
21
+
22
+
23
+ end
24
+
25
+
@@ -0,0 +1,9 @@
1
+ class Jerakia::Datamodel < Jerakia
2
+
3
+
4
+ def initialize
5
+ @@namespace = {}
6
+ end
7
+
8
+ end
9
+
@@ -0,0 +1,17 @@
1
+ class Jerakia::Datasource
2
+ module Dummy
3
+
4
+ def run
5
+ #
6
+ # Do the lookup
7
+
8
+ Jerakia.log.debug("Searching key #{lookup.request.key} in dummy datasource")
9
+ option :return, { :type => String, :default => "Returned data" }
10
+ response.submit options[:return]
11
+
12
+
13
+
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,17 @@
1
+ class Jerakia::Datasource
2
+ module File
3
+ class Yaml
4
+ class << self
5
+ require 'yaml'
6
+ def import_file(fname, extension='yml')
7
+ diskfile="#{fname}.#{extension}"
8
+ Jerakia.log.debug("scanning file #{diskfile}")
9
+ return {} unless ::File.exists?(diskfile)
10
+ data=::File.read(diskfile)
11
+ YAML.load(data)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,65 @@
1
+ class Jerakia::Datasource
2
+ module File
3
+
4
+ attr_reader :file_format
5
+ def load_format_handler
6
+ format = options[:format] || :yaml
7
+ class_name=format.to_s.capitalize
8
+ require "jerakia/datasource/file/#{format.to_s}"
9
+ @file_format = eval "Jerakia::Datasource::File::#{class_name}"
10
+ end
11
+
12
+ def read_from_file(fname)
13
+ fpath = []
14
+ fpath << options[:docroot] unless fname[0] == '/'
15
+ fpath << [ fname, lookup.request.namespace ]
16
+ diskname = ::File.join(fpath.flatten).gsub(/\/$/, '')
17
+
18
+ Jerakia.log.debug("read_from_file() #{fname} using diskname #{diskname}")
19
+
20
+ import_args=[]
21
+ import_args << diskname
22
+ import_args << options[:extension] if options[:extension]
23
+
24
+ cache_index={ :diskname => diskname, :format => options[:format] }
25
+ if options[:enable_caching]
26
+ if in_bucket?(cache_index)
27
+ Jerakia.log.debug("returning cached data #{bucket[cache_index]}")
28
+ bucket[cache_index]
29
+ else
30
+ Jerakia.log.debug("adding to cache #{@file_format.import_file(*import_args)}")
31
+ bucket_add(cache_index,@file_format.import_file(*import_args))
32
+ end
33
+ else
34
+ @file_format.import_file(*import_args)
35
+ end
36
+ end
37
+
38
+
39
+ def run
40
+ #
41
+ # Do the lookup
42
+
43
+ Jerakia.log.debug("Searching key #{lookup.request.key} from file format #{options[:format]} (#{whoami})")
44
+ option :searchpath, { :type => Array, :mandatory => true }
45
+ option :format, { :type => Symbol, :default => :yaml }
46
+ option :docroot, { :type => String, :default => "/etc/jerakia/data" }
47
+ option :extension, { :type => String }
48
+
49
+ load_format_handler
50
+
51
+ options[:searchpath].each do |path|
52
+ Jerakia.log.debug("Attempting to load data from #{path}")
53
+ return unless response.want?
54
+ data=read_from_file(path)
55
+ Jerakia.log.debug("Datasource provided #{data} looking for key #{lookup.request.key}")
56
+ if data[lookup.request.key]
57
+ Jerakia.log.debug("Found data #{data[lookup.request.key]}")
58
+ response.submit data[lookup.request.key]
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,39 @@
1
+ require 'jerakia/cache'
2
+ class Jerakia::Datasource < Jerakia::Cache
3
+
4
+ require 'jerakia/response'
5
+ attr_reader :response
6
+ attr_reader :options
7
+ attr_reader :lookup
8
+
9
+ def initialize(name, lookup, opts)
10
+ @response = Jerakia::Response.new(lookup)
11
+ @options = opts
12
+ @lookup = lookup
13
+ @name = name
14
+ require "jerakia/datasource/#{name.to_s}"
15
+ # rescue loaderrer
16
+ eval "extend Jerakia::Datasource::#{name.to_s.capitalize}"
17
+ end
18
+
19
+
20
+ ## used for verbose logging
21
+ def whoami
22
+ "datasource=#{@name} lookup=#{@lookup.name}"
23
+ end
24
+
25
+ def option(opt, data={})
26
+ @options[opt] ||= data[:default] || nil
27
+ Jerakia.log.debug("[#{whoami}]: options[#{opt}] to #{options[opt]} [#{options[opt].class}]")
28
+ if @options[opt].nil?
29
+ Jerakia.crit "#{opt} must be configured in #{whoami}" if data[:mandatory]
30
+ else
31
+ if data[:type]
32
+ Jerakia.crit "#{opt} must be a #{data[:type].to_s} in #{whoami}" unless @options[opt].is_a?(data[:type])
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+ end
39
+
@@ -0,0 +1,34 @@
1
+ # Here we take a request object and read in the policy file
2
+ # which is evalulated in this instance
3
+ #
4
+ class Jerakia::Launcher
5
+
6
+ attr_reader :request
7
+ attr_reader :answer
8
+ def initialize(req)
9
+ @@request = req
10
+ invoke
11
+ end
12
+
13
+ def invoke
14
+ policy_name=request.policy.to_s
15
+ Jerakia.log.info "Invoked lookup for #{@@request.key} using policy #{policy_name}"
16
+ filename=File.join(Jerakia.config.policydir, "#{policy_name}.rb")
17
+ policydata=Jerakia.filecache(filename)
18
+ instance_eval policydata
19
+ end
20
+
21
+ def request
22
+ @@request
23
+ end
24
+
25
+
26
+ def policy(name, opts={}, &block)
27
+ policy = Jerakia::Policy.new(name, opts, &block)
28
+ policy.fire!
29
+ @answer = policy.answer
30
+ end
31
+ end
32
+
33
+
34
+
@@ -0,0 +1,52 @@
1
+ class Jerakia::Log < Jerakia
2
+
3
+ require 'logger'
4
+ def initialize(level=:info)
5
+ @@logfile ||= config[:logfile] || '/var/log/jerakia.log'
6
+ @@logger ||= Logger.new(@@logfile)
7
+ @@level ||= level
8
+ case @@level
9
+ when :info
10
+ @@logger.level = Logger::INFO
11
+ when :debug
12
+ @@logger.level = Logger::DEBUG
13
+ end
14
+ end
15
+
16
+ def info(msg)
17
+ @@logger.info msg
18
+ end
19
+
20
+ def debug(msg)
21
+ @@logger.debug msg
22
+ end
23
+
24
+ def error(msg)
25
+ @@logger.error msg
26
+ end
27
+
28
+ def fatal(msg)
29
+ @@logger.fatal msg
30
+ end
31
+
32
+ # def self.fatal(msg)
33
+ # self.new.fatal msg
34
+ # end
35
+ #
36
+ # def self.error(msg)
37
+ # self.new.error msg
38
+ # end
39
+ #
40
+ def self.debug(msg)
41
+ self.new.debug msg
42
+ end
43
+ #
44
+ ## def self.info(msg)
45
+ # puts @@logger
46
+ # self.new.info msg
47
+ # end
48
+
49
+
50
+
51
+ end
52
+
@@ -0,0 +1,92 @@
1
+ class Jerakia::Lookup
2
+ require 'jerakia/datasource'
3
+ require 'jerakia/scope'
4
+ require 'jerakia/plugins/lookup/hiera_compat'
5
+ require 'jerakia/plugins/lookup/confine'
6
+
7
+ attr_accessor :request
8
+ attr_reader :datasource
9
+ attr_reader :valid
10
+ attr_reader :lookuptype
11
+ attr_reader :scope_object
12
+ attr_reader :output_filters
13
+ attr_reader :name
14
+ attr_reader :proceed
15
+
16
+ def initialize(name,req,scope,&block)
17
+
18
+ @name=name
19
+ @request=req
20
+ @valid=true
21
+ @scope_object=scope
22
+ @output_filters=[]
23
+ @proceed=true
24
+ extend Jerakia::Lookup::Plugin
25
+ instance_eval &block
26
+
27
+ end
28
+
29
+ def datasource(source, opts={})
30
+ @datasource = Jerakia::Datasource.new(source, self, opts)
31
+ end
32
+
33
+ # If set, Jerakia will pass each Jerakia::Response object
34
+ # to an output filter plugin
35
+ #
36
+
37
+ def scope
38
+ @scope_object.value
39
+ end
40
+
41
+
42
+ def output_filter(name,opts={})
43
+ @output_filters << { :name => name, :opts => opts }
44
+ end
45
+
46
+ def proceed?
47
+ @proceed
48
+ end
49
+
50
+ ## lookup function: stop
51
+ # Enabling stop sets @proceed to false, which will cause Jerakia
52
+ # *not* to load any more lookups in the policy if this lookup is
53
+ # deemed as valid. If the lookup is invalidated than Jerakia *will*
54
+ # progress to the next lookup. This is useful in conjuction with
55
+ # the confine plugin where we want to segregate some lookups but
56
+ # not worry about excluding from later lookups
57
+ #
58
+ def stop
59
+ @proceed = false
60
+ end
61
+
62
+ ## lookup function: continue
63
+ # Will cause Jerakia to continue to the next lookup in the policy
64
+ # which is the default behaviour
65
+ #
66
+ def continue
67
+ @proceed = true
68
+ end
69
+
70
+ ## lookup function: invalidate
71
+ # Setting invalidate will mean this lookup will be skipped in the policy
72
+ #
73
+ def invalidate
74
+ @valid=false
75
+ end
76
+
77
+ def valid?
78
+ return @valid
79
+ end
80
+
81
+ def run
82
+ @datasource.run
83
+ response=@datasource.response
84
+ @output_filters.each do |filter|
85
+ response.filter! filter[:name], filter[:opts]
86
+ end
87
+ return response
88
+ end
89
+
90
+
91
+ end
92
+
@@ -0,0 +1,20 @@
1
+ class Jerakia::Lookup
2
+ module Plugin
3
+
4
+ def confine(key=nil,match)
5
+ if key
6
+ invalidate unless key[Regexp.new(match)] == key
7
+ else
8
+ invalidate
9
+ end
10
+ end
11
+
12
+ def exclude(key=nil,match)
13
+ if key
14
+ invalidate if key[Regexp.new(match)] == key
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+
@@ -0,0 +1,26 @@
1
+ # This plugin reformats the lookup key according to a puppet's
2
+ # Hiera system, so instead of looking up <key> in <path>/<namespace>.yml
3
+ # we lookup <namespace>::<key> in <path>.yml
4
+ #
5
+ # This is a useful plugin for people wanting to test drive Jerakia
6
+ # but maintain an existing hiera filesystem layout and naming convention
7
+ # within the source data.
8
+ #
9
+ class Jerakia::Lookup
10
+ module Plugin
11
+ def hiera_compat
12
+ request.key.prepend("#{request.namespace.join('::')}::")
13
+ request.namespace=[]
14
+ end
15
+
16
+ def calling_module
17
+ if request.namespace.length > 0
18
+ request.namespace[0]
19
+ else
20
+ Jerakia.log.error("hiera_compat plugin tried to use calling_module but there is no namespace declared. Ensure that calling_module is called before hiera_compat in the policy")
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,65 @@
1
+ require 'jerakia/launcher'
2
+
3
+ class Jerakia::Policy < Jerakia::Launcher
4
+ require 'jerakia/answer'
5
+
6
+ attr_accessor :lookups
7
+ attr_reader :routes
8
+ attr_reader :answer
9
+ attr_reader :scope
10
+ attr_reader :lookup_proceed
11
+
12
+ def initialize(name, opts, &block)
13
+ @lookups=[]
14
+ @routes={}
15
+ @answer=Jerakia::Answer.new(request.lookup_type)
16
+ @scope=Jerakia::Scope.new
17
+ @lookup_proceed = true
18
+ begin
19
+ instance_eval &block
20
+ rescue => e
21
+ Jerakia.fatal "Error processing policy file", e
22
+ end
23
+ end
24
+
25
+ def clone_request
26
+ Marshal.load(Marshal.dump(request))
27
+ end
28
+
29
+
30
+ def lookup(name,opts={},&block)
31
+ # We specifically clone the request object to allow plugins to modify the
32
+ # request payload for the scope of this lookup only.
33
+ #
34
+ lookup = Jerakia::Lookup.new(name,clone_request,scope,&block)
35
+ Jerakia.log.debug("Proceed to next lookup #{lookup.proceed?}")
36
+
37
+ @lookups << lookup if lookup.valid? and @lookup_proceed
38
+ @lookup_proceed = false if !lookup.proceed? and lookup.valid?
39
+
40
+ end
41
+
42
+ def fire!
43
+ @lookups.each do |l|
44
+ responses = l.run
45
+ responses.entries.each do |res|
46
+ case request.lookup_type
47
+ when :first
48
+ @answer.payload ||= res[:value]
49
+ @answer.datatype ||= res[:datatype]
50
+ when :cascade
51
+ @answer.payload << res[:value]
52
+ end
53
+ end
54
+
55
+ if request.lookup_type == :cascade && @answer.payload.is_a?(Array) && request.merge == :array
56
+ @answer.flatten_payload!
57
+ end
58
+ if request.lookup_type == :cascade && @answer.payload.is_a?(Array) && request.merge == :hash
59
+ @answer.merge_payload!
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,21 @@
1
+ class Jerakia::Request
2
+
3
+ attr_accessor :key
4
+ attr_accessor :namespace
5
+ attr_accessor :merge
6
+ attr_accessor :policy
7
+ attr_accessor :metadata
8
+ attr_accessor :lookup_type
9
+ attr_accessor :scope
10
+
11
+ def initialize(opts={})
12
+ @key = opts[:key] || ''
13
+ @namespace = opts[:namespace] || []
14
+ @merge = opts[:merge] || false
15
+ @policy = opts[:policy] || 'default'
16
+ @metadata = opts[:metadata] || {}
17
+ @lookup_type = opts[:lookup_type] || :first
18
+ @scope = opts[:scope] || nil
19
+ end
20
+
21
+ end