jerakia 2.4.0 → 2.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea3f9b99ad3814fc4868f19d64d8f47adf16e940
4
- data.tar.gz: 0ff66c99cdff190f8047dfce865cc01e749efa19
3
+ metadata.gz: 6e4145ea38aa8d6573c8511c06241c79032e38a1
4
+ data.tar.gz: d42e6335997192ff954540abf9e9930f35701217
5
5
  SHA512:
6
- metadata.gz: 1e291ef9b8af754741a04088d6782d1710d2194da4aedc73ddd6a447078e06ad119afca6c338080683300aa2e89be8adea381dba91468790acbcb5ccc97977d9
7
- data.tar.gz: 1ffc73296862825e61e8e6eb5ec6c46d6b31b27ce9d47150783879bf4e15762692b9b42fbff07401dd4e15c87aefbb5d84c8c3e53a7bf997ad29af01292e41ff
6
+ metadata.gz: 7ae5b4c70dc8e34e1e486b89f297cae5772bfb138cfa057fbf040b393c00ba0dc65141f00b10e7c136fa6b0c3e2ad89b12dc47ecca0b8c9dd01cc6c6910c9fdd
7
+ data.tar.gz: 52cfaffb30597c12f0d4c881bd795239893ff6c1d49ec8ddb5aca03db9d8316404977e8eeb8ff28894f8ccdb69cbd7406350fca126c3b8433e85ade3ac873b10
@@ -10,6 +10,7 @@ class Jerakia
10
10
  def initialize(lookup_type = :first, merge_strategy = :array)
11
11
  @lookup_type = lookup_type
12
12
  @merge_strategy = merge_strategy
13
+ @found = false
13
14
  case lookup_type
14
15
  when :first
15
16
  @payload = nil
@@ -20,20 +21,29 @@ class Jerakia
20
21
  end
21
22
 
22
23
  def process_response(response_entries)
23
- response_entries.flatten.each do |res|
24
+ responses = response_entries.flatten.compact
25
+
26
+ return nil if responses.empty?
27
+ @found = true
28
+
29
+ responses.each do |res|
24
30
  case lookup_type
25
31
  when :first
26
- @payload = res[:value]
27
- @datatype = res[:datatype]
32
+ @payload = res.value
33
+ @datatype = res.datatype
28
34
  Jerakia.log.debug("Registered answer as #{payload}")
29
35
  break
30
36
  when :cascade
31
- @payload << res[:value]
37
+ @payload << res.value
32
38
  end
33
39
  end
34
40
  consolidate
35
41
  end
36
42
 
43
+ def found?
44
+ @found
45
+ end
46
+
37
47
  def consolidate
38
48
  if lookup_type == :cascade && payload.is_a?(Array)
39
49
  case merge_strategy
@@ -15,9 +15,8 @@ class Jerakia
15
15
  attr_reader :response
16
16
 
17
17
  def initialize(lookup, opts)
18
- self.class.validate_options(opts)
19
18
  @response = Jerakia::Response.new(lookup)
20
- @options = opts
19
+ @options = self.class.set_options(opts)
21
20
  @request = lookup.request
22
21
  @features = []
23
22
  end
@@ -64,11 +63,17 @@ class Jerakia
64
63
  opt
65
64
  end
66
65
  end
67
- def self.validate_options(args)
66
+
67
+ def self.set_options(args)
68
+ opts = {}
68
69
  options.keys.each do |k|
69
- options[k].call(args[k])
70
+ opts[k] = options[k].call(args[k])
70
71
  end
72
+ validate_options(args)
73
+ opts
74
+ end
71
75
 
76
+ def self.validate_options(args)
72
77
  args.keys.each do |k|
73
78
  raise Jerakia::DatasourceArgumentError, "Unknown option #{k}" unless options.keys.include?(k)
74
79
  end
