hieracles 0.2.2 → 0.3.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: a6b5269d88007785d1a82bc4ea5d9a6575206923
4
- data.tar.gz: 3771f9302b9061157874ab0bf715f6c1588525ef
3
+ metadata.gz: 576b1abbe8d06fcf61896855b5474ed2d549e277
4
+ data.tar.gz: 79022f2d38d33472e1e629724ebc4882c7718ba3
5
5
  SHA512:
6
- metadata.gz: e475ba6285c981327d5dd5a662bc8ed27d82606c3a78c383f5f2a9e0cbd8d85666bd8f3a2641ad0c2bd883f960ac7892fba3760d91d38e8e008f8d6f7aec7d4d
7
- data.tar.gz: 8f554bbede7cf6fb3dceca5cf6f18c62defd5ee89b1b20df4a9403014044713b53f931e0e38c85cebe03fa990f67b0ab0ac3c01e41291bced3b9eea89b229303
6
+ metadata.gz: fd35c1ac42aca8724d507904387fb8bbd9543977482bd47e12e8e6301ec09e31ad655521b25904cd99c155caa5bb1ad1799e4e2ee3e4008fdc76f5582eb01139
7
+ data.tar.gz: 8a0528fd874dc417140713ac28858f131f0d858a843e4df1d07861934e7ac57d18061201ba360876333f986457be88f1365c94562d50b5d50331162b77cedc81
data/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
1
  Hieracles Changelog
2
2
  =======================
3
3
 
4
+ ### 0.3.0 - 2015-12-16
5
+ - added json output as an option to ppdb
6
+ - added some more ppdb commands
7
+ - ppdb resources <queries>
8
+ - ppdb same
9
+ - ppdb factnames
10
+ - updated manpage for ppdb with proper documentation
11
+ - prepare a queries transformation class to
12
+ match puppetdb weird query language with a more human one
13
+ - updated ppdb zsh completion
14
+
4
15
  ### 0.2.2 - 2015-12-11
5
16
  - remove support for ruby 1.9.3
6
17
  because of the mime-type gem
data/bin/ppdb CHANGED
@@ -12,31 +12,40 @@ if opt.options.has_key? :version
12
12
  exit(0)
13
13
  end
14
14
 
15
- unless opt.payload[1]
15
+ unless opt.payload[0]
16
16
  puts Hieracles::Options::Ppdb.usage
17
17
  exit(1)
18
18
  end
19
19
 
20
- command = "#{opt.payload[0]}_#{opt.payload[1]}"
21
- args = opt.payload[2..-1] || []
20
+ endpoint = opt.payload[0]
22
21
 
22
+ if Hieracles::Puppetdb::Request.method_defined? endpoint
23
+ command = endpoint
24
+ args = opt.payload[1..-1] || []
25
+ elsif Hieracles::Puppetdb::Request.method_defined? "#{opt.payload[0]}_#{opt.payload[1]}"
26
+ command = "#{opt.payload[0]}_#{opt.payload[1]}"
27
+ args = opt.payload[2..-1] || []
28
+ else
29
+ puts "*** Unknown command: #{command}"
30
+ puts Hieracles::Options::Ppdb.usage
31
+ exit(1)
32
+ end
33
+
23
34
  Hieracles::Config.load opt.options
24
35
 
25
- if Hieracles::Puppetdb::Request.method_defined? command
26
- request = Hieracles::Puppetdb::Request.new Hieracles::Config.puppetdb
27
- meth = request.method(command.to_sym)
28
- required = request.method(command.to_sym).parameters.select { |arg| arg[0] == :req }.map { |arg| arg[1] }
29
- if args.length < required.length
30
- args = required.join(', ')
31
- puts "*** The #{command} method requires arguments: #{args}"
32
- exit(1)
36
+ request = Hieracles::Puppetdb::Request.new Hieracles::Config.puppetdb
37
+ meth = request.method(command.to_sym)
38
+ required = request.method(command.to_sym).parameters.select { |arg| arg[0] == :req }.map { |arg| arg[1] }
39
+ if args.length < required.length
40
+ args = required.join(', ')
41
+ puts "*** The #{command} method requires arguments: #{args}"
42
+ exit(1)
43
+ else
44
+ if Hieracles::Config.format == 'Json'
45
+ format = Hieracles::Formats::Json.new(nil)
33
46
  else
