kitchen_hooks 1.6.3 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41cdc71627aae3524cbbb5642a0cf9364f5aa376
4
- data.tar.gz: a6882ae0519cb298638dd1ab76007794e26bf563
3
+ metadata.gz: 57e367c61cc0d252a78fa6a7a934347f702b59bd
4
+ data.tar.gz: e3c96ae9eb5a51e064f968d564c7f90772ffd57e
5
5
  SHA512:
6
- metadata.gz: 756af65131d98a742e2fb059368961e17a9ec1f0a4efce9ee2207770168c86e2fb162b658771facdddb739d3a686ce497c82be9a248211a768084086c8ec0174
7
- data.tar.gz: 126a1a40db93e80992c4521cf5e032de4dd6613d8edaf0b4a85a47ed7c85e8e4cd21de206b8c53bd8137b8039942614ea8b52803402abe1dc71e59264d7d9647
6
+ metadata.gz: 0448e0bd79eddca8a029766ee64bfb6ce9767795492be28e13a91925c06b59ad1bfbe387d43f13097ffc4ddf6e01d06500db95e34124dd4c641a6222ebc7ab08
7
+ data.tar.gz: 37295349df30512542481063ddc17cf69a3c7fb0a171ddf7dcbe5bf664336fd1b72e4fe7420a5082fea59458b51e41dc071c1b9325a79efd17f0901116d85224
data/Readme.md CHANGED
@@ -122,6 +122,7 @@ The `server` command also exposes some options for Sinatra configuration. See
122
122
  ### 1.6
123
123
 
124
124
  * First public release
125
+ * Parallelize most operations
125
126
  * Add requests to backlog for serial processing
126
127
 
127
128
  #### 1.5
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.6.3
1
+ 1.7.0
data/etc/config.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "hipchat": null,
3
3
  "knives": {
4
- "user": "~/.chef/knife.rb"
4
+ "bng11": "~/.chef/bng11.rb",
5
+ "dc1": "~/.chef/dc1.rb"
5
6
  }
6
7
  }
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.add_runtime_dependency 'daybreak', '~> 0.3'
18
18
  s.add_runtime_dependency 'retryable', '~> 2'
19
19
  s.add_runtime_dependency 'berkshelf', '~> 3'
20
- s.add_runtime_dependency 'chef', '~> 11.16.4'
20
+ s.add_runtime_dependency 'chef', '~> 12.0.0'
21
21
  s.add_runtime_dependency 'thor', '~> 0'
22
22
  s.add_runtime_dependency 'git', '~> 1.2'
23
23
  s.add_runtime_dependency 'sinatra', '~> 1.4'
@@ -9,6 +9,8 @@ require 'sinatra/base'
9
9
  require_relative 'helpers'
10
10
  require_relative 'metadata'
11
11
 
12
+ Thread.abort_on_exception = true
13
+
12
14
 
13
15
  module KitchenHooks
14
16
  class App < Sinatra::Application
@@ -23,6 +25,7 @@ module KitchenHooks
23
25
  def self.tmp! dir ; @@tmp = dir end
24
26
 
25
27
  def self.close!
28
+ @@sync_worker.kill
26
29
  @@backlog_worker.kill
27
30
  @@db.close
28
31
  end
@@ -37,7 +40,18 @@ module KitchenHooks
37
40
  end
38
41
  end
39
42
 
43
+ def self.sync!
44
+ @@sync_worker = Thread.new do
45
+ loop do
46
+ process_sync
47
+ sleep @@sync_interval
48
+ end
49
+ end
50
+ end
51
+
52
+
40
53
  def self.config! config
54
+ @@config = config
41
55
  @@hipchat = nil
42
56
  if config['hipchat']
43
57
  @@hipchat = HipChat::Client.new config['hipchat']['token']
@@ -47,6 +61,7 @@ module KitchenHooks
47
61
  @@knives = config['knives'].map do |_, knife|
48
62
  Pathname.new(knife).expand_path.realpath.to_s
49
63
  end
64
+ @@sync_interval = config.fetch 'sync_interval', 3600 # Hourly
50
65
  end
51
66
 
52
67
  get '/backlog' do
@@ -103,6 +118,7 @@ module KitchenHooks
103
118
  color = case entry[:type]
104
119
  when 'failure' ; 'red'
105
120
  when 'release' ; 'purple'
121
+ when 'unsynced' ; 'yellow'
106
122
  else ; 'green'
107
123
  end
108
124
  hipchat notification(entry), color
@@ -133,6 +149,20 @@ module KitchenHooks
133
149
  end
134
150
 
135
151
 
152
+ def self.process_sync
153
+ sync = sync_servers(knives).status
154
+
155
+ if sync.nil?
156
+ mark "Couldn't sync Chef servers (unknown issue)", 'unsynced'
157
+ return
158
+ end
159
+
160
+ sync_tag = sync[:num_failures].zero? ? 'synced' : 'unsynced'
161
+
162
+ mark sync, sync_tag
163
+ end
164
+
165
+
136
166
  def self.process event
