kitchen_hooks 1.6.3 → 1.7.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: 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