34
47
  format = Hieracles::Formats::Console.new(nil)
35
- resp = meth.call(*args)
36
- puts format.build_list(resp.data, resp.notifications, [])
37
48
  end
38
- else
39
- puts "*** Unknown command: #{command}"
40
- puts Hieracles::Options::Ppdb.usage
41
- exit(1)
49
+ resp = meth.call(*args)
50
+ puts format.build_list(resp.data, resp.notifications, [])
42
51
  end
@@ -35,17 +35,23 @@ module Hieracles
35
35
 
36
36
  def build_list(hash, notifications, filter)
37
37
  back = ''
38
- back << build_notifications(notifications) if notifications
39
- if filter[0]
40
- hash.select! { |k, v| Regexp.new(filter[0]).match(k.to_s) }
41
- end
42
- length = max_key_length(hash) + 2
43
- title = format(COLORS[8], "%-#{length}s")
44
- hash.each do |k, v|
45
- if v.class.name == 'Hash' || v.class.name == 'Array'
46
- v = v.ai({ indent: 10, raw: true}).strip
38
+ if hash.class.name == 'Array'
39
+ hash.each do |v|
40
+ back << "#{v}\n"
41
+ end
42
+ else
43
+ back << build_notifications(notifications) if notifications
44
+ if filter[0]
45
+ hash.select! { |k, v| Regexp.new(filter[0]).match(k.to_s) }
46
+ end
47
+ length = max_key_length(hash) + 2
48
+ title = format(COLORS[8], "%-#{length}s")
49
+ hash.each do |k, v|
50
+ if v.class.name == 'Hash' || v.class.name == 'Array'
51
+ v = v.ai({ indent: 10, raw: true}).strip
52
+ end
53
+ back << format("#{title} %s\n", k, v)
47
54
  end
48
- back << format("#{title} %s\n", k, v)
49
55
  end
50
56
  back
51
57
  end
@@ -33,6 +33,13 @@ module Hieracles
33
33
  @node.params(false).merge(alerts).to_json
34
34
  end
35
35
 
36
+ def build_list(hash, notifications, filter)
37
+ {
38
+ 'notifications' => notifications,
39
+ 'payload' => hash
40
+ }.to_json
41
+ end
42
+
36
43
  private
37
44
 
38
45
  def alerts
@@ -9,6 +9,10 @@ module Hieracles
9
9
  version: {
10
10
  has_arg: false,
11
11
  aliases: ['v', 'version']
12
+ },
13
+ format: {
14
+ has_arg: true,
15
+ aliases: ['f', 'format']
12
16
  }
13
17
  }
14
18
  end
@@ -16,13 +20,20 @@ module Hieracles
16
20
  def self.usage
17
21
  return <<-END
18
22
 
19
- Usage: ppdb <endpoint> <command> [extra_args]
23
+ Usage: ppdb <command> [extra_args]
20
24
 
21
25
  Available commands:
22
26
  node info <fqdn>
23
27
  node facts <fqdn>
24
28
  node resources <fqdn>
25
-
29
+ facts <name> <value>
30
+ same <name> <fqdn>
31
+ factnames
32
+ res[ources] <query>
33
+ query following the form:
34
+ type=sometype title=what
35
+ type=sometype or type=another
36
+ type~someregexp type!~excluded
26
37
  END
27
38
  end
28
39
 
@@ -24,7 +24,7 @@ module Hieracles
24
24
  end
25
25
  end
26
26
 
27
- def request(endpoint, method = 'get', query = nil, opts = {})
27
+ def request(endpoint, query = nil, method = 'get', opts = {})
28
28
  ret = send("#{method}_request".to_sym, endpoint, query, opts)
29
29
  if ret.code.to_s() =~ /^[4|5]/ or ret.parsed_response.length < 1
30
30
  notifications = [ Hieracles::Notification.new('puppetdb', 'No match.', 'error') ]
@@ -34,7 +34,6 @@ module Hieracles
34
34
  if total.nil?
35
35
  total = ret.parsed_response.length
36
36
  end
