wash 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/wash/entry.rb +345 -0
- data/lib/wash/method.rb +52 -0
- data/lib/wash/streamer.rb +24 -0
- data/lib/wash.rb +141 -0
- metadata +47 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f0c229c4c749d26525382c4c26255044308b763335b4d2d6d2ea8aa3495fb9b9
|
4
|
+
data.tar.gz: f60ba8213ec625de9ee9961db8bccc92c85af8a30fd916056d69809446fb1987
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 95ffb1adfde494f374e7dc76d02b68074ed120505e224da3667a80f9f15cc188b72fa158094a0f6dd755116a6964b396c8a65b0c67888ca4bc50603cd9f9f629
|
7
|
+
data.tar.gz: 6cd43ebb0dd830c14e8bf079e33dedd65fc2c25ccb6488b00073e5cf783f9b178f52992a04ae3773ed873fb5743a31774a9a2c1e642f6ae2a95190d53749ff96
|
data/lib/wash/entry.rb
ADDED
@@ -0,0 +1,345 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wash
|
4
|
+
# Entry represents a common base class for Wash entries. All plugin entries
|
5
|
+
# should extend this class.
|
6
|
+
class Entry
|
7
|
+
class << self
|
8
|
+
# attributes is a class-level tag specifying all the attributes that
|
9
|
+
# make sense for instances of this specific kind of entry. It will
|
10
|
+
# pass the specified attributes along to attr_accessor so that instances
|
11
|
+
# can set their values. For example, something like
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# class Foo
|
15
|
+
# # Instances of Foo will be able to set the @mtime and @meta fields
|
16
|
+
# attributes :mtime, :meta
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# @param [Symbol] attr An attribute that will be set
|
20
|
+
# @param [Symbol] attrs More attributes that will be set
|
21
|
+
def attributes(attr, *attrs)
|
22
|
+
@attributes ||= []
|
23
|
+
@attributes += set_fields(attr, *attrs)
|
24
|
+
end
|
25
|
+
|
26
|
+
# slash_replacer is a class-level tag that specifies the slash replacer.
|
27
|
+
# It should only be used if there is a chance that instances of the given
|
28
|
+
# class can contain a "#" in their names. Otherwise, slash_replacer should
|
29
|
+
# be ignored.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# class Foo
|
33
|
+
# # Tell Wash to replace all "/"es with ":" in the given Foo instance's
|
34
|
+
# # name
|
35
|
+
# slash_replacer ":"
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @param [String] char The slash replacer
|
39
|
+
def slash_replacer(char)
|
40
|
+
@slash_replacer = char
|
41
|
+
end
|
42
|
+
|
43
|
+
# state is a class-level tag that specifies the minimum state required
|
44
|
+
# to reconstruct all instances of this specific kind of entry. Each specified
|
45
|
+
# state field will be passed along to attr_accessor so that instances can
|
46
|
+
# get/set their values.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# class Foo
|
50
|
+
# # Indicates that api_key is the minimum state required to reconstruct
|
51
|
+
# # instances of Foo. The gem will serialize the api_key as part of each
|
52
|
+
# # instance's state key when passing them along to Wash. If Wash invokes
|
53
|
+
# # a method on a specific instance, then Wash.run will restore the api_key
|
54
|
+
# # prior to invoking the method (so all methods are free to directly reference
|
55
|
+
# # the @api_key field). Thus, plugin authors do not have to manage their entries'
|
56
|
+
# # states; the gem will do it for them via the state tag.
|
57
|
+
# state :api_key
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# Note that Wash.run uses {Class#allocate} when it reconstructs the entries, so
|
61
|
+
# it does not call the initialize method.
|
62
|
+
def state(field, *fields)
|
63
|
+
@state ||= []
|
64
|
+
@state += set_fields(field, *fields)
|
65
|
+
end
|
66
|
+
|
67
|
+
# label is a class-level tag specifying the entry's label. It is a helper for
|
68
|
+
# Entry schemas.
|
69
|
+
#
|
70
|
+
# @param lbl The label.
|
71
|
+
def label(lbl)
|
72
|
+
@label = lbl
|
73
|
+
end
|
74
|
+
|
75
|
+
# is_singleton is a class-level tag indicating that the given Entry's a singleton.
|
76
|
+
# It is a helper for Entry schemas.
|
77
|
+
#
|
78
|
+
# Note that if an Entry has the is_singleton tag and its name is not filled-in
|
79
|
+
# when that Entry is listed, then the Entry's name will be set to the specified
|
80
|
+
# label. This means that plugin authors do not have to set singleton entries'
|
81
|
+
# names, and it also enforces the convention that singleton entries' labels should
|
82
|
+
# match their names.
|
83
|
+
#
|
84
|
+
# @example
|
85
|
+
# class Foo
|
86
|
+
# label 'foo'
|
87
|
+
# # If Foo's instance does not set @name, then the gem will set @name to 'foo'
|
88
|
+
# is_singleton
|
89
|
+
# end
|
90
|
+
def is_singleton
|
91
|
+
@singleton = true
|
92
|
+
end
|
93
|
+
|
94
|
+
# meta_attribute_schema sets the meta attribute's schema to schema. It is a helper
|
95
|
+
# for Entry schemas.
|
96
|
+
#
|
97
|
+
# @param schema A hash containing the meta attribute's JSON schema
|
98
|
+
def meta_attribute_schema(schema)
|
99
|
+
@meta_attribute_schema = schema
|
100
|
+
end
|
101
|
+
|
102
|
+
# metadata_schema sets the metadata schema to schema. It is a helper for Entry schemas.
|
103
|
+
#
|
104
|
+
# @param schema A hash containing the metadata's JSON schema
|
105
|
+
def metadata_schema(schema)
|
106
|
+
@metadata_schema = schema
|
107
|
+
end
|
108
|
+
|
109
|
+
# parent_of indicates that this kind of Entry is the parent of the given child classes
|
110
|
+
# (i.e. child entries). It is a helper for Entry schemas.
|
111
|
+
#
|
112
|
+
# @example
|
113
|
+
# class Foo
|
114
|
+
# # This indicates that Foo#list will return instances of Bar and Baz. Note
|
115
|
+
# # that both direct class constants (Bar) and strings ('Baz') are valid
|
116
|
+
# # input. The latter's useful when the child class is loaded after the
|
117
|
+
# # parent.
|
118
|
+
# parent_of Bar, 'Baz'
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# @param [Wash::Entry] child_klass A child class object.
|
122
|
+
# @param [Wash::Entry] child_klasses More child class objects.
|
123
|
+
def parent_of(child_klass, *child_klasses)
|
124
|
+
@child_klasses ||= []
|
125
|
+
@child_klasses += [child_klass] + child_klasses
|
126
|
+
end
|
127
|
+
|
128
|
+
# children returns this Entry's child classes. It is a helper for Entry schemas, and
|
129
|
+
# is useful for DRY'ing up schema code when one kind of Entry's children matches another
|
130
|
+
# kind of Entry's children.
|
131
|
+
#
|
132
|
+
# @example
|
133
|
+
# class VolumeDir
|
134
|
+
# parent_of 'VolumeDir', 'VolumeFile'
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# class Volume
|
138
|
+
# parent_of *VolumeDir.children
|
139
|
+
# end
|
140
|
+
def children
|
141
|
+
@child_klasses
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def schema(visited)
|
147
|
+
visited[type_id] = {
|
148
|
+
label: @label,
|
149
|
+
methods: methods,
|
150
|
+
singleton: @singleton,
|
151
|
+
meta_attribute_schema: @meta_attribute_schema,
|
152
|
+
metadata_schema: @metadata_schema,
|
153
|
+
}
|
154
|
+
unless @child_klasses
|
155
|
+
return
|
156
|
+
end
|
157
|
+
visited[type_id][:children] = @child_klasses
|
158
|
+
@child_klasses.each do |child_klass|
|
159
|
+
child_klass = const_get(child_klass)
|
160
|
+
if visited[child_klass.send(:type_id)]
|
161
|
+
next
|
162
|
+
end
|
163
|
+
child_klass.send(:schema, visited)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def methods
|
168
|
+
wash_methods = Method.instance_variable_get(:@methods)
|
169
|
+
methods = []
|
170
|
+
self.public_instance_methods.each do |method|
|
171
|
+
if wash_methods[method]
|
172
|
+
# Only include the Wash methods. This makes the script's output easier
|
173
|
+
# to read when debugging.
|
174
|
+
methods.push(method)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
unless Wash.send(:entry_schemas_enabled?)
|
178
|
+
# Don't include :schema if entry-schema support is not enabled. Otherwise,
|
179
|
+
# Wash will return an error since entry schemas are an "on/off" feature.
|
180
|
+
methods.delete(:schema)
|
181
|
+
end
|
182
|
+
methods
|
183
|
+
end
|
184
|
+
|
185
|
+
def type_id
|
186
|
+
self.name
|
187
|
+
end
|
188
|
+
|
189
|
+
def set_fields(field, *fields)
|
190
|
+
fields.unshift(field)
|
191
|
+
fields.each do |field|
|
192
|
+
attr_accessor field
|
193
|
+
end
|
194
|
+
fields
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# All entries have a name. Note that the name is always
|
199
|
+
# included in the entry's state hash.
|
200
|
+
attr_accessor :name
|
201
|
+
|
202
|
+
def to_json(*)
|
203
|
+
unless @name && @name.size > 0
|
204
|
+
unless singleton
|
205
|
+
raise "A nameless entry is being serialized. The entry is an instance of #{type_id}"
|
206
|
+
end
|
207
|
+
@name = label
|
208
|
+
end
|
209
|
+
|
210
|
+
hash = {
|
211
|
+
type_id: type_id,
|
212
|
+
name: @name,
|
213
|
+
}
|
214
|
+
|
215
|
+
# Include the methods
|
216
|
+
hash[:methods] = self.class.send(:methods).map do |method|
|
217
|
+
if prefetched_methods.include?(method)
|
218
|
+
[method, self.send(method)]
|
219
|
+
else
|
220
|
+
method
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Include the remaining keys. Note that these checks are here to
|
225
|
+
# ensure that we don't serialize empty keys. They're meant to save
|
226
|
+
# some space.
|
227
|
+
if attributes.size > 0 && (attributes_hash = to_hash(attributes))
|
228
|
+
hash[:attributes] = attributes_hash
|
229
|
+
end
|
230
|
+
if cache_ttls.size > 0
|
231
|
+
hash[:cache_ttls] = cache_ttls
|
232
|
+
end
|
233
|
+
if slash_replacer.size > 0
|
234
|
+
hash[:slash_replacer] = slash_replacer
|
235
|
+
end
|
236
|
+
hash[:state] = to_hash(state).merge(klass: type_id, name: @name).to_json
|
237
|
+
if Wash.send(:pretty_print?)
|
238
|
+
JSON.pretty_generate(hash)
|
239
|
+
else
|
240
|
+
JSON.generate(hash)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# type_id returns the entry's type ID, which is its fully-qualified class
|
245
|
+
# name.
|
246
|
+
def type_id
|
247
|
+
self.class.send(:type_id)
|
248
|
+
end
|
249
|
+
|
250
|
+
# prefetch indicates that the given methods should be prefetched. This means
|
251
|
+
# that the gem will invoke those methods on this particular entry instance and
|
252
|
+
# include their results when serializing that entry. Note that the methods are
|
253
|
+
# invoked during serialization.
|
254
|
+
#
|
255
|
+
# @example
|
256
|
+
# class Foo
|
257
|
+
# def initialize(content_size)
|
258
|
+
# if content_size < 10
|
259
|
+
# # content_size < 10, so tell the gem to invoke Foo#list and Foo#read
|
260
|
+
# # on this Foo instance during its serialization
|
261
|
+
# prefetch :list, :read
|
262
|
+
# end
|
263
|
+
# end
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# @param [Symbol] method A method that should be prefetched.
|
267
|
+
# @param [Symbol] methods More methods that should be prefetched.
|
268
|
+
def prefetch(method, *methods)
|
269
|
+
prefetched_methods.concat([method] + methods)
|
270
|
+
end
|
271
|
+
|
272
|
+
# cache_ttls sets the cache TTLs (time-to-live) of the given methods.
|
273
|
+
#
|
274
|
+
# @example
|
275
|
+
# class Foo
|
276
|
+
# def initialize(content_size)
|
277
|
+
# if content_size > 10000
|
278
|
+
# # content_size > 10000 so tell Wash to cache its read result for
|
279
|
+
# # 100 seconds
|
280
|
+
# cache_ttls read: 100
|
281
|
+
# end
|
282
|
+
# end
|
283
|
+
# end
|
284
|
+
#
|
285
|
+
# @param [Hash] ttls A hash of <method_name> => <method_ttl>
|
286
|
+
def cache_ttls(ttls = {})
|
287
|
+
@cache_ttls ||= {}
|
288
|
+
@cache_ttls = @cache_ttls.merge(ttls)
|
289
|
+
end
|
290
|
+
|
291
|
+
# schema returns the entry's schema. It should not be overridden.
|
292
|
+
def schema
|
293
|
+
schemaHash = {}
|
294
|
+
self.class.send(:schema, schemaHash)
|
295
|
+
schemaHash
|
296
|
+
end
|
297
|
+
|
298
|
+
private
|
299
|
+
|
300
|
+
def attributes
|
301
|
+
self.class.instance_variable_get(:@attributes) || []
|
302
|
+
end
|
303
|
+
|
304
|
+
def slash_replacer
|
305
|
+
self.class.instance_variable_get(:@slash_replacer) || ''
|
306
|
+
end
|
307
|
+
|
308
|
+
def state
|
309
|
+
self.class.instance_variable_get(:@state) || {}
|
310
|
+
end
|
311
|
+
|
312
|
+
def label
|
313
|
+
self.class.instance_variable_get(:@label)
|
314
|
+
end
|
315
|
+
|
316
|
+
def singleton
|
317
|
+
self.class.instance_variable_get(:@singleton)
|
318
|
+
end
|
319
|
+
|
320
|
+
def prefetched_methods
|
321
|
+
@prefetched_methods ||= []
|
322
|
+
end
|
323
|
+
|
324
|
+
def to_hash(fields)
|
325
|
+
field_hash = {}
|
326
|
+
fields.each do |field|
|
327
|
+
field = field.to_sym
|
328
|
+
if value = self.send(field)
|
329
|
+
field_hash[field] = self.send(field)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
field_hash
|
333
|
+
end
|
334
|
+
|
335
|
+
def restore_state(state)
|
336
|
+
state.each do |field, value|
|
337
|
+
accessor = "#{field}=".to_sym
|
338
|
+
unless self.respond_to?(accessor)
|
339
|
+
raise "#{field} is an invalid state value"
|
340
|
+
end
|
341
|
+
self.send(accessor, value)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
data/lib/wash/method.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wash
|
4
|
+
# @api private
|
5
|
+
module Method
|
6
|
+
def self.invoke(method, entry, *args)
|
7
|
+
method = method.to_sym
|
8
|
+
unless entry.respond_to?(method)
|
9
|
+
raise "Entry #{entry.name} (#{entry.type_id}) does not implement #{method}"
|
10
|
+
end
|
11
|
+
unless invocation = @methods[method]
|
12
|
+
raise "#{method} is not a supported Wash method"
|
13
|
+
end
|
14
|
+
invocation.call(entry, *args)
|
15
|
+
end
|
16
|
+
private_class_method :invoke
|
17
|
+
|
18
|
+
def self.method(name, &block)
|
19
|
+
name = name.to_sym
|
20
|
+
unless block
|
21
|
+
block = lambda do |entry, *args|
|
22
|
+
result = entry.send(name, *args)
|
23
|
+
Wash.send(:print_json, result)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@methods ||= {}
|
27
|
+
@methods[name] = block
|
28
|
+
end
|
29
|
+
private_class_method :method
|
30
|
+
|
31
|
+
method(:list)
|
32
|
+
method(:read)
|
33
|
+
method(:metadata)
|
34
|
+
method(:schema)
|
35
|
+
|
36
|
+
method(:exec) do |entry, *args|
|
37
|
+
opts, cmd, args = Wash.send(:parse_json, args[0]), args[1], args[2..-1]
|
38
|
+
if opts[:stdin]
|
39
|
+
opts[:stdin] = STDIN
|
40
|
+
else
|
41
|
+
opts[:stdin] = nil
|
42
|
+
end
|
43
|
+
ec = entry.exec(cmd, args, opts)
|
44
|
+
exit ec
|
45
|
+
end
|
46
|
+
|
47
|
+
method(:stream) do |entry, _|
|
48
|
+
entry.stream
|
49
|
+
raise "stream should never return"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wash
|
4
|
+
# Streamer is a class meant to be used by implementations of Wash::Entry#stream.
|
5
|
+
class Streamer
|
6
|
+
def initialize
|
7
|
+
@first_chunk = true
|
8
|
+
end
|
9
|
+
|
10
|
+
# write writes the given chunk to STDOUT then flushes it to ensure that Wash
|
11
|
+
# receives the data. If the chunk is the first chunk that's written, then
|
12
|
+
# write will print the "200" header prior to writing the chunk.
|
13
|
+
#
|
14
|
+
# @param chunk The chunk to be written
|
15
|
+
def write(chunk)
|
16
|
+
if @first_chunk
|
17
|
+
puts("200")
|
18
|
+
@first_chunk = false
|
19
|
+
end
|
20
|
+
print(chunk)
|
21
|
+
STDOUT.flush
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/wash.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Wash
|
6
|
+
# pretty_print enables pretty printing of methods that produce
|
7
|
+
# JSON output. It is a useful debugging tool.
|
8
|
+
def self.pretty_print
|
9
|
+
@pretty_print = true
|
10
|
+
end
|
11
|
+
|
12
|
+
# enable_entry_schemas enables {Entry schema}[https://puppetlabs.github.io/wash/docs/#entry-schemas]
|
13
|
+
# support. See {Wash::Entry}'s documentation for more details on
|
14
|
+
# the available Entry schema helpers.
|
15
|
+
def self.enable_entry_schemas
|
16
|
+
@entry_schemas_enabled = true
|
17
|
+
end
|
18
|
+
|
19
|
+
# prefetch_entry_schemas enables schema-prefetching. This option
|
20
|
+
# should be enabled once external plugin development's finished.
|
21
|
+
# If the external plugin is not using Entry schemas, then this
|
22
|
+
# option can be ignored.
|
23
|
+
def self.prefetch_entry_schemas
|
24
|
+
@prefetch_entry_schemas = true
|
25
|
+
end
|
26
|
+
|
27
|
+
# on_sigterm will execute the provided block when the plugin script
|
28
|
+
# receives a SIGTERM/SIGINT signal. It is useful for handling
|
29
|
+
# plugin-specific cleanup like dangling processes, files, etc.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# class Foo
|
33
|
+
# # ...
|
34
|
+
# def stream
|
35
|
+
# # ...
|
36
|
+
# Wash.on_sigterm do
|
37
|
+
# # Kill any orphaned processes/files
|
38
|
+
# end
|
39
|
+
# # ...
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
def self.on_sigterm(&block)
|
43
|
+
sigterm_handlers << block
|
44
|
+
end
|
45
|
+
|
46
|
+
# run is the plugin script's run function. All plugin scripts using
|
47
|
+
# this gem should invoke this function once they've specified the
|
48
|
+
# desired configuration options (e.g. like pretty_print).
|
49
|
+
#
|
50
|
+
# @param [Wash::Entry] root_klass The plugin root's class object
|
51
|
+
#
|
52
|
+
# @param [Array<String>] argv The plugin script's arguments (usually ARGV).
|
53
|
+
def self.run(root_klass, argv)
|
54
|
+
Signal.trap('INT') do
|
55
|
+
handle_sigterm
|
56
|
+
exit 130
|
57
|
+
end
|
58
|
+
Signal.trap('TERM') do
|
59
|
+
handle_sigterm
|
60
|
+
exit 143
|
61
|
+
end
|
62
|
+
|
63
|
+
method, argv = next_arg(argv)
|
64
|
+
|
65
|
+
if method == "init"
|
66
|
+
config, argv = next_arg(argv)
|
67
|
+
root = root_klass.new
|
68
|
+
unless root.respond_to?(:init)
|
69
|
+
raise "Plugin root #{root.type_id} does not implement init."
|
70
|
+
end
|
71
|
+
config = parse_json(config)
|
72
|
+
root.init(config)
|
73
|
+
if @prefetch_entry_schemas
|
74
|
+
root.prefetch :schema
|
75
|
+
end
|
76
|
+
print_json(root)
|
77
|
+
return
|
78
|
+
end
|
79
|
+
|
80
|
+
_, argv = next_arg(argv)
|
81
|
+
|
82
|
+
state, argv = next_arg(argv)
|
83
|
+
state = parse_json(state)
|
84
|
+
klass = const_get(state.delete(:klass))
|
85
|
+
# Use klass#allocate instead of klass#new to give plugin authors
|
86
|
+
# more freedom in how they decide to setup their constructors
|
87
|
+
entry = klass.allocate
|
88
|
+
entry.send(:restore_state, state)
|
89
|
+
|
90
|
+
Method.send(:invoke, method, entry, *argv)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.next_arg(argv)
|
94
|
+
if argv.size < 1
|
95
|
+
raise "Invalid plugin-script invocation. See https://puppetlabs.github.io/wash/docs/external_plugins/ for details on what this should look like"
|
96
|
+
end
|
97
|
+
return argv[0], argv[1..-1]
|
98
|
+
end
|
99
|
+
private_class_method :next_arg
|
100
|
+
|
101
|
+
def self.handle_sigterm
|
102
|
+
sigterm_handlers.each do |handler|
|
103
|
+
handler.call
|
104
|
+
end
|
105
|
+
end
|
106
|
+
private_class_method :handle_sigterm
|
107
|
+
|
108
|
+
def self.pretty_print?
|
109
|
+
@pretty_print
|
110
|
+
end
|
111
|
+
private_class_method :pretty_print?
|
112
|
+
|
113
|
+
def self.entry_schemas_enabled?
|
114
|
+
@entry_schemas_enabled
|
115
|
+
end
|
116
|
+
private_class_method :entry_schemas_enabled?
|
117
|
+
|
118
|
+
def self.print_json(result)
|
119
|
+
if pretty_print?
|
120
|
+
result_json = JSON.pretty_generate(result)
|
121
|
+
else
|
122
|
+
result_json = JSON.generate(result)
|
123
|
+
end
|
124
|
+
puts(result_json)
|
125
|
+
end
|
126
|
+
private_class_method :print_json
|
127
|
+
|
128
|
+
def self.parse_json(json)
|
129
|
+
JSON.parse(json,:symbolize_names => true)
|
130
|
+
end
|
131
|
+
private_class_method :parse_json
|
132
|
+
|
133
|
+
def self.sigterm_handlers
|
134
|
+
@sigterm_handlers ||= []
|
135
|
+
end
|
136
|
+
private_class_method :sigterm_handlers
|
137
|
+
|
138
|
+
require 'wash/entry'
|
139
|
+
require 'wash/method'
|
140
|
+
require 'wash/streamer'
|
141
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Puppet
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-23 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A library for building Wash external plugins
|
14
|
+
email:
|
15
|
+
- puppet@puppet.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/wash.rb
|
21
|
+
- lib/wash/entry.rb
|
22
|
+
- lib/wash/method.rb
|
23
|
+
- lib/wash/streamer.rb
|
24
|
+
homepage: https://github.com/puppetlabs/wash-ruby
|
25
|
+
licenses:
|
26
|
+
- Apache-2.0
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '2.3'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubygems_version: 3.0.3
|
44
|
+
signing_key:
|
45
|
+
specification_version: 4
|
46
|
+
summary: A library for building Wash external plugins
|
47
|
+
test_files: []
|