blender-serf 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a360de1c7367a78e1ae4cb4a5a1bb2095f11e3d
4
- data.tar.gz: 61df6de3ba420247a8e0169005212c1f74baef39
3
+ metadata.gz: 89f1bece5fe6e866cb89265426ac0f96c3dafcf8
4
+ data.tar.gz: def82f90d757304d58be03f0480e16a125bfbdd6
5
5
  SHA512:
6
- metadata.gz: 43bef41ba273f03c8ebe522e8de7820b215a2fd2606f587cb8916544b2d4d30819e55f8f552d4fbfd1b0a4655aa4ea7183e057aaee58c1503d3769abba33ccac
7
- data.tar.gz: 4870e0f7baf6977b6ec519d3a997317b9df659cb723eb457be3f1311b4fa68a261d51841b50fb9338185f7cf4a527d2ee2b7f680ccc91cdac246c51b65a2df39
6
+ metadata.gz: 89d621fcca8551eef4f2218ba3e56fa98e01815a21a528bd70d2b3464b9ad22c7391b5d95b914bf235b4c290b793e1bacc67a395703a8b5362b646ae7e9d5350
7
+ data.tar.gz: 276b2d52e496c88a29d5c2ef64b9264f76f97cd344d62cf15d38f4cade269604588b2ab0a7f63319a674fb60362c2118011f9cd916c8a7affc186a9f34209874
@@ -1,9 +1,9 @@
1
1
  before_install:
2
2
  - bundle install --path .bundle
3
3
  rvm:
4
- - 1.9.3
5
4
  - 2.1.0
6
5
  - 2.1.2
6
+ - 2.2.3
7
7
  branches:
8
8
  only:
9
9
  - master
@@ -0,0 +1,4 @@
1
+ CHANGELOG for blender-serf
2
+ ==========================
3
+ ## 0.2 (December 10, 2015)
4
+ - Async task support
data/README.md CHANGED
@@ -115,6 +115,102 @@ end
115
115
  run
116
116
 