37
-
38
37
  Response.new(ret.parsed_response, total)
39
38
  end
40
39
  end
@@ -51,7 +50,7 @@ module Hieracles
51
50
  filtered_opts[k.to_s.sub("_", "-")] = v
52
51
  end
53
52
  end
54
- puts path ; puts filtered_opts ; exit(0)
53
+ #puts path ; puts filtered_opts ; exit(0)
55
54
  self.class.get(path, query: filtered_opts)
56
55
  else
57
56
  self.class.get(path)
@@ -2,78 +2,67 @@ module Hieracles
2
2
  module Puppetdb
3
3
  class Query
4
4
 
5
+ attr_reader :elements
6
+
5
7
  def initialize(elements)
6
8
  @elements = parse(elements)
7
9
  end
8
10
 
9
11
  def parse(elements)
10
- items = []
11
- index = 0
12
- if elements.length > 1
13
- elements.each do |e|
14
- puts items.inspect
15
- if e == 'or'
16
- index++
17
- continue
18
- end
19
- if /(.*)(>|<|=|!=|~)(.*)/.match e
20
- items[index] ||= []
21
- items[index] << [$2, $1, $3]
22
- end
23
- end
24
- else
25
- if /(.*)(>|<|=|!=|~)(.*)/.match elements[0]
26
- items = [$2, $1, $3]
27
- end
12
+ if number_or(elements) > 0
13
+ elements = build_or(elements)
28
14
  end
29
- items
15
+ build_and elements
30
16
  end
31
17
 
32
- def output
33
- back = []
34
- if @elements.length > 1
35
- back << 'or'
36
- @elements.each do |e|
37
- back << build_and(e)
38
- end
39
- else
40
- @elements.each do |e|
41
- back << build_and(e)
18
+ def build_and(arrays)
19
+ back = arrays.reduce([]) do |a, v|
20
+ if v.class.name == 'Array'
21
+ if v.length > 1
22
+ a << ['and'] + v.map { |e| expression(e) }
23
+ else
24
+ e = expression(v[0])
25
+ a << e if e
26
+ end
27
+ elsif v == 'or'
28
+ a << 'or'
29
+ else
30
+ e = expression(v)
31
+ a << e if e
42
32
  end
33
+ a
34
+ end
35
+ if back.length == 1 and back[0].class.name == 'Array'
36
+ back = back[0]
37
+ elsif back[0].class.name == 'Array' and back.length > 1
38
+ back.unshift('and')
43
39
  end
44
40
  back
45
41
  end
46
42
 
47
- def build_and(arrays)
48
- if arrays.length > 1
49
- ['and', arrays]
50
- else
51
- arrays
43
+ def build_or(arrays)
44
+ back = ['or']
45
+ (0..number_or(arrays)-1).each do |a|
46
+ back << arrays.slice!(0..arrays.index('or')-1)
47
+ arrays.shift
52
48
  end
49
+ back << arrays
53
50
  end
54
51
 
55
- def defined?
56
- @elements.count > 0
57
- end
58
-
59
- def match(item)
60
- @elements.each do |e|
61
- matched = false
62
- e.each do |a|
63
- case a[0]
64
- when '='
65
-
66
- when '!='
67
- when '<'
68
- when '>'
69
- when '!'
70
- else
71
- end
52
+ def expression(e)
53
+ if /([^!]*)(!)?(>|<|=|~)(.*)/.match e
54
+ if $2
55
+ ['not', [$3, $1, $4]]
56
+ else
57
+ [$3, $1, $4]
72
58
  end
73
- return true if matched
74
59
  end
75
60
  end
76
61
 
62
+ def number_or(a)
63
+ a.select { |i| i == 'or' }.length
64
+ end
65
+
77
66
  end
78
67
  end
79
68
  end
@@ -27,17 +27,54 @@ module Hieracles
27
27
  def node_resources(fqdn, *args)
28
28
  resp = @client.request("nodes/#{fqdn}/resources")
29
29
  field = args.shift