@@ -0,0 +1,88 @@
1
+ require 'diplomat'
2
+ require 'uri'
3
+
4
+ class Jerakia::Datasource::Consul_kv < Jerakia::Datasource::Instance
5
+
6
+ # datacenter option sets the :dc method in the Diplomat
7
+ # request to perform a consul lookup using a particular
8
+ # datacenter
9
+ #
10
+ option(:datacenter) { |str| str.is_a?(String) }
11
+
12
+ # to_hash, when used with recursive, will consolidate the
13
+ # results into a hash, instead of an array
14
+ #
15
+ option(:to_hash, :default => true) { |opt|
16
+ [ TrueClass, FalseClass ].include?(opt.class)
17
+ }
18
+
19
+ # Recursive will return the entire data structure from console
20
+ # rather than just the requested key
21
+ #
22
+ option(:recursive, :default => false) { |opt|
23
+ [ TrueClass, FalseClass ].include?(opt.class)
24
+ }
25
+
26
+ # The searchpath is the root path of the request, which will
27
+ # get appended with the namespace, and key if applicable.
28
+ # We allow this option to be ommited in case the lookup path
29
+ # starts at the namesapce.
30
+ #
31
+ option(:searchpath, :default => ['']) { |opt| opt.is_a?(Array) }
32
+
33
+ # Set any consul parameters against the Diplomat class
34
+ #
35
+ # These values are set in jerakia.yaml and are loaded directly
36
+ # to the class when we load the datasource for the first time.
37
+ #
38
+ consul_config = Jerakia.config['consul']
39
+ if consul_config.is_a?(Hash)
40
+ Diplomat.configure do |config|
41
+ config.url = consul_config['url'] if consul_config.has_key?('url')
42
+ config.acl_token = consul_config['acl_token'] if consul_config.has_key?('acl_token')
43
+ config.options = consul_config['options'] if consul_config['options'].is_a?(Hash)
44
+ end
45
+ end
46
+
47
+
48
+
49
+ # Entrypoint for Jerakia lookups starts here.
50
+ #
51
+ def lookup
52
+
53
+ Jerakia.log.debug("[datasource::console_kv] backend performing lookup for #{request.key}")
54
+ paths = options[:searchpath].reject { |p| p.nil? }
55
+
56
+ key = request.key
57
+ namespace = request.namespace
58
+
59
+
60
+ answer do |response|
61
+
62
+ break if paths.empty?
63
+ path = paths.shift.split('/').compact
64
+
65
+
66
+ path << namespace
67
+ path << key unless key.nil?
68
+
69
+ diplomat_options = {
70
+ :recurse => options[:recursive],
71
+ :convert_to_hash => options[:to_hash],
72
+ :dc => options[:datacenter],
73
+ }
74
+
75
+ begin
76
+ key_path = path.flatten.join('/')
77
+ Jerakia.log.debug("[datasource::consul_kv] Looking up #{key_path} with options #{diplomat_options}")
78
+ result = Diplomat::Kv.get(key_path, diplomat_options)
79
+ rescue Diplomat::KeyNotFound => e
80
+ Jerakia.log.debug("NotFound encountered, skipping to next path entry")
81
+ next
82
+ rescue Faraday::ConnectionFailed => e
83
+ raise Jerakia::Error, "Failed to connect to consul service: #{e.message}"
84
+ end
85
+ response.submit result
86
+ end
87
+ end
88
+ end
@@ -8,7 +8,7 @@ class Jerakia::Datasource::File < Jerakia::Datasource::Instance
8
8
 
9
9
  option :format, :default => :yaml
10
10
  option :docroot, :default => '/var/lib/jerakia/data'
11
- option :extention
11
+ option :extension
12
12
  option :enable_caching, :default => true
13
13
 
14
14
  def load_format_handler
@@ -88,7 +88,7 @@ class Jerakia::Datasource::File < Jerakia::Datasource::Instance
88
88
  path = paths.shift
89
89
  break unless path
90
90
  data = read_from_file(path)
91
- unless data[request.key].nil?
91
+ if data.has_key?(request.key)
92
92
  response.submit data[request.key]
93
93
  end
94
94
  end
@@ -19,6 +19,14 @@ class Jerakia::Datasource::Http < Jerakia::Datasource::Instance
19
19
  option :http_connect_timeout, :type => Integer
20
20
  option :paths, :type => Array, :required => true
21
21
 