137
167
  if event.nil? # JSON parse failed
138
168
  mark event, 'failure', 'Could not parse WebHook payload'
@@ -10,12 +10,43 @@ require 'berkshelf'
10
10
  require 'sinatra/base'
11
11
  require 'pmap'
12
12
 
13
+ require_relative 'helpers/sync_servers'
13
14
 
14
15
  Celluloid.logger = nil
15
16
  Berkshelf.logger = Logger.new $stdout
16
17
 
18
+
19
+
17
20
  module KitchenHooks
18
21
  class App < Sinatra::Application
22
+
23
+ def self.pluralize n, singular, plural=nil
24
+ plural = "#{singular}s" if plural.nil?
25
+ return "no #{plural}" if n.zero?
26
+ return "1 #{singular}" if n == 1
27
+ "#{n} #{plural}"
28
+ end
29
+
30
+ # http://stackoverflow.com/questions/4136248/how-to-generate-a-human-readable-time-range-using-ruby-on-rails
31
+ def self.humanize_seconds secs
32
+ [
33
+ [ 60, :seconds ],
34
+ [ 60, :minutes ],
35
+ [ 24, :hours ],
36
+ [ 1000, :days ]
37
+ ].map { |count, name|
38
+ if secs > 0
39
+ secs, n = secs.divmod(count)
40
+ "#{n.to_i} #{name}"
41
+ end
42
+ }.compact.reverse.join(' ')
43
+ end
44
+
45
+ def self.sync_servers knives
46
+ SyncServers.new knives
47
+ end
48
+
49
+
19
50
  def self.report_error e, msg=nil
20
51
  msg = e.message if msg.nil?
21
52
  $stdout.puts msg
@@ -304,7 +335,19 @@ module KitchenHooks
304
335
  def self.notification entry
305
336
  return entry[:error] if entry[:error]
306
337
  event = entry[:event]
338
+
307
339
  case entry[:type]
340
+ when 'synced', 'unsynced'
341
+ if event.is_a? String
342
+ event
343
+ else
344
+ 'Synced <b>%d</b> of <b>%d</b> nodes (%s, %s elapsed)' % [
345
+ event[:num_successes],
346
+ event[:num_nodes],
347
+ pluralize(event[:num_failures], 'failure'),
348
+ humanize_seconds(event[:elapsed])
349
+ ]
350
+ end
308
351
  when 'kitchen upload'
309
352
  %Q| <i>#{author(event)}</i> updated <a href="#{gitlab_url(event)}">the Kitchen</a> |
310
353
  when 'cookbook upload'
@@ -0,0 +1,64 @@
1
+ require 'ridley'
2
+
3
+ require 'set'
4
+
5
+
6
+ class SyncServers
7
+ attr_reader :status
8
+
9
+
10
+ def initialize knives
11
+ @knives = knives
12
+ @started = Time.now
13
+ @status = sync_servers.merge \
14
+ elapsed: Time.now - @started
15
+ end
16
+
17
+
18
+ private
19
+
20
+ def ridleys
21
+ @ridleys ||= @knives.map do |knife|
22
+ Ridley.from_chef_config(knife)
23
+ end
24
+ end
25
+
26
+ def all_nodes
27
+ @all_nodes ||= ridleys.flat_map do |ridley|
28
+ ridley.partial_search(:node, '*:*', %w[ ohai_time ])
29
+ end
30
+ end
31
+
32
+
33
+ def merged_nodes
34
+ @merged_nodes ||= all_nodes.group_by(&:name).pmap do |name, copies|
35
+ copies.sort_by { |c| c.automatic.ohai_time }.last
36
+ end
37
+ end
38
+
39
+
40
+ def sync_servers
41
+ nodes = merged_nodes
42
+ failures = Set.new
43
+
44
+ nodes.peach(8) do |n|
45
+ n.reload
46
+ ridleys.peach(4) do |ridley|
47
+ ridley.node.create(n) \
48
+ rescue ridley.node.update(n) \
49
+ rescue failures << n.name
50
+ end
51
+ puts 'Synced node "%s"' % n.name
52
+ end
53
+
54
+ return {
55
+ failures: failures,
56
+ num_successes: nodes.length - failures.length,
57
+ num_failures: failures.length,
58
+ num_nodes: nodes.length
59
+ }
60
+ rescue
61
+ return nil
62
+ end
63
+
64
+ end
@@ -61,10 +61,11 @@ module KitchenHooks
61
61
  desc: 'Location of temporary directory',
62
62
  default: '/tmp'
63
63
  def server
64
+ App.config! JSON::parse(File.read(options.config))
64
65
  App.backlog!
65
66
  App.db! options.database
66
67
  App.tmp! options.tmpdir