30
- resp.data = resp.data.reduce({}) do |a, d|
31
- if !field || Regexp.new(field).match(d['title'])
32
- a[d['title']] = d
30
+ make_hashed resp
31
+ end
32
+ alias_method :node_res, :node_resources
33
+
34
+ def facts(label, value)
35
+ resp = @client.request("facts/#{label}/#{value}")
36
+ extract_names resp
37
+ end
38
+
39
+ def same(name, fqdn)
40
+ r = @client.request("nodes/#{fqdn}/facts/#{name}")
41
+ if r.data.length > 0
42
+ value = r.data[0]['value']
43
+ facts name, value
44
+ else
45
+ r
46
+ end
47
+ end
48
+
49
+ def factnames()
50
+ @client.request("fact-names")
51
+ end
52
+
53
+ def resources(*args)
54
+ query = Query.new args
55
+ make_hashed @client.request("resources", query.elements)
56
+ end
57
+ alias_method :res, :resources
58
+
59
+ private
60
+
61
+ def extract_names(resp, label = 'certname')
62
+ resp.data = resp.data.reduce([]) do |a, d|
63
+ a << d[label]
64
+ a
65
+ end.sort
66
+ resp
67
+ end
68
+
69
+ def make_hashed(resp, label = 'title', filter = nil)
70
+ resp.data = resp.data.reduce({}) do |a, d|
71
+ if !filter || Regexp.new(filter).match(d[label])
72
+ a[d[label]] = d
33
73
  end
34
74
  a
35
75
  end
36
76
  resp
37
77
  end
38
- alias_method :node_res, :node_resources
39
-
40
-
41
78
 
42
79
  end
43
80
  end
data/ppdb.1 CHANGED
@@ -4,7 +4,6 @@
4
4
  ppdb \- Command line tool to query puppetdb
5
5
  .SH SYNOPSIS
6
6
  .B ppdb
7
- .I object
8
7
  .I command
