leo_manager_client 0.4.8 → 0.4.9
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 +7 -0
- data/lib/leo_manager_client.rb +167 -108
- data/lib/leo_manager_models.rb +27 -8
- metadata +8 -10
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: af45abcecfde935e83f87353d7f9ade9f5699be3
|
4
|
+
data.tar.gz: 13f6d2867d69df2a906a5e3ea4aa8c89d3c41d55
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ad1f1eaae382faca27c4f08ef36f580956ebe00d624badd71c9b4788e05fd4d4e96ca8e292d4dece173fc908803a90c059b35108d25a0b01372eddd3f81a3e8f
|
7
|
+
data.tar.gz: 4fd20d6085984a0ea0691fa694778a31d63295bdf6d97c27eac67312d42e454b33a6c23f7a900ef827b68b017e3114184ae55faaf2ee6d24afd4e845443c97e4
|
data/lib/leo_manager_client.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# LeoFS Manager Client
|
4
4
|
#
|
5
|
-
# Copyright (c) 2012 Rakuten, Inc.
|
5
|
+
# Copyright (c) 2012-2014 Rakuten, Inc.
|
6
6
|
#
|
7
7
|
# This file is provided to you under the Apache License,
|
8
8
|
# Version 2.0 (the "License"); you may not use this file
|
@@ -26,7 +26,7 @@ require "time"
|
|
26
26
|
require_relative "leo_manager_models"
|
27
27
|
|
28
28
|
module LeoManager
|
29
|
-
VERSION = "0.4.
|
29
|
+
VERSION = "0.4.9"
|
30
30
|
|
31
31
|
class Client
|
32
32
|
CMD_VERSION = "version"
|
@@ -56,6 +56,7 @@ module LeoManager
|
|
56
56
|
CMD_ADD_BUCKET = "add-bucket %s %s"
|
57
57
|
CMD_DELETE_BUCKET = "delete-bucket %s %s"
|
58
58
|
CMD_GET_BUCKETS = "get-buckets"
|
59
|
+
CMD_UPDATE_ACL = "update-acl %s %s %s"
|
59
60
|
CMD_RECOVER_FILE = "recover file %s"
|
60
61
|
CMD_RECOVER_NODE = "recover node %s"
|
61
62
|
CMD_RECOVER_RING = "recover ring %s"
|
@@ -80,242 +81,292 @@ module LeoManager
|
|
80
81
|
attr_reader :current_server
|
81
82
|
|
82
83
|
# Retrieve LeoFS's version from LeoFS Manager
|
83
|
-
# Return
|
84
|
+
# ==== Return
|
84
85
|
# Version of LeoFS
|
85
86
|
def version
|
86
|
-
h =
|
87
|
+
h = call(CMD_VERSION)
|
87
88
|
return h[:result]
|
88
89
|
end
|
89
90
|
|
90
91
|
# Retrieve LeoFS's system status from LeoFS Manager
|
91
|
-
#
|
92
|
+
# ==== Args
|
93
|
+
# node :: Node
|
94
|
+
# ==== Return
|
92
95
|
# Status
|
93
96
|
def status(node=nil)
|
94
|
-
Status.new(
|
97
|
+
Status.new(call(CMD_STATUS % node))
|
95
98
|
end
|
96
99
|
|
97
100
|
# Login as specifies user
|
98
|
-
#
|
101
|
+
# ==== Args
|
102
|
+
# user_id :: user id
|
103
|
+
# password :: password
|
104
|
+
# ==== Return
|
99
105
|
# LoginInfo
|
100
106
|
def login(user_id, password)
|
101
|
-
LoginInfo.new(
|
107
|
+
LoginInfo.new(call(CMD_LOGIN % [user_id, password]))
|
102
108
|
end
|
103
109
|
|
104
110
|
# Launch LeoFS's storage cluster
|
105
|
-
# Return
|
106
|
-
#
|
111
|
+
# ==== Return
|
112
|
+
# Result
|
107
113
|
def start
|
108
|
-
|
109
|
-
nil
|
114
|
+
Result.new(call(CMD_START))
|
110
115
|
end
|
111
116
|
|
112
117
|
# Leave a node from the storage cluster
|
113
|
-
#
|
114
|
-
#
|
118
|
+
# ==== Args
|
119
|
+
# node :: a storage node
|
120
|
+
# ==== Return
|
121
|
+
# Result
|
115
122
|
def detach(node)
|
116
|
-
|
117
|
-
nil
|
123
|
+
Result.new(call(CMD_DETACH % node))
|
118
124
|
end
|
119
125
|
|
120
126
|
# Suspend a node in the storage cluster
|
121
|
-
#
|
122
|
-
#
|
127
|
+
# ==== Args
|
128
|
+
# node :: a storage node
|
129
|
+
# ==== Return
|
130
|
+
# Result
|
123
131
|
def suspend(node)
|
124
|
-
|
125
|
-
nil
|
132
|
+
Result.new(call(CMD_SUSPEND % node))
|
126
133
|
end
|
127
134
|
|
128
135
|
# Resume a node in the storage cluster
|
129
|
-
#
|
130
|
-
#
|
136
|
+
# ==== Args
|
137
|
+
# node :: a storage node
|
138
|
+
# ==== Return
|
139
|
+
# Result
|
131
140
|
def resume(node)
|
132
|
-
|
133
|
-
nil
|
141
|
+
Result.new(call(CMD_RESUME % node))
|
134
142
|
end
|
135
143
|
|
136
|
-
# Execute
|
137
|
-
# Return
|
138
|
-
#
|
144
|
+
# Execute relocate of objects - "rebalance" in the storage cluster
|
145
|
+
# ==== Return
|
146
|
+
# Result
|
139
147
|
def rebalance
|
140
|
-
|
141
|
-
nil
|
148
|
+
Result.new(call(CMD_REBALANCE))
|
142
149
|
end
|
143
150
|
|
144
151
|
# Retrieve assigned file information
|
145
|
-
#
|
152
|
+
# ==== Args
|
153
|
+
# path :: an object path
|
154
|
+
# ==== Return
|
146
155
|
# Array of AssignedFile
|
147
156
|
def whereis(path)
|
148
|
-
assigned_info =
|
157
|
+
assigned_info = call(CMD_WHEREIS % path)[:assigned_info]
|
149
158
|
assigned_info.map {|h| AssignedFile.new(h)}
|
150
159
|
end
|
151
160
|
|
152
161
|
# Retrieve storage status from the storage
|
153
|
-
#
|
162
|
+
# ==== Args
|
163
|
+
# node :: a storage node
|
164
|
+
# ==== Return
|
154
165
|
# StorageStat
|
155
166
|
def du(node)
|
156
|
-
StorageStat.new(
|
167
|
+
StorageStat.new(call(CMD_DU % node))
|
157
168
|
end
|
158
169
|
|
159
|
-
# Execute
|
160
|
-
#
|
161
|
-
#
|
170
|
+
# Execute data comaction in a storage node
|
171
|
+
# ==== Args
|
172
|
+
# node :: a storage node
|
173
|
+
# num_of_targets_or_all :: a number of targets - [integer | all]
|
174
|
+
# num_of_concurrents :: a number of concurrents
|
175
|
+
# ==== Return
|
176
|
+
# Result
|
162
177
|
def compact_start(node, num_of_targets_or_all, num_of_concurrents=nil)
|
163
178
|
case num_of_targets_or_all.to_s
|
164
179
|
when /^all$/i
|
165
|
-
|
180
|
+
Result.new(call(CMD_COMPACT_START_ALL % node))
|
166
181
|
else
|
167
182
|
num_of_concurrents = num_of_concurrents ? Integer(num_of_concurrents) : ""
|
168
|
-
|
183
|
+
Result.new(call(CMD_COMPACT_START % [node, Integer(num_of_targets_or_all), num_of_concurrents]))
|
169
184
|
end
|
170
|
-
nil
|
171
185
|
end
|
172
186
|
|
173
187
|
# Execute 'compact suspend'
|
174
|
-
#
|
175
|
-
#
|
188
|
+
# ==== Args
|
189
|
+
# node :: a storage node
|
190
|
+
# ==== Return
|
191
|
+
# Result
|
176
192
|
def compact_suspend(node)
|
177
|
-
|
178
|
-
nil
|
193
|
+
Result.new(call(CMD_COMPACT_SUSPEND % node))
|
179
194
|
end
|
180
195
|
|
181
196
|
# Execute 'compact suspend'
|
182
|
-
#
|
183
|
-
#
|
197
|
+
# ==== Args
|
198
|
+
# node :: a storage node
|
199
|
+
# ==== Return
|
200
|
+
# Result
|
184
201
|
def compact_resume(node)
|
185
|
-
|
186
|
-
nil
|
202
|
+
Result.new(call(CMD_COMPACT_RESUME % node))
|
187
203
|
end
|
188
204
|
|
189
205
|
# Execute 'compact status'
|
190
|
-
#
|
191
|
-
#
|
206
|
+
# ==== Args
|
207
|
+
# node :: a storage node
|
208
|
+
# ==== Return
|
209
|
+
# CompactionStatus
|
192
210
|
def compact_status(node)
|
193
|
-
compaction =
|
211
|
+
compaction = call(CMD_COMPACT_STATUS % node)[:compaction_status]
|
194
212
|
CompactionStatus.new(compaction)
|
195
213
|
end
|
196
214
|
|
197
|
-
# Purge a cache in gateways
|
198
|
-
#
|
199
|
-
#
|
215
|
+
# Purge a cache in the gateways
|
216
|
+
# ==== Args
|
217
|
+
# path :: an object path
|
218
|
+
# ==== Return
|
219
|
+
# Result
|
200
220
|
def purge(path)
|
201
|
-
|
202
|
-
nil
|
221
|
+
Result.new(call(CMD_PURGE % path))
|
203
222
|
end
|
204
223
|
|
205
|
-
# Generate credential
|
206
|
-
#
|
224
|
+
# Generate credential of a user
|
225
|
+
# ==== Args
|
226
|
+
# user_id :: user id
|
227
|
+
# password :: password
|
228
|
+
# ==== Return
|
207
229
|
# Credential
|
208
230
|
def create_user(user_id, password=nil)
|
209
|
-
Credential.new(
|
231
|
+
Credential.new(call(CMD_CRE_USER % [user_id, password]))
|
210
232
|
end
|
211
233
|
|
212
|
-
# Update user
|
213
|
-
#
|
214
|
-
#
|
234
|
+
# Update role of a user
|
235
|
+
# ==== Args
|
236
|
+
# user_id :: user id
|
237
|
+
# role :: operation role of a user
|
238
|
+
# ==== Return
|
239
|
+
# Result
|
215
240
|
def update_user_role(user_id, role)
|
216
241
|
role = role.to_sym if role.is_a? String
|
217
242
|
role = USER_ROLES[role] if role.is_a? Symbol
|
218
|
-
|
219
|
-
nil
|
243
|
+
Result.new(call(CMD_UPD_USER_ROLE % [user_id, role]))
|
220
244
|
end
|
221
245
|
|
222
|
-
# Update user
|
223
|
-
#
|
224
|
-
#
|
246
|
+
# Update password of a user
|
247
|
+
# ==== Args
|
248
|
+
# user_id :: user id
|
249
|
+
# new_password :: new password
|
250
|
+
# ==== Return
|
251
|
+
# Result
|
225
252
|
def update_user_password(user_id, new_password)
|
226
|
-
|
227
|
-
nil
|
253
|
+
Result.new(call(CMD_UPD_USER_PASS % [user_id, new_password]))
|
228
254
|
end
|
229
255
|
|
230
|
-
# Delete user
|
231
|
-
#
|
232
|
-
#
|
256
|
+
# Delete a user
|
257
|
+
# ==== Args
|
258
|
+
# user_id :: user id
|
259
|
+
# ==== Return
|
260
|
+
# Result
|
233
261
|
def delete_user(user_id)
|
234
|
-
|
235
|
-
nil
|
262
|
+
Result.new(call(CMD_DEL_USER % user_id))
|
236
263
|
end
|
237
264
|
|
265
|
+
# Retrieve a user
|
266
|
+
# ==== Return
|
267
|
+
# Map
|
238
268
|
def get_users
|
239
|
-
users =
|
269
|
+
users = call(CMD_GET_USERS)[:users]
|
240
270
|
users.map {|account| User.new(account) }
|
241
271
|
end
|
242
272
|
|
243
273
|
# Insert an endpoint in the system
|
244
|
-
#
|
245
|
-
#
|
274
|
+
# ==== Args
|
275
|
+
# endpoint :: an endpoint
|
276
|
+
# ==== Return
|
277
|
+
# Result
|
246
278
|
def set_endpoint(endpoint)
|
247
|
-
|
248
|
-
nil
|
279
|
+
Result.new(call(CMD_SET_ENDPOINT % endpoint))
|
249
280
|
end
|
250
281
|
|
251
282
|
# Remove an endpoint from the system
|
252
|
-
#
|
253
|
-
#
|
283
|
+
# ==== Args
|
284
|
+
# endpoint :: an endpoint
|
285
|
+
# ==== Return
|
286
|
+
# nil
|
254
287
|
def delete_endpoint(endpoint)
|
255
|
-
|
256
|
-
nil
|
288
|
+
Result.new(call(CMD_DEL_ENDPOINT % endpoint))
|
257
289
|
end
|
258
290
|
alias :del_endpoint :delete_endpoint
|
259
291
|
|
260
292
|
# Retrieve an endpoint in the system
|
261
|
-
# Return
|
293
|
+
# ==== Return
|
262
294
|
# Array of Endpoint
|
263
295
|
def get_endpoints
|
264
|
-
endpoints =
|
296
|
+
endpoints = call(CMD_GET_ENDPOINTS)[:endpoints]
|
265
297
|
endpoints.map {|endpoint| Endpoint.new(endpoint) }
|
266
298
|
end
|
267
299
|
|
268
300
|
# Add an Bucket in the system
|
269
|
-
#
|
270
|
-
#
|
301
|
+
# ==== Args
|
302
|
+
# bucket_name :: a bucket name
|
303
|
+
# access_key_id :: access key id
|
304
|
+
# ==== Return
|
305
|
+
# Result
|
271
306
|
def add_bucket(bucket_name, access_key_id)
|
272
|
-
|
273
|
-
nil
|
307
|
+
Result.new(call(CMD_ADD_BUCKET % [bucket_name, access_key_id]))
|
274
308
|
end
|
275
309
|
|
276
310
|
# Delete an Bucket in the system
|
277
|
-
#
|
278
|
-
#
|
311
|
+
# ==== Args
|
312
|
+
# bucket_name :: a bucket name
|
313
|
+
# access_key_id :: access key id
|
314
|
+
# ==== Return
|
315
|
+
# Result
|
279
316
|
def delete_bucket(bucket_name, access_key_id)
|
280
|
-
|
281
|
-
nil
|
317
|
+
Result.new(call(CMD_DELETE_BUCKET % [bucket_name, access_key_id]))
|
282
318
|
end
|
283
319
|
|
284
320
|
# Retrieve all buckets from the system
|
285
|
-
# Return
|
321
|
+
# ==== Return
|
286
322
|
# Array of Bucket
|
287
323
|
def get_buckets
|
288
|
-
buckets =
|
324
|
+
buckets = call(CMD_GET_BUCKETS)[:buckets]
|
289
325
|
buckets.map {|bucket| Bucket.new(bucket) }
|
290
326
|
end
|
291
327
|
|
328
|
+
# Update acl of a bucket
|
329
|
+
# ==== Args
|
330
|
+
# bucket_name :: a bucket name
|
331
|
+
# access_key_id :: access key id
|
332
|
+
# acl :: acl of a bucket
|
333
|
+
# ==== Return
|
334
|
+
# Result
|
335
|
+
def update_acl(bucket, accesskey, acl)
|
336
|
+
Result.new(call(CMD_UPDATE_ACL % [bucket, accesskey, acl]))
|
337
|
+
end
|
338
|
+
|
292
339
|
# Recover file
|
293
|
-
#
|
294
|
-
#
|
340
|
+
# ==== Args
|
341
|
+
# path :: an object path
|
342
|
+
# ==== Return
|
343
|
+
# Result
|
295
344
|
def recover_file(path)
|
296
|
-
|
297
|
-
nil
|
345
|
+
Result.new(call(CMD_RECOVER_FILE % path))
|
298
346
|
end
|
299
347
|
|
300
348
|
# Recover node
|
301
|
-
#
|
302
|
-
#
|
349
|
+
# ==== Args
|
350
|
+
# node :: a storage node
|
351
|
+
# ==== Return
|
352
|
+
# Result
|
303
353
|
def recover_node(node)
|
304
|
-
|
305
|
-
nil
|
354
|
+
Result.new(call(CMD_RECOVER_NODE % node))
|
306
355
|
end
|
307
356
|
|
308
357
|
# Recover ring
|
309
|
-
#
|
310
|
-
#
|
358
|
+
# ==== Args
|
359
|
+
# node :: a storage node
|
360
|
+
# ==== Return
|
361
|
+
# Result
|
311
362
|
def recover_ring(node)
|
312
|
-
|
363
|
+
Result.new(call(CMD_RECOVER_RING % node))
|
313
364
|
nil
|
314
365
|
end
|
315
366
|
|
316
367
|
# Disconnect to LeoFS Manager explicitly
|
317
|
-
# Return
|
318
|
-
#
|
368
|
+
# ==== Return
|
369
|
+
# Result
|
319
370
|
def disconnect!
|
320
371
|
disconnect
|
321
372
|
end
|
@@ -380,7 +431,7 @@ module LeoManager
|
|
380
431
|
# Send a request to LeoFS Manager
|
381
432
|
# Return::
|
382
433
|
# Hash
|
383
|
-
def
|
434
|
+
def call(command)
|
384
435
|
response = nil
|
385
436
|
begin
|
386
437
|
@mutex.synchronize do
|
@@ -393,6 +444,7 @@ module LeoManager
|
|
393
444
|
warn "EOFError occured (server: #{@current_server})"
|
394
445
|
reconnect
|
395
446
|
rescue => ex
|
447
|
+
reconnect
|
396
448
|
raise "An Error occured: #{ex.class} (server: #{@current_server})\n#{ex.message}"
|
397
449
|
else
|
398
450
|
raise response[:error] if response.has_key?(:error)
|
@@ -409,6 +461,7 @@ if __FILE__ == $PROGRAM_NAME
|
|
409
461
|
$DEBUG = true
|
410
462
|
m = LeoManager::Client.new("localhost:10020", "localhost:10021")
|
411
463
|
p m.version
|
464
|
+
|
412
465
|
p "[status]"
|
413
466
|
p m.status
|
414
467
|
|
@@ -418,6 +471,12 @@ if __FILE__ == $PROGRAM_NAME
|
|
418
471
|
p "[status gateway_0@127.0.0.1]"
|
419
472
|
p m.status("gateway_0@127.0.0.1")
|
420
473
|
|
474
|
+
p "[add-bucket]"
|
475
|
+
p m.add_bucket("photo", "05236")
|
476
|
+
|
477
|
+
p "[update-acl]"
|
478
|
+
p m.update_acl("photo", "05236", "public-read")
|
479
|
+
|
421
480
|
p "[get-buckets]"
|
422
481
|
p m.get_buckets()
|
423
482
|
|
data/lib/leo_manager_models.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# LeoFS Manager Client
|
4
4
|
#
|
5
|
-
# Copyright (c) 2012 Rakuten, Inc.
|
5
|
+
# Copyright (c) 2012-2014 Rakuten, Inc.
|
6
6
|
#
|
7
7
|
# This file is provided to you under the Apache License,
|
8
8
|
# Version 2.0 (the "License"); you may not use this file
|
@@ -21,6 +21,23 @@
|
|
21
21
|
# ======================================================================
|
22
22
|
module LeoManager
|
23
23
|
|
24
|
+
# ==========================
|
25
|
+
# Common Result
|
26
|
+
# ==========================
|
27
|
+
class Result
|
28
|
+
attr_reader :result
|
29
|
+
|
30
|
+
def initialize(h)
|
31
|
+
error = h[:error]
|
32
|
+
if error == nil
|
33
|
+
@result = h[:result]
|
34
|
+
else
|
35
|
+
@result = error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
24
41
|
# ==========================
|
25
42
|
# System Information Model
|
26
43
|
# ==========================
|
@@ -118,8 +135,10 @@ module LeoManager
|
|
118
135
|
@@properties = [:handler, :port, :ssl_port, :num_of_acceptors, :http_cache,
|
119
136
|
:cache_workers, :cache_expire, :cache_ram_capacity,
|
120
137
|
:cache_disc_capacity, :cache_disc_threshold_len, :cache_disc_dir_data,
|
121
|
-
:cache_disc_dir_journal, :cache_max_content_len,
|
122
|
-
:max_len_for_obj, :chunked_obj_len,
|
138
|
+
:cache_disc_dir_journal, :cache_max_content_len,
|
139
|
+
:max_chunked_objs, :max_len_for_obj, :chunked_obj_len,
|
140
|
+
:reading_chunked_obj_len, :threshold_of_chunk_len
|
141
|
+
]
|
123
142
|
attr_reader *@@properties
|
124
143
|
|
125
144
|
def initialize(h)
|
@@ -154,9 +173,9 @@ module LeoManager
|
|
154
173
|
# ==========================
|
155
174
|
class StorageStat
|
156
175
|
attr_reader :active_num_of_objects, :total_num_of_objects,
|
157
|
-
|
158
|
-
|
159
|
-
|
176
|
+
:active_size_of_objects, :total_size_of_objects,
|
177
|
+
:ratio_of_active_size,
|
178
|
+
:last_compaction_start, :last_compaction_end
|
160
179
|
|
161
180
|
alias total_of_objects total_num_of_objects # for compatibility
|
162
181
|
|
@@ -285,8 +304,8 @@ module LeoManager
|
|
285
304
|
# ==========================
|
286
305
|
class CompactionStatus
|
287
306
|
attr_reader :status, :last_compaction_start,
|
288
|
-
|
289
|
-
|
307
|
+
:total_targets, :num_of_pending_targets,
|
308
|
+
:num_of_ongoing_targets, :num_of_out_of_targets
|
290
309
|
|
291
310
|
def initialize(h)
|
292
311
|
@status = h[:status]
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leo_manager_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.9
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Yosuke Hara
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-06 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Client for LeoFS-Manager
|
15
14
|
email:
|
@@ -18,7 +17,7 @@ executables: []
|
|
18
17
|
extensions: []
|
19
18
|
extra_rdoc_files: []
|
20
19
|
files:
|
21
|
-
- .gitignore
|
20
|
+
- ".gitignore"
|
22
21
|
- Gemfile
|
23
22
|
- LICENSE.txt
|
24
23
|
- README.md
|
@@ -30,27 +29,26 @@ files:
|
|
30
29
|
- spec/leo_manager_client_spec.rb
|
31
30
|
homepage: ''
|
32
31
|
licenses: []
|
32
|
+
metadata: {}
|
33
33
|
post_install_message:
|
34
34
|
rdoc_options: []
|
35
35
|
require_paths:
|
36
36
|
- lib
|
37
37
|
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
-
none: false
|
39
38
|
requirements:
|
40
|
-
- -
|
39
|
+
- - ">="
|
41
40
|
- !ruby/object:Gem::Version
|
42
41
|
version: '0'
|
43
42
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
-
none: false
|
45
43
|
requirements:
|
46
|
-
- -
|
44
|
+
- - ">="
|
47
45
|
- !ruby/object:Gem::Version
|
48
46
|
version: '0'
|
49
47
|
requirements: []
|
50
48
|
rubyforge_project:
|
51
|
-
rubygems_version:
|
49
|
+
rubygems_version: 2.2.0
|
52
50
|
signing_key:
|
53
|
-
specification_version:
|
51
|
+
specification_version: 4
|
54
52
|
summary: Client for LeoFS-Manager
|
55
53
|
test_files:
|
56
54
|
- spec/dummy_tcp_server.rb
|