myer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +5 -0
- data/Rakefile +44 -0
- data/bin/myer +198 -0
- data/features/myer.feature +8 -0
- data/features/step_definitions/myer_steps.rb +6 -0
- data/features/support/env.rb +15 -0
- data/lib/myer.rb +25 -0
- data/lib/myer/admin_cli_controller.rb +70 -0
- data/lib/myer/api.rb +104 -0
- data/lib/myer/cli_controller.rb +204 -0
- data/lib/myer/config.rb +86 -0
- data/lib/myer/content.rb +92 -0
- data/lib/myer/crypto.rb +40 -0
- data/lib/myer/exceptions.rb +7 -0
- data/lib/myer/plot.rb +11 -0
- data/lib/myer/proc_net_parser.rb +11 -0
- data/lib/myer/test_cli_controller.rb +52 -0
- data/lib/myer/ticket.rb +3 -0
- data/lib/myer/ticket_store.rb +61 -0
- data/lib/myer/version.rb +3 -0
- data/myer.gemspec +26 -0
- data/myer.rdoc +5 -0
- data/scripts/plot-helper.py +32 -0
- data/spec/admin_cli_controller_spec.rb +128 -0
- data/spec/api_spec.rb +136 -0
- data/spec/cli_controller_spec.rb +368 -0
- data/spec/config_spec.rb +116 -0
- data/spec/content_spec.rb +103 -0
- data/spec/crypto_spec.rb +37 -0
- data/spec/data/myer-full.config +9 -0
- data/spec/data/myer-multiple.config +14 -0
- data/spec/data/myer.config +6 -0
- data/spec/data/plot-data.csv +31 -0
- data/spec/data/secret-ticket-12345678.json +1 -0
- data/spec/data/secret-ticket-987654321.json +1 -0
- data/spec/plot_spec.rb +9 -0
- data/spec/proc_net_parser_spec.rb +15 -0
- data/spec/shared_examples_for_config.rb +47 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/test_cli_controller_spec.rb +72 -0
- data/spec/ticket_store_spec.rb +86 -0
- data/test/default_test.rb +14 -0
- data/test/test_helper.rb +9 -0
- metadata +220 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 96eb334f1899d3979918cb3fdec8a20bc20edf80
|
4
|
+
data.tar.gz: 7b857a67dea1c8440c69d87cd776d7ef4c90aec0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c928c5c4484c25836bcc86170844c173221271118da31d8d47523d81af609ab44cedc0bbfb3e7bfc69c3fc56d01775fe5e99dc7dd876443a7f8c9286f754fa9e
|
7
|
+
data.tar.gz: 97b62bd79399807f99d3defa7eba08b70139b8447439ab2cdbd9af9c94cbf14c5153cac2ac78bae62fb813514186bd6d515cba9e5790a25ef89f5f3dfaa92c31
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- "2.0.0"
|
4
|
+
- "2.1.1"
|
5
|
+
script: bundle exec rspec spec
|
6
|
+
addons:
|
7
|
+
code_climate:
|
8
|
+
repo_token:
|
9
|
+
secure: XQRgzJQhdraJYMTUusZwi2D7CeArx1a/PF8tkpT3BiGO3xKLRdImfjSWP4HOAMzKE7iOOtwcySgHMJIEguWurn95mvIwbMQtA41vjDbEXCnHOS2F0n15Gb7sy2ULf6Qx+41YO5TlqubAUQRvPgb6wNFZ0OBemvLENTWMzrhITJo=
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Cornelius Schumacher
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/cornelius/myer.svg?branch=master)](https://travis-ci.org/cornelius/myer)
|
2
|
+
[![Test Coverage](https://codeclimate.com/github/cornelius/myer/badges/coverage.svg)](https://codeclimate.com/github/cornelius/myer)
|
3
|
+
[![Code Climate](https://codeclimate.com/github/cornelius/myer/badges/gpa.svg)](https://codeclimate.com/github/cornelius/myer)
|
4
|
+
|
5
|
+
Command line client of [Project MySelf](https://github.com/cornelius/project-myself)
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'rdoc/task'
|
5
|
+
require 'cucumber'
|
6
|
+
require 'cucumber/rake/task'
|
7
|
+
Rake::RDocTask.new do |rd|
|
8
|
+
rd.main = "README.rdoc"
|
9
|
+
rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
|
10
|
+
rd.title = 'Your application title'
|
11
|
+
end
|
12
|
+
|
13
|
+
spec = eval(File.read('myer.gemspec'))
|
14
|
+
|
15
|
+
Gem::PackageTask.new(spec) do |pkg|
|
16
|
+
end
|
17
|
+
CUKE_RESULTS = 'results.html'
|
18
|
+
CLEAN << CUKE_RESULTS
|
19
|
+
desc 'Run features'
|
20
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
21
|
+
opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
|
22
|
+
opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
|
23
|
+
t.cucumber_opts = opts
|
24
|
+
t.fork = false
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Run features tagged as work-in-progress (@wip)'
|
28
|
+
Cucumber::Rake::Task.new('features:wip') do |t|
|
29
|
+
tag_opts = ' --tags ~@pending'
|
30
|
+
tag_opts = ' --tags @wip'
|
31
|
+
t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}"
|
32
|
+
t.fork = false
|
33
|
+
end
|
34
|
+
|
35
|
+
task :cucumber => :features
|
36
|
+
task 'cucumber:wip' => 'features:wip'
|
37
|
+
task :wip => 'features:wip'
|
38
|
+
require 'rake/testtask'
|
39
|
+
Rake::TestTask.new do |t|
|
40
|
+
t.libs << "test"
|
41
|
+
t.test_files = FileList['test/*_test.rb']
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => [:test,:features]
|
data/bin/myer
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'gli'
|
4
|
+
|
5
|
+
require_relative '../lib/myer'
|
6
|
+
|
7
|
+
include GLI::App
|
8
|
+
|
9
|
+
program_desc 'Command line client for Project MySelf'
|
10
|
+
|
11
|
+
version Myer::VERSION
|
12
|
+
|
13
|
+
subcommand_option_handling :normal
|
14
|
+
arguments :strict
|
15
|
+
|
16
|
+
desc 'Describe some switch here'
|
17
|
+
switch [:s,:switch]
|
18
|
+
|
19
|
+
desc 'Describe some flag here'
|
20
|
+
default_value 'the default'
|
21
|
+
arg_name 'The name of the argument'
|
22
|
+
flag [:f,:flagname]
|
23
|
+
|
24
|
+
pre do |global,command,options,args|
|
25
|
+
# Pre logic here
|
26
|
+
# Return true to proceed; false to abort and not call the
|
27
|
+
# chosen command
|
28
|
+
# Use skips_pre before a command to skip this block
|
29
|
+
# on that command only
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
post do |global,command,options,args|
|
34
|
+
# Post logic here
|
35
|
+
# Use skips_post before a command to skip this
|
36
|
+
# block on that command only
|
37
|
+
end
|
38
|
+
|
39
|
+
on_error do |exception|
|
40
|
+
# Error logic here
|
41
|
+
# return false to skip default error handling
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Test"
|
46
|
+
command :test do |c|
|
47
|
+
c.desc "Full server acceptance test"
|
48
|
+
c.arg :server
|
49
|
+
c.arg :pin
|
50
|
+
c.command :full do |full|
|
51
|
+
full.action do |global_options, options, args|
|
52
|
+
TestCliController.new.full(args[0], args[1])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
c.desc "Full local server acceptance test"
|
57
|
+
c.arg :executable
|
58
|
+
c.command :local do |local|
|
59
|
+
local.action do |global_options, options, args|
|
60
|
+
TestCliController.new.local(args[0])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Admin actions"
|
66
|
+
command :admin do |c|
|
67
|
+
c.desc "Register admin client"
|
68
|
+
c.arg :server
|
69
|
+
c.arg :pin
|
70
|
+
c.command :register do |register|
|
71
|
+
register.action do |global_options, options, args|
|
72
|
+
AdminCliController.new.register(args[0], args[1])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
c.desc "Register as user client"
|
77
|
+
c.command :register_user do |register|
|
78
|
+
register.action do |global_options, options, args|
|
79
|
+
AdminCliController.new.register_user
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
c.desc "List all existing buckets"
|
84
|
+
c.command :list_buckets do |sc|
|
85
|
+
sc.action do
|
86
|
+
AdminCliController.new.list_buckets
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
c.desc "Delete bucket"
|
91
|
+
c.arg :bucket_id
|
92
|
+
c.command :delete_bucket do |sc|
|
93
|
+
sc.action do |global_options, options, args|
|
94
|
+
AdminCliController.new.delete_bucket(args[0])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
c.desc "Print status"
|
99
|
+
c.command :status do |sc|
|
100
|
+
sc.action do
|
101
|
+
AdminCliController.new.status
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
desc "Create bucket"
|
107
|
+
arg :name
|
108
|
+
command :create_bucket do |c|
|
109
|
+
c.action do |global_options, options, args|
|
110
|
+
CliController.new.create_bucket(args[0])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "Create token"
|
115
|
+
command :create_token do |c|
|
116
|
+
c.action do
|
117
|
+
CliController.new.create_token
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "Register user client"
|
122
|
+
arg :server
|
123
|
+
arg :token
|
124
|
+
command :register do |c|
|
125
|
+
c.action do |global_options, options, args|
|
126
|
+
CliController.new.register(args[0], args[1])
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
desc "Write item"
|
131
|
+
command :write do |c|
|
132
|
+
c.switch :raw, desc: "Write unencrypted"
|
133
|
+
c.action do |global_options, options, args|
|
134
|
+
if options[:raw]
|
135
|
+
CliController.new.write_raw(STDIN.read)
|
136
|
+
else
|
137
|
+
CliController.new.write(STDIN.read)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
desc "Write value"
|
143
|
+
arg :value
|
144
|
+
command :write_value do |c|
|
145
|
+
c.flag :tag, desc: "Add tag as meta data"
|
146
|
+
c.action do |global_options, options, args|
|
147
|
+
CliController.new.write_value(args[0], options[:tag])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
desc "Write pair of values"
|
152
|
+
arg :value1
|
153
|
+
arg :value2
|
154
|
+
command :write_pair do |c|
|
155
|
+
c.action do |global_options, options, args|
|
156
|
+
CliController.new.write_pair(args[0], args[1])
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
desc "Read items"
|
161
|
+
command :read do |c|
|
162
|
+
c.action do
|
163
|
+
CliController.new.read
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
desc "Plot data"
|
168
|
+
command :plot do |c|
|
169
|
+
c.switch :dont_sync, desc: "Don't sync data from server"
|
170
|
+
c.action do |_, options, _|
|
171
|
+
CliController.new.plot(dont_sync: options[:dont_sync])
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
desc "Export data"
|
176
|
+
arg :output_path
|
177
|
+
command :export do |c|
|
178
|
+
c.action do|global_options, options, args|
|
179
|
+
CliController.new.export(args[0])
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
desc "Consume ticket"
|
184
|
+
arg :ticket_path
|
185
|
+
command :consume_ticket do |c|
|
186
|
+
c.action do |global_options, options, args|
|
187
|
+
CliController.new.consume_ticket(args[0])
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
desc "List tickets"
|
192
|
+
command :list_tickets do |c|
|
193
|
+
c.switch :status, desc: "Show server status"
|
194
|
+
c.action do |_, options, _|
|
195
|
+
CliController.new.list_tickets(show_status: options[:status])
|
196
|
+
end
|
197
|
+
end
|
198
|
+
exit run(ARGV)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
|
3
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
4
|
+
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
5
|
+
|
6
|
+
Before do
|
7
|
+
# Using "announce" causes massive warnings on 1.9.2
|
8
|
+
@puts = true
|
9
|
+
@original_rubylib = ENV['RUBYLIB']
|
10
|
+
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
After do
|
14
|
+
ENV['RUBYLIB'] = @original_rubylib
|
15
|
+
end
|
data/lib/myer.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
require "xdg"
|
4
|
+
require "open3"
|
5
|
+
require "tempfile"
|
6
|
+
require "securerandom"
|
7
|
+
|
8
|
+
def require_myer(file)
|
9
|
+
require_relative("myer/#{file}")
|
10
|
+
end
|
11
|
+
|
12
|
+
require_myer "version"
|
13
|
+
|
14
|
+
require_myer "exceptions"
|
15
|
+
require_myer "config"
|
16
|
+
require_myer "cli_controller"
|
17
|
+
require_myer "admin_cli_controller"
|
18
|
+
require_myer "test_cli_controller"
|
19
|
+
require_myer "crypto"
|
20
|
+
require_myer "ticket"
|
21
|
+
require_myer "ticket_store"
|
22
|
+
require_myer "proc_net_parser"
|
23
|
+
require_myer "content"
|
24
|
+
require_myer "plot"
|
25
|
+
require_myer "api"
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class AdminCliController
|
2
|
+
include Myer::Config
|
3
|
+
|
4
|
+
attr_accessor :out
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@out = STDOUT
|
8
|
+
initialize_config
|
9
|
+
end
|
10
|
+
|
11
|
+
def api(server_name = default_server)
|
12
|
+
api = MySelf::Api.new
|
13
|
+
api.server = server_name
|
14
|
+
if server(server_name)
|
15
|
+
api.user = server(server_name).admin_id
|
16
|
+
api.password = server(server_name).admin_password
|
17
|
+
end
|
18
|
+
api
|
19
|
+
end
|
20
|
+
|
21
|
+
def register(server_name, pid)
|
22
|
+
self.default_server = server_name
|
23
|
+
self.admin_id, self.admin_password = api(server_name).admin_register(pid)
|
24
|
+
|
25
|
+
write_config
|
26
|
+
end
|
27
|
+
|
28
|
+
def list_buckets
|
29
|
+
read_config
|
30
|
+
|
31
|
+
buckets = api.admin_list_buckets
|
32
|
+
|
33
|
+
store = TicketStore.new(config_dir)
|
34
|
+
buckets.each do |bucket_id|
|
35
|
+
line = bucket_id + ": "
|
36
|
+
ticket = store.load_ticket(bucket_id)
|
37
|
+
if ticket
|
38
|
+
line += ticket.name || "<no name>"
|
39
|
+
else
|
40
|
+
line += "<no ticket>"
|
41
|
+
end
|
42
|
+
if bucket_id == default_bucket_id
|
43
|
+
line += " (default)"
|
44
|
+
end
|
45
|
+
out.puts line
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete_bucket(bucket_id)
|
50
|
+
read_config
|
51
|
+
|
52
|
+
api.admin_delete_bucket(bucket_id)
|
53
|
+
end
|
54
|
+
|
55
|
+
def status
|
56
|
+
read_config
|
57
|
+
|
58
|
+
out.puts "Default server: #{default_server}"
|
59
|
+
out.puts "Default bucket: #{default_bucket_id}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def register_user
|
63
|
+
read_config
|
64
|
+
|
65
|
+
token = api.create_token
|
66
|
+
self.user_id, self.user_password = api.register(token)
|
67
|
+
|
68
|
+
write_config
|
69
|
+
end
|
70
|
+
end
|
data/lib/myer/api.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
module MySelf
|
2
|
+
class Api
|
3
|
+
attr_accessor :server
|
4
|
+
attr_accessor :user, :password
|
5
|
+
|
6
|
+
def http_request
|
7
|
+
http = Net::HTTP.new(server, 4735)
|
8
|
+
|
9
|
+
request = yield
|
10
|
+
|
11
|
+
response = http.request(request)
|
12
|
+
|
13
|
+
if response.code != "200"
|
14
|
+
raise "#{request.path} HTTP Error #{response.code} - #{response.body}"
|
15
|
+
else
|
16
|
+
if response.body and !response.body.empty?
|
17
|
+
return JSON.parse(response.body)
|
18
|
+
else
|
19
|
+
return nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def post(path, content = nil, auth_enabled = true)
|
25
|
+
http_request do
|
26
|
+
request = Net::HTTP::Post.new(path)
|
27
|
+
request.basic_auth(user, password) if auth_enabled
|
28
|
+
request.body = content if content
|
29
|
+
request
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(path)
|
34
|
+
http_request do
|
35
|
+
request = Net::HTTP::Get.new(path)
|
36
|
+
request.basic_auth(user, password)
|
37
|
+
request
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete(path)
|
42
|
+
http_request do
|
43
|
+
request = Net::HTTP::Delete.new(path)
|
44
|
+
request.basic_auth(user, password)
|
45
|
+
request
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def admin_register(pid)
|
50
|
+
json = post("/admin/register/#{pid}",nil,false)
|
51
|
+
return json["admin_id"], json["password"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def admin_list_buckets
|
55
|
+
get("/admin/buckets")
|
56
|
+
end
|
57
|
+
|
58
|
+
def admin_delete_bucket(bucket_id)
|
59
|
+
delete("/admin/buckets/#{bucket_id}")
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_token
|
63
|
+
json = post("/tokens")
|
64
|
+
return json["token"]
|
65
|
+
end
|
66
|
+
|
67
|
+
def register(token)
|
68
|
+
json = post("/register/" + token, nil, false)
|
69
|
+
return json["user_id"], json["user_password"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_bucket
|
73
|
+
json = post("/data")
|
74
|
+
return json["bucket_id"]
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_item(bucket_id, content)
|
78
|
+
json = post("/data/#{bucket_id}", content)
|
79
|
+
return json["item_id"]
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_items(bucket_id)
|
83
|
+
json = get("/data/#{bucket_id}")
|
84
|
+
|
85
|
+
inner_items = []
|
86
|
+
|
87
|
+
json.each do |json_item|
|
88
|
+
item = OpenStruct.new
|
89
|
+
item.id = json_item["item_id"]
|
90
|
+
item.content = json_item["content"]
|
91
|
+
inner_items.unshift(item)
|
92
|
+
end
|
93
|
+
|
94
|
+
return inner_items
|
95
|
+
end
|
96
|
+
|
97
|
+
def ping
|
98
|
+
json = get("/ping")
|
99
|
+
if json["ping"] != "pong"
|
100
|
+
raise "ping error: expected 'pong', got '#{result}'"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|