9
8
  .B [
10
9
  .I options
@@ -29,17 +28,11 @@ of the PuppetDB API.
29
28
  Ref http://docs.puppetlabs.com/puppetdb/2.3/api/
30
29
  .PP
31
30
  .B ppdb
32
- takes at minimum 2 arguments, an object (or endpoint)
33
- and a subcommand, plus extra parameters depending the subcommand.
34
- .PP
35
- The object is like the endpoint in PuppetDB API, but we extend it
36
- to a different list of possible objects:
37
-
38
- .IP node 10
39
- Uses the nodes endpoint. It accepts the subcommands:
40
- .RS
31
+ takes a command, plus extra parameters depending the command.
41
32
 
42
- .IP info 10
33
+ .TP
34
+ .PD 0
35
+ .B node info \fR<fqdn>
43
36
  will display the equivalent of
44
37
  .I "GET /v3/nodes/<NODE>"
45
38
  and takes the node
@@ -60,7 +53,9 @@ in their label.
60
53
  .RE
61
54
  .RE
62
55
 
63
- .IP facts 10
56
+ .TP
57
+ .PD 0
58
+ .B node facts \fR<fqdn>
64
59
  will display the equivalent of
65
60
  .I "GET /v3/nodes/<NODE>/facts"
66
61
  and takes the node
@@ -82,7 +77,9 @@ in their label.
82
77
  .RE
83
78
  .RE
84
79
 
85
- .IP resources 10
80
+ .TP
81
+ .PD 0
82
+ .B node resources \fR<fqdn>
86
83
  will display the equivalent of
87
84
  .I "GET /v3/nodes/<NODE>/resources"
88
85
  and takes the node
@@ -108,6 +105,65 @@ in their label.
108
105
  .RE
109
106
  .RE
110
107
 
108
+ .RE
109
+
110
+ .TP
111
+ .PD 0
112
+ .B facts <name> <value>
113
+ will list all fqdn (aka. certnames) of the nodes having the <name>
114
+ fact set to <value>.
115
+ .RS
116
+ eq. ppdb facts puppet_environment dev
117
+ .RE
118
+
119
+ .TP
120
+ .PD 0
121
+ .B same <name> <fqdn>
122
+ will list all the fqdn having the same value for the fact <name> as
123
+ <fqdn> has.
124
+ .RS
125
+ eq. ppdb same farm node32.example.com
126
+ .RE
127
+
128
+ .TP
129
+ .PD 0
130
+ .B resources <queries>
131
+ .TP
132
+ .PD
133
+ .B res <queries>
134
+ will list the resources matching a given set of queries.
135
+ Queries are a combination of statements, with a label, an operator
136
+ and a value. You can use
137
+ .I or
138
+ to separate one or several statements. If there is no
139
+ .I or
140
+ indicated, the statements follow an
141
+ .I and
142
+ logic. All statements that don't contain an operator or match the
143
+ .I or
144
+ keyword are purely ignored (which makes possible to use the
145
+ .I and
146
+ keyword for mental stability purpose).
147
+
148
+ .RS
149
+ Operators can be >, <, =, ~ and can be prefixed by a ! to negate them.
150
+ .RS
151
+ eq. ppdb res type=Nagios_ghost and tag~api
152
+ .RE
153
+ .RS
154
+ eq. ppdb res tag~api title!~dev
155
+ .RE
156
+ .RS
157
+ eq. ppdb res tag~api or certname~api or title~api
158
+ .RE
159
+ .RE
160
+
161
+ .TP
162
+ .PD 0
163
+ .B factnames
164
+ will list all the factnames puppetdb knows about.
165
+ This may be a long list.
166
+
111
167
  .SH OPTIONS
112
168
 
113
169
  .TP
@@ -118,6 +174,15 @@ in their label.
118
174
  .B \-\-version
119
175
  outputs version.
120
176
 
177
+ .TP
178
+ .PD 0
179
+ .B \-f \fRformat
180
+ .TP
181
+ .PD
182
+ .B \-\-format \fRformat
183
+ outputs in the selected format. For now only the json format
184
+ is available as an alternative to the default console format.
185
+
121
186
 
122
187
  .SH FILES
123
188
  .I ~/.config/hieracles/config.yaml
@@ -26,7 +26,7 @@ describe Hieracles::Puppetdb::Client do
26
26
  describe '.request' do
27
27
  context 'with a GET request' do
28
28
  let(:client) { Hieracles::Puppetdb::Client.new Hash.new }
29
- let(:request) { client.request('endpoint', 'get')}
29
+ let(:request) { client.request('endpoint')}
30
30
  let(:response) { Hieracles::Puppetdb::Response.new(Hash.new, 0, Array.new) }
31
31
  before {
32
32
  resp = double
@@ -49,7 +49,7 @@ describe Hieracles::Puppetdb::Client do
49
49
  describe '.get_request' do
50
50
  let(:client) { Hieracles::Puppetdb::Client.new Hash.new }
51
51
  context 'without query' do
52
- let(:request) { client.request('endpoint', 'get')}
52
+ let(:request) { client.request('endpoint')}
53
53
  before {
54
54
  allow(client.class).
55
55
  to receive(:get).
@@ -2,18 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe Hieracles::Puppetdb::Query do
4
4
 
5
- describe '.new' do
6
- let(:elements) { [ 'something=value' ] }
7
- let(:query) { Hieracles::Puppetdb::Query.new elements }
8
- before {
9
- allow(query).
10
- to receive(:parse).
11
- with(elements).
12
- and_return(['=', 'something', 'value'])
13
- }
14
- it { expect(query.instance_variable_get(:@elements)).to eq ['=', 'something', 'value'] }
15
- end
16
-
17
5
  describe '.parse' do
18
6
  context 'with a single argument not matching an assignment' do
19
7
  let(:elements) { [ 'anything' ] }
@@ -29,11 +17,91 @@ describe Hieracles::Puppetdb::Query do
29
17
  end
30
18
  context 'with 2 arguments matching an assignment' do
31
19
  let(:elements) { [ 'something=value', 'another=else' ] }
32
- let(:expected) { [['=', 'something', 'value'], ['=', 'another', 'else']] }
20
+ let(:expected) { ['and', ['=', 'something', 'value'], ['=', 'another', 'else']] }
21
+ let(:query) { Hieracles::Puppetdb::Query.new elements }
22
+ it { expect(query.instance_variable_get(:@elements)).to eq expected }
23
+ end
24
+ context 'with 3 arguments but only 2 match assignment' do
25
+ let(:elements) { [ 'something=value', 'and', 'another=else' ] }
26
+ let(:expected) { ['and', ['=', 'something', 'value'], ['=', 'another', 'else']] }
27
+ let(:query) { Hieracles::Puppetdb::Query.new elements }
28
+ it { expect(query.instance_variable_get(:@elements)).to eq expected }
29
+ end
30
+ context 'with 2 arguments separated by a or' do
31
+ let(:elements) { [ 'something=value', 'or', 'another=else' ] }
32
+ let(:expected) { ['or', ['=', 'something', 'value'], ['=', 'another', 'else']] }
33
33
  let(:query) { Hieracles::Puppetdb::Query.new elements }
34
- #it { expect(query.instance_variable_get(:@elements)).to eq expected }
34
+ it { expect(query.instance_variable_get(:@elements)).to eq expected }
35
35
  end
36
+ context 'with 3 arguments including a or' do
37
+ let(:elements) { [ 'something=value', 'or', 'another=else', 'more=ever' ] }
38
+ let(:expected) {
39
+ [ 'or',
40
+ ['=', 'something', 'value'],
41
+ ['and', ['=', 'another', 'else'], ['=', 'more', 'ever']]
42
+ ]
43
+ }
44
+ let(:query) { Hieracles::Puppetdb::Query.new elements }
45
+ it { expect(query.instance_variable_get(:@elements)).to eq expected }
46
+ end
47
+ end
36
48
 
49
+ describe '.build_and' do
50
+ let(:query) { Hieracles::Puppetdb::Query.new [] }
51
+ context 'with no and' do
52
+ let(:array) { ["a=b"]}
53
+ let(:expected) { ['=', 'a', 'b'] }
54
+ it { expect(query.send(:build_and, array)).to eq expected }
55
+ end
56
+ context 'with a single and' do
57
+ let(:array) { ["a=b", "a=c"]}
58
+ let(:expected) { ['and', ['=', 'a', 'b'],['=', 'a', 'c']] }
59
+ it { expect(query.send(:build_and, array)).to eq expected }
60
+ end
61
+
62
+ end
63
+
64
+ describe '.build_or' do
65
+ let(:query) { Hieracles::Puppetdb::Query.new [] }
66
+ context 'with a single or' do
67
+ let(:array) { ["a=b", "or", "a=c"]}
68
+ let(:expected) { ['or', ['a=b'],['a=c']]}
69
+ it { expect(query.send(:build_or, array)).to eq expected }
70
+ end
71
+ context 'with a double or' do
72
+ let(:array) { ["a=b", "or", "a=c", "or", "a=d"]}
73
+ let(:expected) { ['or', ['a=b'],['a=c'],['a=d']]}
74
+ it { expect(query.send(:build_or, array)).to eq expected }
75
+ end
76
+ context 'with a double or and multiple ands' do
77
+ let(:array) { ["a=b", "a=x", "or", "a=c", "or", "a=d"]}
78
+ let(:expected) { ['or', ['a=b', 'a=x'],['a=c'],['a=d']]}
79
+ it { expect(query.send(:build_or, array)).to eq expected }
80
+ end
81
+ end
82
+
83
+ describe '.expression' do
84
+ let(:query) { Hieracles::Puppetdb::Query.new [] }
85
+ context 'with a = sign' do
86
+ let(:string) { 'a=b' }
87
+ let(:expected) { ['=', 'a', 'b']}
88
+ it { expect(query.send(:expression, string)).to eq expected }
89
+ end
90
+ context 'with a != sign' do
91
+ let(:string) { 'a!=b' }
92
+ let(:expected) { ['not', ['=', 'a', 'b']]}
93
+ it { expect(query.send(:expression, string)).to eq expected }
94
+ end
95
+ context 'with a ~ sign' do
96
+ let(:string) { 'a~b' }
97
+ let(:expected) { ['~', 'a', 'b']}
98
+ it { expect(query.send(:expression, string)).to eq expected }
99
+ end
100
+ context 'with a !~ sign' do
101
+ let(:string) { 'a!~b' }
102
+ let(:expected) { ['not', ['~', 'a', 'b']]}
103
+ it { expect(query.send(:expression, string)).to eq expected }
104
+ end
37
105
  end
38
106
 
39
107
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hieracles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mose
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-11 00:00:00.000000000 Z
11
+ date: 2015-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty