jerakia 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a4dda5d22fe6e0fa29b9ce287a9b44f20c2fe3e9
4
- data.tar.gz: 21e5f066edc6cd60249767e8ccd277559d9419d6
3
+ metadata.gz: 4303c4efbf02503a4942b9db6c1396a3f3076a39
4
+ data.tar.gz: 198c1a968a1502b73ce15c0467225e001dff93f8
5
5
  SHA512:
6
- metadata.gz: ab871bf140fd08288bbf39a7be8101c7151823c8eb3249e47e7ed89468399e500111edfc2dc5e108fdae7a557213811afedc5f3e8fb39c310fd27e68c718d187
7
- data.tar.gz: 2d793c5c420b128380d813c92e99bb7c56ff137003a016b2f624eb54e9c2a225172f7a7ae49c40495bbbf98a8342a723347bb3deba7699aaab036268d35b511b
6
+ metadata.gz: d8ab25c31d6044d86ba469d5f33c043152e269a4a22f52f991b3edfe8950012e0ec3889cf77c80e8ce4047af154176a438914d4f3bdcd7e72a86b9ab730cc826
7
+ data.tar.gz: ab5dd6838aec464f3a053d227ee71ed3180cbd79d0c592ba4b490023501882e8467b94b302f6c2176e2e4c052ced0fa1685ac602bf6c56c0719c848c34c512be
data/lib/jerakia.rb CHANGED
@@ -15,6 +15,7 @@ class Jerakia
15
15
  require 'jerakia/error'
16
16
 
17
17
  attr_reader :options
18
+ attr_reader :launcher
18
19
 
19
20
  class << self
20
21
  attr_reader :config
@@ -26,6 +27,7 @@ class Jerakia
26
27
 
27
28
  def initialize(options = {})
28
29
  @options = options
30
+ @policies = {}
29
31
 
30
32
  load_config
31
33
  load_log_handler
@@ -36,14 +38,11 @@ class Jerakia
36
38
 
37
39
  log.debug('Jerakia initialized')
38
40
  Jerakia.log.verbose("Jerakia started. Version #{Jerakia::VERSION}")
41
+ @launcher = Jerakia::Launcher.new
39
42
  end
40
43
 
41
44
  def lookup(request)
42
- lookup_instance = Jerakia::Launcher.new(request)
43
- lookup_instance.invoke_from_file
44
- lookup_instance.answer
45
- rescue Jerakia::Error => e
46
- Jerakia.fatal(e.message, e)
45
+ launcher.policies[request.policy.to_sym].run(request)
47
46
  end
48
47
 
49
48
  def self.fatal(msg, e)
@@ -4,9 +4,12 @@ class Jerakia
4
4
 
5
5
  attr_accessor :payload
6
6
  attr_accessor :datatype
7
+ attr_reader :merge_strategy
7
8
  attr_reader :lookup_type
8
9
 
9
- def initialize(lookup_type = :first)
10
+ def initialize(lookup_type = :first, merge_strategy = :array)
11
+ @lookup_type = lookup_type
12
+ @merge_strategy = merge_strategy
10
13
  case lookup_type
11
14
  when :first
12
15
  @payload = nil
@@ -16,17 +19,44 @@ class Jerakia
16
19
  end
17
20
  end
18
21
 
22
+ def process_response(response_entries)
23
+ response_entries.flatten.each do |res|
24
+ case lookup_type
25
+ when :first
26
+ @payload = res[:value]
27
+ @datatype = res[:datatype]
28
+ Jerakia.log.debug("Registered answer as #{payload}")
29
+ break
30
+ when :cascade
31
+ @payload << res[:value]
32
+ end
33
+ end
34
+ consolidate
35
+ end
36
+
37
+ def consolidate
38
+ if lookup_type == :cascade && payload.is_a?(Array)
39
+ case merge_strategy
40
+ when :array
41
+ flatten_payload!
42
+ when :hash, :deep_hash
43
+ merge_payload!
44
+ end
45
+ end
46
+ end
47
+
48
+
19
49
  def flatten_payload!
20
50
  @payload.flatten!
21
51
  end
22
52
 
23
53
  # TODO: consolidate this into less lines
24
54
  #
25
- def merge_payload!(method = :hash) # rubocop:disable Metrics/MethodLength
55
+ def merge_payload! # rubocop:disable Metrics/MethodLength
26
56
  payload_hash = {}
27
57
  @payload.each do |p|
28
58
  next unless p.is_a?(Hash)
29
- case method
59
+ case merge_strategy
30
60
  when :hash
31
61
  payload_hash = p.merge(payload_hash)
32
62
  when :deep_hash
data/lib/jerakia/cli.rb CHANGED
@@ -5,13 +5,15 @@ require 'yaml'
5
5
  require 'jerakia/cli/server'