22
+ # When lookup_key is set to false, the datasource will not attempt to
23
+ # look up the key from a hash that gets returned. This flag will be
24
+ # set to default of false in Jerakia 3.0
25
+ #
26
+ option(:lookup_key, :default => true) { |opt|
27
+ [TrueClass,FalseClass].include?(opt.class)
28
+ }
29
+
22
30
  def lookup
23
31
 
24
32
  lookup_supported_params = [
@@ -53,9 +61,10 @@ class Jerakia::Datasource::Http < Jerakia::Datasource::Instance
53
61
  Jerakia.log.debug("Datasource provided #{data} (#{data.class}) looking for key #{request.key}")
54
62
 
55
63
  if data.is_a?(Hash)
56
- unless data[request.key].nil?
57
- Jerakia.log.debug("Found data #{data[request.key]}")
58
- response.submit data[request.key]
64
+ if options[:lookup_key]
65
+ response.submit data[request.key] if data.has_key?(request.key)
66
+ else
67
+ response.submit data
59
68
  end
60
69
  else
61
70
  unless options[:output] == 'plain' || options[:failure] == 'graceful'
@@ -21,8 +21,6 @@ class Jerakia
21
21
  # @api: public
22
22
  def datasource(name, opts = {})
23
23
  lookup.datasource = { :name => name, :opts => opts }
24
- #datasource = Jerakia::Datasource.new(name, lookup, opts)
25
- #lookup.datasource = datasource
26
24
  end
27
25
 
28
26
  # pass through exposed functions from the main lookup object
@@ -44,6 +44,7 @@ class Jerakia
44
44
  break unless lookup_instance.proceed?
45
45
  end
46
46
  answer.process_response(response_entries)
47
+ Jerakia.log.debug(answer)
47
48
  return answer
48
49
  end
49
50
 
@@ -1,7 +1,30 @@
1
1
  class Jerakia::Response < Jerakia
2
- attr_accessor :entries
3
2
  attr_reader :lookup
4
3
 
4
+ class Entry
5
+ attr_reader :value
6
+ attr_reader :datatype
7
+ attr_reader :valid
8
+
9
+ def initialize(val)
10
+ @valid = true
11
+ set_value(val)
12
+ end
13
+
14
+ def invalidate
15
+ @valid = false
16
+ end
17
+
18
+ def valid?
19
+ @valid
20
+ end
21
+
22
+ def set_value(val)
23
+ @value = val
24
+ @datatype = val.class.to_s.downcase
25
+ end
26
+ end
27
+
5
28
  def initialize(lookup)
6
29
  @entries = []
7
30
  @lookup = lookup
@@ -17,28 +40,30 @@ class Jerakia::Response < Jerakia
17
40
  end
18
41
  end
19
42
 
43
+
20
44
  def submit(val)
21
45
  Jerakia.log.debug "Backend submitted #{val}"
22
46
  if want?
23
- @entries << {
24
- :value => val,
25
- :datatype => val.class.to_s.downcase
26
- }
47
+ @entries << Jerakia::Response::Entry.new(val)
27
48
  Jerakia.log.debug "Added answer #{val}"
28
49
  else
29
50
  no_more_answers
30
51
  end
31
52
  end
32
53
 
33
- def values
34
- Jerakia::Util.walk(@entries) do |entry|
54
+ def responses
55
+ @entries.each do |entry|
35
56
  yield entry
36
57
  end
37
58
  end
38
59
 
60
+ def entries
61
+ @entries.select { |e| e.valid? }
62
+ end
63
+
39
64
  def parse_values
40
65
  @entries.map! do |entry|
41
- Jerakia::Util.walk(entry[:value]) do |v|
66
+ Jerakia::Util.walk(entry.value) do |v|
42
67
  yield v
43
68
  end
44
69
  entry
@@ -0,0 +1,17 @@
1
+ #class Jerakia::Response
2
+ # class Entry
3
+ #
4
+ # attr_reader :value
5
+ # attr_reader :datatype
6
+ #
7
+ # def initialize(val)
8
+ # set_value(val)
9
+ # end
10
+ #
11
+ # def set_value(val)
12
+ # @value = val
13
+ # @datatype = val.class.to_s.downcase
14
+ # end
15
+ # end
16
+ #end
17
+ #
@@ -1,10 +1,14 @@
1
1
  class Jerakia::Response
2
2
  module Filter
3
3
  def filter!(name, opts = {})
4
+
5
+ unless opts.is_a?(Hash) || opts.is_a?(Array)
6
+ raise Jerakia::PolicyError, "Output filters may only accept hashes or arrays as arguments"
7
+ end
4
8
  Jerakia::Util.autoload('response/filter', name)
5
9
  Jerakia.log.debug("Invoking output filter #{name}")
6
10
  instance_eval "extend Jerakia::Response::Filter::#{name.to_s.capitalize}"
7
- instance_eval "self.filter_#{name} (#{opts})"
11
+ instance_eval "self.filter_#{name}(#{opts})"
8
12
  end
9
13
  end
10
14
  end
@@ -0,0 +1,25 @@
1
+ class Jerakia::Response
2
+ module Filter
3
+ module Dig
4
+ def filter_dig(path = [])
5
+ raise Jerakia::PolicyError, "Argument to output filter dig must be an array" unless path.is_a?(Array)
6
+ Jerakia.log.debug("[output_filter:dig]: Attempting to dig using path #{path}")
7
+ responses do |entry|
8
+
9
+ unless entry.value.is_a?(Hash)
10
+ raise Jerakia::Error, "Cannot perform dig on a non hash value"
11
+ end
12
+
13
+ value = Jerakia::Util.dig(entry.value, path.flatten)
14
+ if value == :not_found
15
+ Jerakia.log.debug('[output_filter:dig]: Digging value from response failed, invalidating')
16
+ entry.invalidate
17
+ else
18
+ entry.set_value(value)
19
+ Jerakia.log.debug("[output_filter:dig]: Re-submitting response as #{value}")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -123,7 +123,8 @@ class Jerakia
123
123
  rescue Jerakia::Error => e
124
124
  request_failed(e.message, 501)
125
125
  end
126
- encode_result({ :status => 'ok',
126
+ encode_result({ :status => 'ok',
127
+ :found => answer.found?,
127
128
  :payload => answer.payload})
128
129
  end
129
130
 
@@ -6,6 +6,20 @@ class Jerakia
6
6
  require "jerakia/#{path}/#{mod}"
7
7
  end
8
8
 
9
+ def dig(data, dig_path)
10
+ key = dig_path.shift
11
+ if dig_path.empty?
12
+ if data.has_key?(key)
13
+ return data[key]
14
+ else
15
+ return :not_found
16
+ end
17
+ else
18
+ return :not_found unless data[key].is_a?(Hash)
19
+ return dig(data[key], dig_path)
20
+ end
21
+ end
22
+
9
23
  def walk(data)
10
24
  if data.is_a?(Hash)
11
25
  walk_hash(data) do |target|
@@ -3,5 +3,5 @@ class Jerakia
3
3
  #
4
4
  # This should be updated when a new gem is released and it is read from the gemspec file
5
5
  #
6
- VERSION = '2.4.0'.freeze
6
+ VERSION = '2.5.0'.freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jerakia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Dunn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-14 00:00:00.000000000 Z
11
+ date: 2018-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: diplomat
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2.0'
125
139
  description: Extendable and flexible data lookup system
126
140
  email:
127
141
  executables:
@@ -143,6 +157,7 @@ files:
143
157
  - lib/jerakia/cli/token.rb
144
158
  - lib/jerakia/config.rb
145
159
  - lib/jerakia/datasource.rb
160
+ - lib/jerakia/datasource/consul_kv.rb
146
161
  - lib/jerakia/datasource/dummy.rb
147
162
  - lib/jerakia/datasource/file.rb
148
163
  - lib/jerakia/datasource/file/json.rb
@@ -163,7 +178,9 @@ files:
163
178
  - lib/jerakia/policy.rb
164
179
  - lib/jerakia/request.rb
165
180
  - lib/jerakia/response.rb
181
+ - lib/jerakia/response/entry.rb
166
182
  - lib/jerakia/response/filter.rb
183
+ - lib/jerakia/response/filter/dig.rb
167
184
  - lib/jerakia/response/filter/encryption.rb
168
185
  - lib/jerakia/response/filter/strsub.rb
169
186
  - lib/jerakia/schema.rb