67
- App.config! JSON::parse(File.read(options.config))
68
+ App.sync!
68
69
  App.set :environment, options.environment
69
70
  App.set :port, options.port
70
71
  App.set :bind, options.bind
@@ -10,6 +10,10 @@ body {
10
10
  background: #d9534f;
11
11
  }
12
12
 
13
+ .unsynced .cd-timeline-img {
14
+ background: #f0ad4e;
15
+ }
16
+
13
17
  .release .cd-timeline-img {
14
18
  background: #5bc0de;
15
19
  }
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0"?>
2
+ <svg width="800" height="800" xmlns="http://www.w3.org/2000/svg">
3
+ <g>
4
+ <title>background</title>
5
+ <rect x="-1" y="-1" width="802" height="802" id="canvas_background" fill="none"/>
6
+ </g>
7
+
8
+ <g>
9
+ <title>Layer 1</title>
10
+ <path id="cloud-5-icon" d="m709.958801,397.394226c-12.598816,-158.646255 -221.498688,-210.920303 -306.884827,-75.072937c-55.378632,-31.311005 -126.010834,5.526672 -130.436066,70.253632c-60.718811,7.439392 -107.756332,59.146332 -107.756332,121.873932c0,67.83905 54.990204,122.829346 122.829361,122.829346l384.973877,0c67.835327,0 122.827454,-54.990295 122.827454,-122.829346c0.002014,-54.838409 -35.941895,-101.266602 -85.553467,-117.054626zm-591.126747,143.131042c-65.176666,-6.489807 -115.318749,-60.720673 -115.318749,-126.443329c0,-57.07019 37.981427,-106.291473 91.172333,-121.91629c14.955742,-50.987915 68.608047,-80.878265 119.807449,-67.225845c30.647736,-36.243652 75.486191,-57.308533 123.855881,-57.308533c44.846069,0 85.705231,18.275543 115.236084,47.994858c-17.300964,7.968079 -33.211975,18.15062 -47.62381,30.420929c-19.500092,-15.799637 -43.733093,-23.289108 -67.612274,-23.289108c-69.332733,0 -97.812119,52.479721 -104.920914,72.575729c-28.264053,-40.766861 -104.982407,-9.986542 -89.084747,44.580872c-47.595016,-8.629364 -85.703339,27.202789 -85.703339,74.167389c0,35.530396 25.891945,65.111328 60.782272,70.918701c-3.256432,18.646515 -3.39489,37.287445 -0.590187,55.524628z" fill="#ffffff"/>
11
+ </g>
12
+ </svg>
data/web/views/app.erb CHANGED
@@ -16,6 +16,10 @@
16
16
  <img src="/vendor/img/error.svg" alt="Error">
17
17
  <% when 'release' %>
18
18
  <img src="/vendor/img/cube.svg" alt="Cube">
19
+ <% when 'synced' %>
20
+ <img src="/vendor/img/sync.svg" alt="Sync">
21
+ <% when 'unsynced' %>
22
+ <img src="/vendor/img/sync.svg" alt="Sync">
19
23
  <% end %>
20
24
  </div>
21
25
  <div class="cd-timeline-content">
@@ -26,6 +30,10 @@
26
30
  <p><%= notification entry %></p>
27
31
  <% elsif type == 'release' %>
28
32
  <p><%= notification entry %></p>
33
+ <% elsif type == 'synced' %>
34
+ <p><%= notification entry %></p>
35
+ <% elsif type == 'unsynced' %>
36
+ <p><%= notification entry %></p>
29
37
  <% else %>
30
38
  <p><%= notification entry %> by pushing <%= push_details(entry[:event]) %></p>
31
39
  <% end %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen_hooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.3
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Clemmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-04 00:00:00.000000000 Z
11
+ date: 2015-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hipchat
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 11.16.4
75
+ version: 12.0.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 11.16.4
82
+ version: 12.0.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: thor
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -171,6 +171,7 @@ files:
171
171
  - lib/kitchen_hooks.rb
172
172
  - lib/kitchen_hooks/app.rb
173
173
  - lib/kitchen_hooks/helpers.rb
174
+ - lib/kitchen_hooks/helpers/sync_servers.rb
174
175
  - lib/kitchen_hooks/main.rb
175
176
  - lib/kitchen_hooks/metadata.rb
176
177
  - web/app/kitchen_hooks.js
@@ -183,6 +184,7 @@ files:
183
184
  - web/public/vendor/img/cutlery.svg
184
185
  - web/public/vendor/img/error.svg
185
186
  - web/public/vendor/img/shield.svg
187
+ - web/public/vendor/img/sync.svg
186
188
  - web/public/vendor/js/bootstrap-v3.3.0.js
187
189
  - web/public/vendor/js/jquery-timeago-v1.4.1.js
188
190
  - web/public/vendor/js/jquery-v2.1.1.js