117
117
  ```
118
+
119
+ ### Async task DSL:
120
+
121
+ Since serf event handler execution happens synchronously (i.e. normal serf
122
+ events wont be processed when an event handler is running). Hence, it is
123
+ desirable that the actual event handler returns promptly. This imposes certain
124
+ design challenges in orchestrating long running commands via serf.
125
+
126
+ blender-serf integration provides a simpler solution to this problem.
127
+ It recommends using the serf event handler only to fork off the long running command, and maintain
128
+ a state file locally that can be used to decide whether the original task is running or finished.
129
+ Most of these gears are offered by Serfx::Utils::AsynJob module. On blender side `serf_async_task` method
130
+ is used to manage this long running job, using three separate serf events (one to start
131
+ the command, another one to poll and check if its finished or not, and the last one
132
+ to reap the finished command).
133
+
134
+ Following is an example handler that runs apt update. It exposes the task management as 4
135
+ distinct events, start, check, kill, reap.
136
+
137
+ ```ruby
138
+ require 'serfx/utils/async_job'
139
+ require 'serfx/utils/handler'
140
+ require 'json'
141
+
142
+ include Serfx::Utils::Handler
143
+
144
+ job = Serfx::Utils::AsyncJob.new( name: 'update', command: 'sudo apt-get update -y', state: '/opt/serf/states/chef')
145
+
146
+ on :query, 'apt-update' do |event|
147
+ case event.payload
148
+ when 'start'
149
+ status = job.start
150
+ code = (status == 'success') ? 0 : -1
151
+ puts JSON.dump(code: code, result: { status: status })
152
+ when 'kill'
153
+ status = job.kill
154
+ code = (status == 'success') ? 0 : -1
155
+ puts JSON.dump(code: code, result: { status: status })
156
+ when 'reap'
157
+ status = job.reap
158
+ code = (status == 'success') ? 0 : -1
159
+ puts JSON.dump(code: code, result: { status: status })
160
+ when 'check'
161
+ state = job.stateinfo
162
+ puts JSON.dump(code: 0, result: state)
163
+ else
164
+ puts JSON.dump(code: -1, result: { status: 'failed' })
165
+ end
166
+ end
167
+
168
+ run
169
+ ```
170
+
171
+ This long running command can be orchestrated using the `serf_async_task` like this:
172
+
173
+ ```ruby
174
+ serf_async_task 'run apt-get update' do
175
+
176
+ start do
177
+ query 'apt-update'
178
+ payload 'start'
179
+ end
180
+
181
+ check do
182
+ query 'apt-update'
183
+ payload 'check'
184
+ process do |responses|
185
+ responses.all? do |resp|
186
+ status = JSON.parse(resp['Payload'])['result']['status']
187
+ fail 'Apt-get update is running' if status == 'running'
188
+ end
189
+ end
190
+ end
191
+
192
+ reap do
193
+ query 'apt-update'
194
+ payload 'reap'
195
+ end
196
+ end
197
+ ```
198
+ Which can also be reduced to this, as job named are default query names and `serf_async_task`
199
+ defaults to `start`, `check` and `reap` as payload for managing the life cycle of the command.
200
+
201
+ ```ruby
202
+ serf_async_task 'apt-update' do
203
+ check do
204
+ process do |responses|
205
+ responses.all? do |resp|
206
+ status = JSON.parse(resp['Payload'])['result']['status']
207
+ fail ChefRunning if status == 'running'
208
+ end
209
+ end
210
+ end
211
+ end
212
+ ```
213
+
118
214
  ## Supported ruby versions
119
215
 
120
216
  Blender-serf currently support the following MRI versions:
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'blender-serf'
7
- spec.version = '0.1.0'
7
+ spec.version = '0.2.0'
8
8
  spec.authors = ['Ranjib Dey']
9
9
  spec.email = ['ranjib@pagerduty.com']
10
10
  spec.summary = %q{Serf backend for blender}
@@ -47,7 +47,7 @@ module Blender
47
47
  raise ExecutionFailed, cmd.stderr
48
48
  end
49
49
  end
50
- cmd = @driver.run_command(task.stop_query.command, nodes)
50
+ cmd = @driver.run_command(task.reap_query.command, nodes)
51
51
  if cmd.exitstatus != 0 and !task.metadata[:ignore_failure]
52
52
  raise ExecutionFailed, cmd.stderr
53
53
  end
@@ -19,7 +19,7 @@ require 'blender/tasks/serf'
19
19
  module Blender
20
20
  module Task
21
21
  class SerfAsync < Blender::Task::Base
22
- attr_reader :start_query, :stop_query, :check_query
22
+ attr_reader :start_query, :reap_query, :check_query
23
23
 
24
24
  def initialize(name, options = {})
25
25
  super
@@ -29,11 +29,11 @@ module Blender
29
29
  @start_query.no_ack(metadata[:no_ack])
30
30
  @start_query.process(&metadata[:process])
31
31
 
32
- @stop_query = Blender::Task::Serf.new(name)
33
- @stop_query.payload(metadata[:stop])
34
- @stop_query.timeout(metadata[:timeout])
35
- @stop_query.no_ack(metadata[:no_ack])
36
- @stop_query.process(&metadata[:process])
32
+ @reap_query = Blender::Task::Serf.new(name)
33
+ @reap_query.payload(metadata[:reap])
34
+ @reap_query.timeout(metadata[:timeout])
35
+ @reap_query.no_ack(metadata[:no_ack])
36
+ @reap_query.process(&metadata[:process])
37
37
 
38
38
  @check_query = Blender::Task::Serf.new(name)
39
39
  @check_query.payload(metadata[:check])
@@ -42,12 +42,18 @@ module Blender
42
42
  @check_query.process(&metadata[:process])
43
43
  end
44
44
 
45
+ def query(event)
46
+ @start_query.query(event)
47
+ @reap_query.query(event)
48
+ @check_query.query(event)
49
+ end
50
+
45
51
  def start(&block)
46
52
  @start_query.instance_eval(&block)
47
53
  end
48
54
 
49
- def stop(&block)
50
- @stop_query.instance_eval(&block)
55
+ def reap(&block)
56
+ @reap_query.instance_eval(&block)
51
57
  end
52
58
 
53
59
  def check(&block)
@@ -61,19 +67,19 @@ module Blender
61
67
  end
62
68
 
63
69
  def retry_options(options = {})
64
- @metadata[:retry_options].merge!(options)
70
+ @metadata[:retry_options] = options
65
71
  end
66
72
 
67
73
  def default_metadata
68
74
  {
69
75
  ignore_failure: false,
70
76
  start: 'start',
71
- stop: 'stop',
77
+ reap: 'reap',
72
78
  check: 'check',
73
79
  timeout: 5,
74
80
  no_ack: false,
75
81
  process: nil,
76
- retry_options: { max_elapsed_time: 180 }
82
+ retry_options: { intervals: Array.new(5, 30) }
77
83
  }
78
84
  end
79
85
  end
@@ -61,7 +61,7 @@ describe Blender::Driver::Serf do
61
61
  conn = double('serf connection')
62
62
  ev = double('serf event')
63
63
  allow(ev).to receive(:body).and_return({'success' => true})
64
- %w{start stop check}.each do |payload|
64
+ %w{start reap check}.each do |payload|
65
65
  allow(conn).to receive(:query).with('chef', payload , Timeout: 5000000000, FilterNodes: ['node1']).and_yield(ev)
66
66
  end
67
67
  allow(Serfx).to receive(:connect).with(authkey: 'asyncexample').and_yield(conn)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blender-serf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ranjib Dey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-02 00:00:00.000000000 Z
11
+ date: 2015-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pd-blender
@@ -159,6 +159,7 @@ extra_rdoc_files: []
159
159
  files:
160
160
  - ".gitignore"
161
161
  - ".travis.yml"
162
+ - CHANGELOG.md
162
163
  - Gemfile
163
164
  - README.md
164
165
  - Rakefile
@@ -195,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
196
  version: '0'
196
197
  requirements: []
197
198
  rubyforge_project:
198
- rubygems_version: 2.2.2
199
+ rubygems_version: 2.4.5.1
199
200
  signing_key:
200
201
  specification_version: 4
201
202
  summary: Serf backend for blender