pvdgm-bs-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ module JobPrompter
2
+
3
+ def job_id(allow_none=false)
4
+ return options[:job_id] if options[:job_id]
5
+ return options[:job_id] = ENV['JOB_ID'] if ENV['JOB_ID']
6
+ return options[:job_Id] = prompt_for_job_id(allow_none)
7
+ end
8
+
9
+ private
10
+
11
+ def prompt_for_job_id(allow_none)
12
+ puts
13
+ command = prompter.choose do | menu |
14
+ menu.prompt = "Which tube state do you want to peek into? "
15
+ menu.choice("Ready") { 'ready' }
16
+ menu.choice("Delayed") { 'delayed' }
17
+ menu.choice("Buried") { 'buried' }
18
+ end
19
+
20
+ result = get("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/#{command}")
21
+ return -1 if result.has_key?('error')
22
+
23
+ # Build a menu of the job
24
+ puts
25
+ return prompter.choose do | menu |
26
+ menu.prompt = "Select the job: "
27
+ menu.choice("No Selection") { -1 } if allow_none
28
+ menu.choice("Job ID: #{result.keys.first}") { result.keys.first }
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,25 @@
1
+ module ToTubePrompter
2
+
3
+ def to_tube_name(allow_none=false)
4
+ return options[:to_tube] if options[:to_tube]
5
+ return options[:to_tube] = ENV['TO_TUBE_NAME'] if ENV['TO_TUBE_NAME']
6
+ return options[:to_tube] = prompt_for_to_tube_name(allow_none)
7
+ end
8
+
9
+ private
10
+
11
+ def prompt_for_to_tube_name(allow_none)
12
+ result = get("beanstalk/tubes")
13
+
14
+ # Build a menu of the tube names
15
+ puts
16
+ return prompter.choose do | menu |
17
+ menu.prompt = "Select the destination beanstalk tube: "
18
+ menu.choice("No Selection") { -1 } if allow_none
19
+ result.each do | tube_name |
20
+ menu.choice(tube_name) { tube_name }
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,25 @@
1
+ module TubePrompter
2
+
3
+ def tube_name(allow_none=false)
4
+ return options[:tube] if options[:tube]
5
+ return options[:tube] = ENV['TUBE_NAME'] if ENV['TUBE_NAME']
6
+ return options[:tube] = prompt_for_tube_name(allow_none)
7
+ end
8
+
9
+ private
10
+
11
+ def prompt_for_tube_name(allow_none)
12
+ result = get("beanstalk/tubes")
13
+
14
+ # Build a menu of the tube names
15
+ puts
16
+ return prompter.choose do | menu |
17
+ menu.prompt = "Select the beanstalk tube: "
18
+ menu.choice("No Selection") { -1 } if allow_none
19
+ result.each do | tube_name |
20
+ menu.choice(tube_name) { tube_name }
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,61 @@
1
+ module Resources
2
+
3
+ class Job < BaseResource
4
+ include TubePrompter
5
+ include JobPrompter
6
+
7
+ def list
8
+ tube = tube_name
9
+ job = job_id
10
+
11
+ if job == -1
12
+ puts "\nNo jobs in state"
13
+ puts
14
+ return
15
+ end
16
+
17
+ result = get("beanstalk/jobs/#{job}")
18
+
19
+ if result.has_key?('error')
20
+ puts
21
+ puts result['error']
22
+ else
23
+ table = Terminal::Table.new headings: [ 'Id', 'Body' ] do | t |
24
+ t << [ result['job'].keys.first, result['job'].values.first ]
25
+ end
26
+ puts table
27
+ puts
28
+
29
+ table = Terminal::Table.new headings: [ 'Key', 'Value' ] do | t |
30
+ result['statistics'].each_pair do | key, value |
31
+ t << [ key, value ]
32
+ end
33
+ end
34
+ puts table
35
+ end
36
+ puts
37
+ end
38
+
39
+ def destroy
40
+ tube = tube_name
41
+ job = job_id(true)
42
+
43
+ if job == -1
44
+ puts "\nNo jobs in state"
45
+ puts
46
+ return
47
+ end
48
+
49
+ result = delete("beanstalk/jobs/#{job}")
50
+ if result.has_key?('error')
51
+ puts
52
+ puts result['error']
53
+ else
54
+ puts result['job']
55
+ end
56
+ puts
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,29 @@
1
+ module Resources
2
+
3
+ class Statistics < BaseResource
4
+
5
+ def list
6
+
7
+ filter = Proc.new do | key |
8
+ if options[:all_stats]
9
+ true
10
+ else
11
+ not key =~ /(^cmd-|^max-|^pid|^version|^rusage|^binlog|^id)/
12
+ end
13
+ end
14
+
15
+ result = get("beanstalk")
16
+ puts "\nBeanstalk global statistics"
17
+ table = Terminal::Table.new headings: [ 'Key', 'Value' ] do | t |
18
+ result.keys.sort.each do | key |
19
+ next unless filter.call(key)
20
+ t << [ key, result[key] ]
21
+ end
22
+ end
23
+ puts table
24
+ puts
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,124 @@
1
+ module Resources
2
+
3
+ class Tube < BaseResource
4
+ include TubePrompter
5
+ include ToTubePrompter
6
+
7
+ def list
8
+ result = get("beanstalk/tubes")
9
+ puts "\nBeanstalk tubes"
10
+ table = Terminal::Table.new headings: [ 'Tube Name' ] do | t |
11
+ result.each do | tube_name |
12
+ t << [ tube_name ]
13
+ end
14
+ end
15
+ puts table
16
+ puts
17
+ end
18
+
19
+ def show
20
+ tube = tube_name
21
+ result = get("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}")
22
+ puts "\nStatistics for tube: #{tube}"
23
+ table = Terminal::Table.new headings: [ 'Key', 'Value' ] do | t |
24
+ result.each_pair do | key, value |
25
+ t << [ key, value ]
26
+ end
27
+ end
28
+ puts table
29
+ puts
30
+ end
31
+
32
+ def ready
33
+ tube = tube_name
34
+ result = get("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/ready")
35
+ if result.has_key?('error')
36
+ puts
37
+ puts result['error']
38
+ else
39
+ puts "\nJobs in the Ready state:"
40
+ table = Terminal::Table.new headings: [ 'Id', 'Body' ] do | t |
41
+ t << [ result.keys.first, result.values.first ]
42
+ end
43
+ puts table
44
+ end
45
+ puts
46
+ end
47
+
48
+ def delayed
49
+ tube = tube_name
50
+ result = get("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/delayed")
51
+ if result.has_key?('error')
52
+ puts
53
+ puts result['error']
54
+ else
55
+ puts "\nJobs in the Delayed state:"
56
+ table = Terminal::Table.new headings: [ 'Id', 'Body' ] do | t |
57
+ t << [ result.keys.first, result.values.first ]
58
+ end
59
+ puts table
60
+ end
61
+ puts
62
+ end
63
+
64
+ def buried
65
+ tube = tube_name
66
+ result = get("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/buried")
67
+ if result.has_key?('error')
68
+ puts
69
+ puts result['error']
70
+ else
71
+ puts "\nJobs in the Buried state:"
72
+ table = Terminal::Table.new headings: [ 'Id', 'Body' ] do | t |
73
+ t << [ result.keys.first, result.values.first ]
74
+ end
75
+ puts table
76
+ end
77
+ puts
78
+ end
79
+
80
+ def delete_one_job
81
+ tube = tube_name
82
+ result = delete("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/one_job")
83
+ puts "\nJob deleted"
84
+ puts result['eat_job']
85
+ puts
86
+ end
87
+
88
+ def delete_all_jobs
89
+ tube = tube_name
90
+ result = delete("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/all_jobs")
91
+ puts "\nAll jobs deleted"
92
+ puts result['eat_job']
93
+ puts
94
+ end
95
+
96
+ def move
97
+ tube = tube_name
98
+ to_tube = to_tube_name
99
+ result = delete("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/move/#{Base64.urlsafe_encode64(to_tube)}")
100
+ puts "\nAll jobs moved from '#{tube}' to '#{to_tube}':"
101
+ puts result['eat_job']
102
+ puts
103
+ end
104
+
105
+ def kill_worker
106
+ tube = tube_name
107
+ result = delete("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/worker")
108
+ puts "\nWorker killed:"
109
+ puts result['kill_worker']
110
+ puts
111
+ end
112
+
113
+ def kick
114
+ tube = tube_name
115
+ num_jobs = prompter.ask("Number of jobs to kick: ", Integer) { |q| q.default = 1 }
116
+ result = get("beanstalk/tubes/#{Base64.urlsafe_encode64(tube_name)}/kick/#{num_jobs}")
117
+ puts "\nKick #{num_jobs} in tube '#{tube}':"
118
+ puts result['kick']
119
+ puts
120
+ end
121
+
122
+ end
123
+
124
+ end
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ describe BaseResource do
4
+
5
+ context 'Private Methods' do
6
+
7
+ before(:each) do
8
+ @cut = BaseResource.new({ use_ssl: false, server: 'localhost:3000', api_token: 'sltc_api_token'})
9
+ end
10
+
11
+ context '#invoke_rest' do
12
+
13
+ it "should return a raw string if a non-JSON response is made from the block" do
14
+ result = @cut.send(:invoke_rest, false) do
15
+ "abc123"
16
+ end
17
+ expect(result).to eq("abc123")
18
+ end
19
+
20
+ it "should parse a response as JSON by default" do
21
+ result = @cut.send(:invoke_rest) do
22
+ '{ "message": "from the other side" }'
23
+ end
24
+ expect(result).to eq({ 'message' => 'from the other side' })
25
+ end
26
+
27
+ it "should output an error message and exit if the JSON payload is invalid" do
28
+ expect {
29
+ @cut.send(:invoke_rest) do
30
+ '{ message => 3'
31
+ end
32
+ }.to raise_error(SystemExit)
33
+ end
34
+
35
+ it "should output an error message and exit if there is a non-403,404 exception" do
36
+ mock_response = double("Response")
37
+ mock_response.should_receive(:code).any_number_of_times.and_return(500)
38
+ mock_response.should_receive(:description).and_return("System error")
39
+
40
+ expect {
41
+ @cut.send(:invoke_rest) do
42
+ raise RestClient::Exception.new(mock_response, 500)
43
+ end
44
+ }.to raise_error(SystemExit)
45
+ end
46
+
47
+ it "should output an error message and exit if there is a 403 exception with no json" do
48
+ mock_response = double("Response")
49
+ mock_response.should_receive(:code).any_number_of_times.and_return(403)
50
+ mock_response.should_receive(:description).and_return("Some other error")
51
+
52
+ expect {
53
+ @cut.send(:invoke_rest, false) do
54
+ raise RestClient::Exception.new(mock_response, 403)
55
+ end
56
+ }.to raise_error(SystemExit)
57
+ end
58
+
59
+ it "should output an error message and exit if there is a 404 exception with error json" do
60
+ mock_response = double("Response")
61
+ mock_response.should_receive(:code).any_number_of_times.and_return(404)
62
+ mock_response.should_receive(:description).and_return("Some other error")
63
+ mock_response.should_receive(:http_body).and_return('{ "error" : "Error message" }')
64
+
65
+ expect {
66
+ @cut.send(:invoke_rest) do
67
+ raise RestClient::Exception.new(mock_response, 404)
68
+ end
69
+ }.to raise_error(SystemExit)
70
+ end
71
+
72
+ it "should output an error message and exit if there is a 403 exception with validation error json" do
73
+ mock_response = double("Response")
74
+ mock_response.should_receive(:code).any_number_of_times.and_return(403)
75
+ mock_response.should_receive(:description).and_return("Some other error")
76
+ mock_response.should_receive(:http_body).and_return('{ "validation_error" : { "name" : [ "Error 1", "Error 2" ] } }')
77
+
78
+ expect {
79
+ @cut.send(:invoke_rest) do
80
+ raise RestClient::Exception.new(mock_response, 403)
81
+ end
82
+ }.to raise_error(SystemExit)
83
+ end
84
+
85
+ it "should output an error message and exit if there is a 403 exception with some other error json" do
86
+ mock_response = double("Response")
87
+ mock_response.should_receive(:code).any_number_of_times.and_return(403)
88
+ mock_response.should_receive(:description).and_return("Some other error")
89
+ mock_response.should_receive(:http_body).and_return('{ "other_error" : { "name" : [ "Error 1", "Error 2" ] } }')
90
+
91
+ expect {
92
+ @cut.send(:invoke_rest) do
93
+ raise RestClient::Exception.new(mock_response, 403)
94
+ end
95
+ }.to raise_error(SystemExit)
96
+ end
97
+
98
+ it "should output an error message and exit if there is a 403 exception with invalid validation error json" do
99
+ mock_response = double("Response")
100
+ mock_response.should_receive(:code).any_number_of_times.and_return(403)
101
+ mock_response.should_receive(:description).and_return("Some other error")
102
+ mock_response.should_receive(:http_body).any_number_of_times.and_return('{ "validation_error" : { "name" : "Error 1", "Error 2" ] } }')
103
+
104
+ expect {
105
+ @cut.send(:invoke_rest) do
106
+ raise RestClient::Exception.new(mock_response, 403)
107
+ end
108
+ }.to raise_error(SystemExit)
109
+ end
110
+
111
+ it "should output an error message and exit if there is an unknown exception raised in the block" do
112
+ expect {
113
+ @cut.send(:invoke_rest) do
114
+ raise "Some unknown exception"
115
+ end
116
+ }.to raise_error(SystemExit)
117
+ end
118
+
119
+ end
120
+
121
+ context '#get' do
122
+
123
+ it "should return the response from the GET call" do
124
+ @cut.should_receive(:invoke_rest).with(true).and_yield
125
+
126
+ RestClient.should_receive(:get).
127
+ with('http://localhost:3000/tubes', {"Authorization"=>"Token token=\"sltc_api_token\"" }).
128
+ and_return({ hey: 'guy' })
129
+
130
+ expect(@cut.send(:get, 'tubes')).to eq({ hey: 'guy' })
131
+ end
132
+
133
+ end
134
+
135
+ context '#delete' do
136
+
137
+ it "should return the response from the DELETE call" do
138
+ @cut.should_receive(:invoke_rest).with(true).and_yield
139
+
140
+ RestClient.should_receive(:delete).
141
+ with('http://localhost:3000/tubes', {"Authorization"=>"Token token=\"sltc_api_token\"" }).
142
+ and_return({ hey: 'guy' })
143
+
144
+ expect(@cut.send(:delete, 'tubes')).to eq({ hey: 'guy' })
145
+ end
146
+
147
+ end
148
+
149
+ context '#post' do
150
+
151
+ it "should return the response from the POST call" do
152
+ @cut.should_receive(:invoke_rest).with(true).and_yield
153
+
154
+ RestClient.should_receive(:post).
155
+ with('http://localhost:3000/tubes',
156
+ {"param1"=>"pvalue"},
157
+ {"Authorization"=>"Token token=\"sltc_api_token\"" }).
158
+ and_return({ hey: 'guy' })
159
+
160
+ expect(@cut.send(:post, 'tubes', { 'param1' => 'pvalue' })).to eq({ hey: 'guy' })
161
+ end
162
+
163
+ end
164
+
165
+ context '#put' do
166
+
167
+ it "should return the response from the PUT call" do
168
+ @cut.should_receive(:invoke_rest).with(true).and_yield
169
+
170
+ RestClient.should_receive(:put).
171
+ with('http://localhost:3000/tubes',
172
+ {"param1"=>"pvalue"},
173
+ {"Authorization"=>"Token token=\"sltc_api_token\"" }).
174
+ and_return({ hey: 'guy' })
175
+
176
+ expect(@cut.send(:put, 'tubes', { 'param1' => 'pvalue' })).to eq({ hey: 'guy' })
177
+ end
178
+
179
+ end
180
+
181
+ context '#build_url' do
182
+
183
+ it "should return the properly formatted url" do
184
+ @cut.options[:use_ssl] = false
185
+ @cut.options[:server] = 'www.bob.com'
186
+
187
+ expect(@cut.send(:build_url, 'the_uri')).to eq('http://www.bob.com/the_uri')
188
+
189
+ @cut.options[:use_ssl] = true
190
+
191
+ expect(@cut.send(:build_url, 'the_uri')).to eq('https://www.bob.com/the_uri')
192
+ end
193
+
194
+ end
195
+
196
+ context '#authentication_headers' do
197
+
198
+ it "should return a hash containing the authentication headers" do
199
+ @cut.options[:api_token] = 'this is the token string'
200
+ expect(@cut.send(:authentication_headers)).
201
+ to eq( { 'Authorization' => "Token token=\"this is the token string\"" } )
202
+ end
203
+
204
+ end
205
+
206
+ end
207
+
208
+ end