6
6
  require 'jerakia/cli/token'
7
7
  require 'jerakia/cli/lookup'
8
-
8
+ require 'jerakia/cli/secret'
9
9
 
10
10
  class Jerakia
11
11
  class CLI < Thor
12
12
  include Jerakia::CLI::Server
13
13
  include Jerakia::CLI::Lookup
14
14
  include Jerakia::CLI::Token
15
+ include Jerakia::CLI::Secret
16
+
15
17
 
16
18
  desc 'version', 'Version information'
17
19
  def version
@@ -66,13 +66,13 @@ class Jerakia
66
66
  efault: 'json',
67
67
  desc: 'Output format, yaml or json'
68
68
 
69
- def lookup(key)
69
+ def lookup(key=nil)
70
70
  # Thor by default now returns a frozen options hash so we
71
71
  # need to dup this here to prevent problems later with
72
72
  # modifying the request object
73
73
  #
74
74
  options_copy = options.dup
75
-
75
+ key_copy = key.nil? ? key : key.dup
76
76
  case true
77
77
  when options[:verbose]
78
78
  loglevel = 'verbose'
@@ -91,7 +91,7 @@ class Jerakia
91
91
  :loglevel => loglevel,
92
92
  :trace => options[:trace])
93
93
  req = Jerakia::Request.new(
94
- :key => key.dup,
94
+ :key => key_copy,
95
95
  :namespace => options_copy[:namespace].split(/::/),
96
96
  :policy => options_copy[:policy].to_sym,
97
97
  :lookup_type => options_copy[:type].to_sym,
@@ -0,0 +1,58 @@
1
+ require 'jerakia/encryption'
2
+ require 'jerakia'
3
+
4
+ class Jerakia
5
+ class CLI < Thor
6
+ module Secret
7
+ class Secret < Thor
8
+
9
+ Jerakia.new
10
+ @provider = Jerakia::Encryption.new
11
+
12
+ class << self
13
+ attr_reader :provider
14
+ end
15
+
16
+ no_commands do
17
+ def provider
18
+ self.class.provider
19
+ end
20
+ end
21
+
22
+ if @provider.features?(:decrypt)
23
+ desc 'decrypt <encrypted value>', 'Decrypt an encrypted value'
24
+ def decrypt(encrypted)
25
+ begin
26
+ plaintext = provider.decrypt(encrypted)
27
+ rescue Jerakia::EncryptionError => e
28
+ puts e.message
29
+ exit(1)
30
+ end
31
+ puts plaintext
32
+ end
33
+ end
34
+
35
+ if @provider.features?(:encrypt)
36
+ desc 'encrypt <string>', 'Encrypt a plain text string'
37
+ def encrypt(plaintext)
38
+ begin
39
+ encrypted = provider.encrypt(plaintext)
40
+ rescue Jerakia::EncryptionError => e
41
+ puts e.message
42
+ exit(1)
43
+ end
44
+ puts encrypted
45
+ end
46
+ end
47
+ end
48
+
49
+ def self.included(thor)
50
+ thor.class_eval do
51
+ info = Secret.provider.loaded? ? "" : "(No encryption provider configured!)"
52
+ desc 'secret [SUBCOMMAND] <options>', "Manage encrypted secrets #{info}"
53
+ subcommand 'secret', Secret
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -3,47 +3,88 @@
3
3
  require 'jerakia/cache'
4
4
  class Jerakia
5
5
  class Datasource
6
- require 'jerakia/response'
6
+ class Instance
7
7
 
8
- attr_reader :response
9
- attr_reader :options
10
- attr_reader :lookup
11
- attr_reader :name
12
-
13
- def initialize(name, lookup, opts)
14
- @response = Jerakia::Response.new(lookup)
15
- @options = opts
16
- @lookup = lookup
17
- @name = name
18
- begin
19
- require "jerakia/datasource/#{name}"
20
- eval "extend Jerakia::Datasource::#{name.capitalize}"
21
- rescue LoadError => e
22
- raise Jerakia::Error, "Cannot load datasource #{name} in lookup #{lookup.name}, #{e.message}"
8
+ class << self
9
+ attr_reader :features
10
+ attr_accessor :options
23
11
  end
24
- end
25
12
 
26
- ## used for verbose logging
27
- def whoami
28
- "datasource=#{@name} lookup=#{@lookup.name}"
29
- end
13
+ attr_reader :options
14
+ attr_reader :request
15
+ attr_reader :response
30
16
 
31
- def option(opt, data = {})
32
- if @options[opt].nil? && data.key?(:default)
33
- @options[opt] = data[:default]
17
+ def initialize(lookup, opts)
18
+ self.class.validate_options(opts)
19
+ @response = Jerakia::Response.new(lookup)
20
+ @options = opts
21
+ @request = lookup.request
22
+ @features = []
23
+ end
24
+
25
+ def answer(data=nil)
26
+ if block_given?
27
+ while @response.want?
28
+ yield @response
29
+ end
30
+ else
31
+ @response.submit(data) if response.want? and not data.nil?
32
+ end
34
33
  end
35
34
 
36
- Jerakia.log.debug("[#{whoami}]: options[#{opt}] to #{options[opt]} [#{options[opt].class}]")
37
- if @options[opt].nil?
38
- raise Jerakia::PolicyError, "#{opt} option must be supplied for datasource #{@name} in lookup #{lookup.name}" if data[:mandatory]
39
- else
40
- if data[:type]
41
- if Array(data[:type]).select { |t| @options[opt].is_a?(t) }.empty?
42
- raise Jerakia::PolicyError,
43
- "#{opt} is a #{@options[opt].class} but must be a #{data[:type]} for datasource #{@name} in lookup #{lookup.name}"
35
+ def self.feature(name)
36
+ @features << name.to_sym unless @features.include?(name.to_sym)
37
+ end
38
+
39
+ def features?(name)
40
+ @features.include?(name)
41
+ end
42
+
43
+ def self.option(name, arguments = {}, &block)
44
+ self.options={} if self.options.nil?
45
+ @options[name] = Proc.new do |opt|
46
+ if arguments[:default]
47
+ opt = arguments[:default] if opt.nil?
48
+ end
49
+ if arguments[:required]
50
+ raise Jerakia::DatasourceArgumentError, "Must specify #{name} parameter" if opt.nil?
51
+ end
52
+
53
+ if block_given?
54
+ unless opt.nil?
55
+ raise Jerakia::DatasourceArgumentError, "Validation failed for #{name}" unless yield opt
56
+ end
44
57
  end
58
+ opt
45
59
  end
46
60
  end
61
+ def self.validate_options(args)
62
+ options.keys.each do |k|
63
+ options[k].call(args[k])
64
+ end
65
+
66
+ args.keys.each do |k|
67
+ raise Jerakia::DatasourceArgumentError, "Unknown option #{k}" unless options.keys.include?(k)
68
+ end
69
+ end
70
+ end
71
+
72
+ require 'jerakia/response'
73
+
74
+ def self.load_datasource(name)
75
+ require "jerakia/datasource/#{name.to_s}"
76
+ end
77
+
78
+ def self.class_of(name)
79
+ return eval "Jerakia::Datasource::#{name.to_s.capitalize}"
80
+ end
81
+
82
+
83
+ def self.run(lookup)
84
+ options = lookup.datasource[:opts]
85
+ datasource = class_of(lookup.datasource[:name]).new(lookup, options)
86
+ datasource.lookup
87
+ return datasource.response
47
88
  end
48
89
  end
49
90
  end
@@ -1,12 +1,8 @@
1
- class Jerakia::Datasource
2
- module Dummy
3
- def run
4
- #
5
- # Do the lookup
6
-
7
- Jerakia.log.debug("Searching key #{lookup.request.key} in dummy datasource")
8
- option :return, :type => [String, Hash, Array], :default => 'Returned data'
9
- response.submit options[:return]
10
- end
1
+ class Jerakia::Datasource::Dummy < Jerakia::Datasource::Instance
2
+ option :return, :default => 'Returned data'
3
+ def lookup
4
+ answer options[:return]
11
5
  end
12
6
  end
7
+
8
+
@@ -1,81 +1,95 @@
1
1
  require 'jerakia/cache/file'
2
2
 
3
- class Jerakia::Datasource
4
- module File
5
- attr_reader :file_format
6
-
7
- def load_format_handler
8
- format = options[:format] || :yaml
9
- class_name = format.to_s.capitalize
10
- require "jerakia/datasource/file/#{format}"
11
- @file_format = eval "Jerakia::Datasource::File::#{class_name}"
12
- end
3
+ #Jerakia::Datasource.define(:file) do
4
+ #
5
+ class Jerakia::Datasource::File < Jerakia::Datasource::Instance
13
6
 
14
- def cache
15
- Jerakia::Cache::File
16
- end
7
+ option(:searchpath, :required => true) { |opt| opt.is_a?(Array) }
17
8
 
18
- def get_file_with_cache(diskname)
19
- if options[:enable_caching]
20
- Jerakia.log.debug("Querying cache for file #{diskname}")
21
- cache.retrieve(diskname)
22
- else
23
- ::File.read(diskname) if ::File.exists?(diskname)
24
- end
25
- end
9
+ option :format, :default => :yaml
10
+ option :docroot, :default => '/var/lib/jerakia/data'
11
+ option :extention
12
+ option :enable_caching, :default => true
26
13
 
27
- def list_fragments(prefix, extension)
28
- Dir["#{prefix}.d/*.#{extension}"] if ::File.directory?("#{prefix}.d")
29
- end
14
+ def load_format_handler
15
+ format = options[:format]
16
+ require "jerakia/datasource/file/#{format.to_s}"
17
+ eval "extend Jerakia::Datasource::File::#{format.to_s.capitalize}"
18
+ end
30
19
 
31
- def read_from_file(fname)
32
- fpath = []
33
- fpath << options[:docroot] unless fname[0] == '/'
34
- fpath << [fname, lookup.request.namespace]
20
+ def format_handler
21
+ format = options[:format]
22
+ eval "Jerakia::Datasource::File::#{format.to_s.capitalize}"
23
+ end
24
+
25
+ def extension
26
+ options[:extension] || format_handler::EXTENSION
27
+ end
35
28
 
36
- extension = options[:extension] || @file_format::EXTENSION
37
- diskname_prefix = ::File.join(fpath.flatten).gsub(/\/$/, '').to_s
38
- diskname = "#{diskname_prefix}.#{extension}"
29
+ def cache
30
+ Jerakia::Cache::File
31
+ end
39
32
 
40
- files = [diskname]
41
- files << list_fragments(diskname_prefix, extension)
33
+ def get_file_with_cache(diskname)
34
+ Jerakia.log.debug("Querying cache for file #{diskname}")
35
+ cache.retrieve(diskname)
36
+ end
42
37
 
43
- raw_data = ''
38
+ def get_file(diskname)
39
+ ::File.read(diskname) if ::File.exists?(diskname)
40
+ end
44
41
 
45
- files.flatten.compact.each do |f|
46
- Jerakia.log.debug("read_from_file() #{f}")
42
+ def list_fragments(prefix, extension)
43
+ Dir["#{prefix}.d/*.#{extension}"] if ::File.directory?("#{prefix}.d")
44
+ end
45
+
46
+ def read_from_file(fname)
47
+ docroot = options[:docroot]
48
+ namespace = request.namespace
49
+ cached = options[:enable_caching]
50
+
51
+ fpath = []
52
+ fpath << docroot unless fname[0] == '/'
53
+ fpath << [fname, namespace]
54
+
55
+ diskname_prefix = ::File.join(fpath.flatten).gsub(/\/$/, '').to_s
56
+ diskname = "#{diskname_prefix}.#{extension}"
57
+
58
+ files = [diskname]
59
+ files << list_fragments(diskname_prefix, extension)
60
+
61
+ raw_data = ''
62
+
63
+ files.flatten.compact.each do |f|
64
+ Jerakia.log.debug("read_from_file() #{f}")
65
+ file_contents = get_file_with_cache(f)
66
+ if cached
47
67
  file_contents = get_file_with_cache(f)
48
- raw_data << file_contents if file_contents
68
+ else
69
+ file_content = get_file(f)
49
70
  end
71
+ raw_data << file_contents if file_contents
72
+ end
50
73
 
51
- begin
52
- file_format.convert(raw_data)
53
- rescue Jerakia::FileParseError => e
54
- raise Jerakia::FileParseError, "While parsing #{diskname}: #{e.message}"
55
- end
74
+ begin
75
+ convert(raw_data)
76
+ rescue Jerakia::FileParseError => e
77
+ raise Jerakia::FileParseError, "While parsing #{diskname}: #{e.message}"
56
78
  end
79
+ end
80
+
81
+ def lookup
82
+ Jerakia.log.debug("Searching key #{request.key} from file format #{options[:format]}")
83
+
84
+ load_format_handler
85
+ paths=options[:searchpath].flatten
57
86
 
58
- def run
59
- #
60
- # Do the lookup
61
-
62
- Jerakia.log.debug("Searching key #{lookup.request.key} from file format #{options[:format]} (#{whoami})")
63
- option :searchpath, :type => Array, :mandatory => true
64
- option :format, :type => Symbol, :default => :yaml
65
- option :docroot, :type => String, :default => '/etc/jerakia/data'
66
- option :extension, :type => String
67
-
68
- load_format_handler
69
-
70
- options[:searchpath].flatten.each do |path|
71
- Jerakia.log.debug("Attempting to load data from #{path}")
72
- return unless response.want?
73
- data = read_from_file(path)
74
- Jerakia.log.debug("Datasource provided #{data} looking for key #{lookup.request.key}")
75
- unless data[lookup.request.key].nil?
76
- Jerakia.log.debug("Found data #{data[lookup.request.key]}")
77
- response.submit data[lookup.request.key]
78
- end
87
+ answer do |response|
88
+ path = paths.shift
89
+ break unless path
90
+ data = read_from_file(path)
91
+ unless data[request.key].nil?
92
+ response.submit data[request.key]
79
93
  end
80
94
  end
81
95
  end