aix-errlog 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aix/errlog/entry.rb +33 -3
- data/lib/aix/errlog/errlog.rb +43 -140
- data/lib/aix/errlog/match.rb +133 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5294c01b19b7bd0a1977c511df790d5d002c34fa968c4c1ccc432d927f7406a
|
4
|
+
data.tar.gz: a7e9fe17605da84b4f4c0cc694c99886a3690859cbf52a37854a045e151a6e0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee963b63a3877ca69c5e180e7f20613ac41c0a9ba424cdda648e1ba9aefb089b4280d8b7212081ea9e74dfe3f792a7edd7bbd82dd2d7cfc80f69d46e5953c286
|
7
|
+
data.tar.gz: 6d34ac53693e129524de2ddeac04559e1ed8a33d0cc0c12b80090977e95316bf8d54b04e9e229fbdcb5c2541be7404c2f83dca0bf671ed141124042efba29eab
|
data/lib/aix/errlog/entry.rb
CHANGED
@@ -4,14 +4,21 @@ require 'aix/errlog/constants'
|
|
4
4
|
|
5
5
|
module AIX
|
6
6
|
module Errlog
|
7
|
+
PARSE_REGEX = /(?:^Detail Data$\n(.*?))?(?:^Symptom Data$\n(.*))?\z/m.freeze
|
8
|
+
|
7
9
|
##
|
8
10
|
# An errlog entry class. Used to parse the raw errlog_entry_t struct into a
|
9
11
|
# more useful Ruby object.
|
10
12
|
#
|
11
13
|
# You shouldn't need to invoke this class directly; it is generated by the
|
12
14
|
# Errlog#forward_each and Errlog#reverse_each.
|
15
|
+
#
|
16
|
+
# Unfortunately, the retreived detail and symptom fields aren't horribly
|
17
|
+
# useful, and IBM has presented no API for parsing these correctly, so the
|
18
|
+
# only canonical path to getting the correct detail and symptom data is
|
19
|
+
# through a call to the errpt command.
|
13
20
|
class Entry
|
14
|
-
attr_reader :magic, :sequence, :label, :timestamp, :crcid, :errdiag, :machineid, :nodeid, :class, :type, :resource, :rclass, :rtype, :vpd_ibm, :vpd_user, :in, :connwhere, :flags, :
|
21
|
+
attr_reader :magic, :sequence, :label, :timestamp, :crcid, :errdiag, :machineid, :nodeid, :class, :type, :resource, :rclass, :rtype, :vpd_ibm, :vpd_user, :in, :connwhere, :flags, :raw_detail, :raw_symptom, :dup_count, :dup_time1, :dup_time2, :wparid
|
15
22
|
|
16
23
|
def initialize(raw)
|
17
24
|
@magic = raw[:el_magic]
|
@@ -33,14 +40,37 @@ module AIX
|
|
33
40
|
@connwhere = raw[:el_connwhere].to_s.freeze
|
34
41
|
@flags = raw[:el_flags]
|
35
42
|
length = raw[:el_detail_length]
|
36
|
-
@
|
43
|
+
@raw_detail = raw[:el_detail_data].to_ptr.get_bytes(0, length).freeze
|
37
44
|
length = raw[:el_symptom_length]
|
38
|
-
@
|
45
|
+
@raw_symptom = raw[:el_symptom_data].to_ptr.get_bytes(0, length).freeze
|
39
46
|
@dup_count = raw[:el_errdup][:ed_dupcount]
|
40
47
|
@dup_time1 = Time.at(raw[:el_errdup][:ed_time1]).freeze
|
41
48
|
@dup_time2 = Time.at(raw[:el_errdup][:ed_time2]).freeze
|
42
49
|
@wparid = raw[:el_wparid].to_s.freeze
|
43
50
|
end
|
51
|
+
|
52
|
+
def errpt
|
53
|
+
@errpt ||= %x(errpt -al#{@sequence}).freeze
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_errpt
|
57
|
+
unless @parsed
|
58
|
+
@detail, @symptom = errpt.match(PARSE_REGEX).captures
|
59
|
+
@detail ||= ''.freeze
|
60
|
+
@symptom ||= ''.freeze
|
61
|
+
@detail.freeze
|
62
|
+
@symptom.freeze
|
63
|
+
@parsed = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
def detail
|
67
|
+
parse_errpt unless @parsed
|
68
|
+
@detail
|
69
|
+
end
|
70
|
+
def symptom
|
71
|
+
parse_errpt unless @parsed
|
72
|
+
@symptom
|
73
|
+
end
|
44
74
|
end
|
45
75
|
end
|
46
76
|
end
|
data/lib/aix/errlog/errlog.rb
CHANGED
@@ -30,11 +30,10 @@ module AIX
|
|
30
30
|
# operates as a cursor, so if you try to re-invoke one before it is
|
31
31
|
# finished, the cursor will get reset, and you'll get jumbled results).
|
32
32
|
# While one of these enumerators as active, trying to re-invoke one will
|
33
|
-
# raise an EnumeratorError.
|
33
|
+
# raise an Errors::EnumeratorError.
|
34
34
|
#
|
35
|
-
# If you need to do complex matching, use
|
36
|
-
#
|
37
|
-
# to how to create those.
|
35
|
+
# If you need to do complex matching, use #match or ::match to build a match
|
36
|
+
# expression using a DSL.
|
38
37
|
#
|
39
38
|
# A simple example, showing how to get a list of all labels of all log
|
40
39
|
# entries in forward order which contain the string 'KILL' in their label
|
@@ -47,19 +46,19 @@ module AIX
|
|
47
46
|
# require 'aix/errlog'
|
48
47
|
#
|
49
48
|
# AIX::Errlog.open do |log|
|
50
|
-
# log.forward_each(match:
|
51
|
-
#
|
49
|
+
# log.forward_each(match: log.match {
|
50
|
+
# label.include?('KILL') & (
|
52
51
|
# (
|
53
|
-
# (
|
54
|
-
# (
|
55
|
-
# (
|
52
|
+
# (sequence > 1000) &
|
53
|
+
# (timestamp >= DateTime.new(2017, 1, 1)) &
|
54
|
+
# (timestamp < DateTime.new(2017, 2, 1))
|
56
55
|
# ) | (
|
57
|
-
# (
|
58
|
-
# (
|
59
|
-
# (
|
56
|
+
# (sequence < 500) &
|
57
|
+
# (timestamp >= DateTime.new(2016, 12, 1)) &
|
58
|
+
# (timestamp < DateTime.new(2017, 1, 1))
|
60
59
|
# )
|
61
60
|
# )
|
62
|
-
# )
|
61
|
+
# }).map(&:label)
|
63
62
|
# end
|
64
63
|
#
|
65
64
|
# Certainly, that looks a little complex, but it is a bit more efficient
|
@@ -156,7 +155,7 @@ module AIX
|
|
156
155
|
# An active enumerator can not be nested within another active enumerator,
|
157
156
|
# including the block form of this. If you invoke any of the #each_
|
158
157
|
# methods while another has not finished and exited, you'll raise an
|
159
|
-
# EnumeratorError. You can create an enumerator of one within the other,
|
158
|
+
# Errors::EnumeratorError. You can create an enumerator of one within the other,
|
160
159
|
# as long as you don't activate it until the first one has exited.
|
161
160
|
#
|
162
161
|
# Warning: if the sequence does not exist (which is common when error logs
|
@@ -190,7 +189,7 @@ module AIX
|
|
190
189
|
# An active enumerator can not be nested within another active enumerator,
|
191
190
|
# including the block form of this. If you invoke any of the #each_
|
192
191
|
# methods while another has not finished and exited, you'll raise an
|
193
|
-
# EnumeratorError. You can create an enumerator of one within the other,
|
192
|
+
# Errors::EnumeratorError. You can create an enumerator of one within the other,
|
194
193
|
# as long as you don't activate it until the first one has exited.
|
195
194
|
#
|
196
195
|
# Warning: if the sequence does not exist (which is common when error logs
|
@@ -208,129 +207,33 @@ module AIX
|
|
208
207
|
end
|
209
208
|
|
210
209
|
##
|
211
|
-
#
|
212
|
-
|
213
|
-
|
214
|
-
Match.new(left: :sequence)
|
215
|
-
end
|
216
|
-
##
|
217
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
218
|
-
# label.
|
219
|
-
def match_label
|
220
|
-
Match.new(left: :label)
|
221
|
-
end
|
222
|
-
##
|
223
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
224
|
-
# timestamp.
|
225
|
-
def match_timestamp
|
226
|
-
Match.new(left: :timestamp)
|
227
|
-
end
|
228
|
-
##
|
229
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
230
|
-
# crcid.
|
231
|
-
def match_crcid
|
232
|
-
Match.new(left: :crcid)
|
233
|
-
end
|
234
|
-
##
|
235
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
236
|
-
# machineid.
|
237
|
-
def match_machineid
|
238
|
-
Match.new(left: :machineid)
|
239
|
-
end
|
240
|
-
##
|
241
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
242
|
-
# nodeid.
|
243
|
-
def match_nodeid
|
244
|
-
Match.new(left: :nodeid)
|
245
|
-
end
|
246
|
-
##
|
247
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
248
|
-
# class.
|
249
|
-
def match_class
|
250
|
-
Match.new(left: :class)
|
251
|
-
end
|
252
|
-
##
|
253
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
254
|
-
# type.
|
255
|
-
def match_type
|
256
|
-
Match.new(left: :type)
|
257
|
-
end
|
258
|
-
##
|
259
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
260
|
-
# resource.
|
261
|
-
def match_resource
|
262
|
-
Match.new(left: :resource)
|
263
|
-
end
|
264
|
-
##
|
265
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
266
|
-
# rclass.
|
267
|
-
def match_rclass
|
268
|
-
Match.new(left: :rclass)
|
269
|
-
end
|
270
|
-
##
|
271
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
272
|
-
# rtype.
|
273
|
-
def match_rtype
|
274
|
-
Match.new(left: :rtype)
|
275
|
-
end
|
276
|
-
##
|
277
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
278
|
-
# vpd_ibm.
|
279
|
-
def match_vpd_ibm
|
280
|
-
Match.new(left: :vpd_ibm)
|
281
|
-
end
|
282
|
-
##
|
283
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
284
|
-
# vpd_user.
|
285
|
-
def match_vpd_user
|
286
|
-
Match.new(left: :vpd_user)
|
287
|
-
end
|
288
|
-
##
|
289
|
-
# Match convenience function. Gets a Leaf match for comparing against in.
|
290
|
-
def match_in
|
291
|
-
Match.new(left: :in)
|
292
|
-
end
|
293
|
-
##
|
294
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
295
|
-
# connwhere.
|
296
|
-
def match_connwhere
|
297
|
-
Match.new(left: :connwhere)
|
298
|
-
end
|
299
|
-
##
|
300
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
301
|
-
# flag_err64.
|
302
|
-
def match_flag_err64
|
303
|
-
Match.new(left: :flag_err64)
|
304
|
-
end
|
305
|
-
##
|
306
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
307
|
-
# flag_errdup.
|
308
|
-
def match_flag_errdup
|
309
|
-
Match.new(left: :flag_errdup)
|
310
|
-
end
|
311
|
-
##
|
312
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
313
|
-
# detail_data.
|
314
|
-
def match_detail_data
|
315
|
-
Match.new(left: :detail_data)
|
316
|
-
end
|
317
|
-
##
|
318
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
319
|
-
# symptom_data.
|
320
|
-
def match_symptom_data
|
321
|
-
Match.new(left: :symptom_data)
|
322
|
-
end
|
323
|
-
##
|
324
|
-
# Match convenience function. Gets a Leaf match for comparing against
|
325
|
-
# errdiag.
|
326
|
-
def match_errdiag
|
327
|
-
Match.new(left: :errdiag)
|
210
|
+
# Calls ::match
|
211
|
+
def match(&block)
|
212
|
+
Errlog.match(&block)
|
328
213
|
end
|
214
|
+
|
329
215
|
##
|
330
|
-
#
|
331
|
-
#
|
332
|
-
|
333
|
-
|
216
|
+
# Used to build a match expression using a DSL. This simply calls
|
217
|
+
# instance_eval on Match, so remember the semantics of block scope. If
|
218
|
+
# you have a local +sequence+ variable, for instance, you'll need to use
|
219
|
+
# an explicit self to escape that:
|
220
|
+
#
|
221
|
+
# [2] pry(main)> AIX::Errlog::Errlog.match { sequence }
|
222
|
+
# => #<AIX::Errlog::Match:0xeb32a4df @left=:sequence, @operator=nil, @right=nil>
|
223
|
+
# [3] pry(main)> sequence = 5
|
224
|
+
# => 5
|
225
|
+
# [4] pry(main)> AIX::Errlog::Errlog.match { sequence }
|
226
|
+
# => 5
|
227
|
+
# [5] pry(main)> AIX::Errlog::Errlog.match { self.sequence }
|
228
|
+
# => #<AIX::Errlog::Match:0xcb7d8c03 @left=:sequence, @operator=nil, @right=nil>
|
229
|
+
# [6] pry(main)> AIX::Errlog::Errlog.match { self.sequence > sequence }
|
230
|
+
# => #<AIX::Errlog::Match:0x7be0bbf5 @left=:sequence, @operator=:gt, @right=5>
|
231
|
+
#
|
232
|
+
# In any case, this function lets you use a block as a shortcut to call a
|
233
|
+
# bunch of public class methods on the Match class, in order to build
|
234
|
+
# complex match expressions, as shown in the summary of this class.
|
235
|
+
def self.match(&block)
|
236
|
+
Match.instance_eval(&block)
|
334
237
|
end
|
335
238
|
|
336
239
|
private
|
@@ -344,7 +247,7 @@ module AIX
|
|
344
247
|
return if status == :done
|
345
248
|
Errors.throw(status, "handle: #{@handle}, sequence: #{id}") unless status == :ok
|
346
249
|
|
347
|
-
Entry.new(entry)
|
250
|
+
Entry.new(entry)
|
348
251
|
end
|
349
252
|
|
350
253
|
##
|
@@ -356,7 +259,7 @@ module AIX
|
|
356
259
|
return if status == :done
|
357
260
|
Errors.throw(status, "handle: #{@handle}, match: #{match}") unless status == :ok
|
358
261
|
|
359
|
-
Entry.new(entry)
|
262
|
+
Entry.new(entry)
|
360
263
|
end
|
361
264
|
|
362
265
|
##
|
@@ -366,7 +269,7 @@ module AIX
|
|
366
269
|
status = Lib.errlog_find_next(@handle, entry)
|
367
270
|
return if status == :done
|
368
271
|
Errors.throw(status, "handle: #{@handle}") unless status == :ok
|
369
|
-
Entry.new(entry)
|
272
|
+
Entry.new(entry)
|
370
273
|
end
|
371
274
|
|
372
275
|
##
|
@@ -393,7 +296,7 @@ module AIX
|
|
393
296
|
# An active enumerator can not be nested within another active enumerator,
|
394
297
|
# including the block form of this. If you invoke any of the #each_
|
395
298
|
# methods while another has not finished and exited, you'll raise an
|
396
|
-
# EnumeratorError. You can create an enumerator of one within the other,
|
299
|
+
# Errors::EnumeratorError. You can create an enumerator of one within the other,
|
397
300
|
# as long as you don't activate it until the first one has exited.
|
398
301
|
#
|
399
302
|
# Warning: if the sequence does not exist (which is common when error logs
|
data/lib/aix/errlog/match.rb
CHANGED
@@ -9,8 +9,7 @@ module AIX
|
|
9
9
|
# A class that is useful for building errlog matchers.
|
10
10
|
#
|
11
11
|
# You usually won't need to access this class directly; you'll be able to
|
12
|
-
# create instances of it indirectly through the
|
13
|
-
# available in Errlog.
|
12
|
+
# create instances of it indirectly through the use of Errlog::match
|
14
13
|
#
|
15
14
|
# You can build field matchers using the methods on the errlog and standard
|
16
15
|
# logical operators, and there are standard conversions for certain things
|
@@ -18,18 +17,18 @@ module AIX
|
|
18
17
|
# entries only in January 2018 with +FOO+ in the label somewhere, you cold
|
19
18
|
# use a match like this with an Errlog instance.
|
20
19
|
#
|
21
|
-
#
|
22
|
-
# (
|
23
|
-
# (
|
24
|
-
#
|
25
|
-
#
|
20
|
+
# errlog.match {
|
21
|
+
# (timestamp >= DateTime.new(2018, 1, 1)) &
|
22
|
+
# (timestamp < DateTime.new(2018, 2, 1)) &
|
23
|
+
# label.include?('FOO')
|
24
|
+
# }
|
26
25
|
#
|
27
26
|
# It really is that easy. The rest of the magic is done for you behind the
|
28
27
|
# scenes, as long as you follow the rules and know how to make these matches
|
29
28
|
# in the C equivalent. Note that there must always be a Match on the left
|
30
29
|
# side of all comparisons, so something like
|
31
30
|
#
|
32
|
-
# DateTime.new(2018, 1, 1) <= errlog.
|
31
|
+
# DateTime.new(2018, 1, 1) <= errlog.match{timestamp}
|
33
32
|
#
|
34
33
|
# is not possible.
|
35
34
|
#
|
@@ -151,6 +150,132 @@ module AIX
|
|
151
150
|
operator: :not,
|
152
151
|
)
|
153
152
|
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
156
|
+
# sequence.
|
157
|
+
def self.sequence
|
158
|
+
new(left: :sequence)
|
159
|
+
end
|
160
|
+
##
|
161
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
162
|
+
# label.
|
163
|
+
def self.label
|
164
|
+
new(left: :label)
|
165
|
+
end
|
166
|
+
##
|
167
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
168
|
+
# timestamp.
|
169
|
+
def self.timestamp
|
170
|
+
new(left: :timestamp)
|
171
|
+
end
|
172
|
+
##
|
173
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
174
|
+
# crcid.
|
175
|
+
def self.crcid
|
176
|
+
new(left: :crcid)
|
177
|
+
end
|
178
|
+
##
|
179
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
180
|
+
# machineid.
|
181
|
+
def self.machineid
|
182
|
+
new(left: :machineid)
|
183
|
+
end
|
184
|
+
##
|
185
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
186
|
+
# nodeid.
|
187
|
+
def self.nodeid
|
188
|
+
new(left: :nodeid)
|
189
|
+
end
|
190
|
+
##
|
191
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
192
|
+
# class.
|
193
|
+
def self.class
|
194
|
+
new(left: :class)
|
195
|
+
end
|
196
|
+
##
|
197
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
198
|
+
# type.
|
199
|
+
def self.type
|
200
|
+
new(left: :type)
|
201
|
+
end
|
202
|
+
##
|
203
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
204
|
+
# resource.
|
205
|
+
def self.resource
|
206
|
+
new(left: :resource)
|
207
|
+
end
|
208
|
+
##
|
209
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
210
|
+
# rclass.
|
211
|
+
def self.rclass
|
212
|
+
new(left: :rclass)
|
213
|
+
end
|
214
|
+
##
|
215
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
216
|
+
# rtype.
|
217
|
+
def self.rtype
|
218
|
+
new(left: :rtype)
|
219
|
+
end
|
220
|
+
##
|
221
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
222
|
+
# vpd_ibm.
|
223
|
+
def self.vpd_ibm
|
224
|
+
new(left: :vpd_ibm)
|
225
|
+
end
|
226
|
+
##
|
227
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
228
|
+
# vpd_user.
|
229
|
+
def self.vpd_user
|
230
|
+
new(left: :vpd_user)
|
231
|
+
end
|
232
|
+
##
|
233
|
+
# Match convenience function. Gets a Leaf match for comparing against in.
|
234
|
+
def self.in
|
235
|
+
new(left: :in)
|
236
|
+
end
|
237
|
+
##
|
238
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
239
|
+
# connwhere.
|
240
|
+
def self.connwhere
|
241
|
+
new(left: :connwhere)
|
242
|
+
end
|
243
|
+
##
|
244
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
245
|
+
# flag_err64.
|
246
|
+
def self.flag_err64
|
247
|
+
new(left: :flag_err64)
|
248
|
+
end
|
249
|
+
##
|
250
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
251
|
+
# flag_errdup.
|
252
|
+
def self.flag_errdup
|
253
|
+
new(left: :flag_errdup)
|
254
|
+
end
|
255
|
+
##
|
256
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
257
|
+
# detail_data.
|
258
|
+
def self.detail_data
|
259
|
+
new(left: :detail_data)
|
260
|
+
end
|
261
|
+
##
|
262
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
263
|
+
# symptom_data.
|
264
|
+
def self.symptom_data
|
265
|
+
new(left: :symptom_data)
|
266
|
+
end
|
267
|
+
##
|
268
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
269
|
+
# errdiag.
|
270
|
+
def self.errdiag
|
271
|
+
new(left: :errdiag)
|
272
|
+
end
|
273
|
+
##
|
274
|
+
# Match convenience function. Gets a Leaf match for comparing against
|
275
|
+
# wparid.
|
276
|
+
def self.wparid
|
277
|
+
new(left: :wparid)
|
278
|
+
end
|
154
279
|
end
|
155
280
|
end
|
156
281
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aix-errlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taylor C. Richberger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|