pvdgm-bs-client 0.1.0

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.
@@ -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