itamae 1.8.0 → 1.9.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: 1638b5d146f89a94ea442567a8d7f54b5e770055
4
- data.tar.gz: 88b9dbfc9d74db2008e89c3dd31ca4da5fe05640
3
+ metadata.gz: be707f952f0626bb44b015cee0d20e52458d732e
4
+ data.tar.gz: 1c12830f1a14ce7dacc5c10bf90f33e1cae17398
5
5
  SHA512:
6
- metadata.gz: 98f3995c772b038282d7afc6f4741ae1360000bbe3ac022e8bf159f26819c87c4bfbabf7dcaa9384dd62a2adae6b96de324553952ae45ae2a07911a671ea6e45
7
- data.tar.gz: 655e435f1a1e0976efb9f722dfa9b9b22179374721ef8b4730d9e0306b2cdaef5ae7950aaf85bc660e83463a83ac3838a2f28058e9e30d2ee37d8dc83b36ca90
6
+ metadata.gz: 052278ea06cccc8065d3452fec345eead2ff9ca5dd0a77bc447d9bb699f5c4de8efb20ca5648a36ef73a70e96eec3788895d1ef12053f920e92b046819905bef
7
+ data.tar.gz: d52c51210ae9ae7b6a99ee1c14be97a2f0fea28ceb596fc8bb66eee2b7668d21bcdb183100a597ba39852bb75fd283aa17ecd59c77e39c9bed28cd3e0c1124a3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## v1.9.0
2
+
3
+ Features
4
+
5
+ - [New resource: `http_request` resource (by @hico-horiuchi)](https://github.com/itamae-kitchen/itamae/pull/180)
6
+ - [Introduce Handler which handles events from Itamae (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/181)
7
+ - Compatibility can be broken because this is experimental feature
8
+
9
+ Improvements
10
+
11
+ - [Optimize `git` resource for fixed revision (by @k0kubun)](https://github.com/itamae-kitchen/itamae/pull/182)
12
+ - Rename `--dot` option to `--recipe-graph` option. (by @ryotarai)
13
+ - Compatibility can be broken because this is experimental feature
14
+
1
15
  ## v1.8.0
2
16
 
3
17
  Features
@@ -16,12 +30,13 @@ No change
16
30
 
17
31
  Features
18
32
 
19
- - `--profile` option (experimental)
33
+ - `--profile` option (by @ryotarai)
20
34
  - `--profile PATH` saves executed commands to `PATH` in JSON format
35
+ - Compatibility can be broken because this is experimental feature
21
36
 
22
37
  Bugfixes
23
38
 
24
- - [Suppress errors of `edit` action of `file` resource when the target file doesn't exist in `dry-run` mode](https://github.com/itamae-kitchen/itamae/pull/144)
39
+ - [Suppress errors of `edit` action of `file` resource when the target file doesn't exist in `dry-run` mode (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/144)
25
40
 
26
41
  ## v1.6.3
27
42
 
@@ -54,19 +69,19 @@ Improvements
54
69
 
55
70
  Improvements
56
71
 
57
- - [`include_recipe 'plugin_name'` loads `itamae/plugin/recipe/plugin_name/default.rb` too](https://github.com/itamae-kitchen/itamae/pull/162)
72
+ - [`include_recipe 'plugin_name'` loads `itamae/plugin/recipe/plugin_name/default.rb` too (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/162)
58
73
 
59
74
  ## v1.5.1
60
75
 
61
76
  Improvements
62
77
 
63
- - [Logger can be injected one which doesn't have `color` method.](https://github.com/itamae-kitchen/itamae/commit/7c50f376f69029836047f26ab0a46b41b928c0d3)
78
+ - [Logger can be injected one which doesn't have `color` method. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/commit/7c50f376f69029836047f26ab0a46b41b928c0d3)
64
79
 
65
80
  ## v1.5.0
66
81
 
67
82
  Improvements
68
83
 
69
- - [Make a logger injectable from outside of Itamae.](https://github.com/itamae-kitchen/itamae/pull/160)
84
+ - [Make a logger injectable from outside of Itamae. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/160)
70
85
 
71
86
  ## v1.4.5
72
87
 
@@ -78,13 +93,13 @@ Improvements
78
93
 
79
94
  Features
80
95
 
81
- - `--shell` option for `local`, `ssh` and `docker` subcommands. If it is set, it will be used instead of /bin/sh
96
+ - `--shell` option for `local`, `ssh` and `docker` subcommands. If it is set, it will be used instead of /bin/sh (by @ryotarai)
82
97
 
83
98
  ## v1.4.3
84
99
 
85
100
  Bugfixes
86
101
 
87
- - [Restore original attributes of a resource after each action.](https://github.com/itamae-kitchen/itamae/commit/28d33da3cb67c6a7635e47845b0055cb17df53a8)
102
+ - [Restore original attributes of a resource after each action. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/commit/28d33da3cb67c6a7635e47845b0055cb17df53a8)
88
103
 
89
104
  ## v1.4.2
90
105
 
@@ -113,13 +128,13 @@ Improvements
113
128
 
114
129
  Bugfixes
115
130
 
116
- - `create` action of `file` resource without `content` attribute changes mode and owner without touching the content of the file
131
+ - `create` action of `file` resource without `content` attribute changes mode and owner without touching the content of the file (by @ryotarai)
117
132
 
118
133
  ## v1.3.5
119
134
 
120
135
  Improvements
121
136
 
122
- - [`create` action of `file` resource without `content` attribute changes mode and owner without touching the content of the file](https://github.com/itamae-kitchen/itamae/compare/itamae-kitchen:d4a0abc...itamae-kitchen:3eae144)
137
+ - [`create` action of `file` resource without `content` attribute changes mode and owner without touching the content of the file (by @ryotarai)](https://github.com/itamae-kitchen/itamae/compare/itamae-kitchen:d4a0abc...itamae-kitchen:3eae144)
123
138
 
124
139
  Bugfixes
125
140
 
@@ -129,7 +144,7 @@ Bugfixes
129
144
 
130
145
  Improvements
131
146
 
132
- - [Output stdout/err logs during command execution](https://github.com/itamae-kitchen/itamae/commit/24f140dd9744f30c645422959a6a72b6e31eacc4)
147
+ - [Output stdout/err logs during command execution (by @ryotarai)](https://github.com/itamae-kitchen/itamae/commit/24f140dd9744f30c645422959a6a72b6e31eacc4)
133
148
 
134
149
  ## v1.3.3
135
150
 
@@ -153,7 +168,7 @@ Features
153
168
 
154
169
  Improvements
155
170
 
156
- - Update `HOME` environment variable when `user` attribute is specified. (incompatible change)
171
+ - Update `HOME` environment variable when `user` attribute is specified. (incompatible change) (by @ryotarai)
157
172
 
158
173
  ## v1.2.21
159
174
 
@@ -166,7 +181,7 @@ Improvements
166
181
 
167
182
  Improvements
168
183
 
169
- - [Wrap host inventory value with Hashie::Mash to access it by a method call](https://github.com/itamae-kitchen/itamae/pull/135)
184
+ - [Wrap host inventory value with Hashie::Mash to access it by a method call (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/135)
170
185
 
171
186
  ## v1.2.19
172
187
 
@@ -178,7 +193,7 @@ Features
178
193
 
179
194
  Features
180
195
 
181
- - `run_command` method in a recipe, definition and resource
196
+ - `run_command` method in a recipe, definition and resource (by @ryotarai)
182
197
 
183
198
  ## v1.2.17
184
199
 
@@ -203,7 +218,7 @@ Bugfixes
203
218
 
204
219
  Features
205
220
 
206
- - "edit" action of "file" resource
221
+ - "edit" action of "file" resource (by @ryotarai)
207
222
 
208
223
  ## v1.2.13
209
224
 
@@ -215,8 +230,8 @@ Features
215
230
 
216
231
  Bugfixes
217
232
 
218
- - Run delayed notifications created by a delayed notification.
219
- - Set updated false after executing resources.
233
+ - Run delayed notifications created by a delayed notification. (by @ryotarai)
234
+ - Set updated false after executing resources. (by @ryotarai)
220
235
 
221
236
  ## v1.2.11
222
237
 
@@ -234,7 +249,7 @@ Bugfixes
234
249
 
235
250
  Bugfixes
236
251
 
237
- - Do not use local variable named `variables`.
252
+ - Do not use local variable named `variables`. (by @ryotarai)
238
253
 
239
254
  If `variables` is used as local variable's name, the following causes a syntax error.
240
255
 
@@ -261,31 +276,31 @@ Bugfixes
261
276
 
262
277
  ## v1.2.6
263
278
 
264
- - Remove code for debugging...
279
+ - Remove code for debugging... (by @ryotarai)
265
280
 
266
281
  ## v1.2.5
267
282
 
268
283
  Bugfixes
269
284
 
270
- - Bugs in definition feature.
285
+ - Bugs in definition feature. (by @ryotarai)
271
286
 
272
287
  ## v1.2.4
273
288
 
274
289
  Improvements
275
290
 
276
- - Use specinfra/core instead of specinfra.
291
+ - Use specinfra/core instead of specinfra. (by @ryotarai)
277
292
 
278
293
  ## v1.2.3
279
294
 
280
295
  Bugfixes
281
296
 
282
- - Bugs in Node class
297
+ - Bugs in Node class (by @ryotarai)
283
298
 
284
299
  ## v1.2.2
285
300
 
286
301
  Improvements
287
302
 
288
- - Refactor Backend and Runner class for multi backends.
303
+ - Refactor Backend and Runner class for multi backends. (by @ryotarai)
289
304
 
290
305
  ## v1.2.1
291
306
 
@@ -295,41 +310,42 @@ Improvements
295
310
 
296
311
  Feature
297
312
 
298
- - Docker backend
313
+ - Docker backend (by @ryotarai)
299
314
  - This backend builds a Docker image.
300
315
  - Usage: `itamae docker --image baseimage recipe.rb`
301
316
  - NOTE: This feature is experimental.
317
+ - Compatibility can be broken because this is experimental feature
302
318
 
303
319
  ## v1.1.26
304
320
 
305
321
  Bugfix
306
322
 
307
- - Always outdent.
323
+ - Always outdent. (by @ryotarai)
308
324
 
309
325
  ## v1.1.25
310
326
 
311
327
  Improvements
312
328
 
313
329
  - Make logging less verbose by default. (by @eagletmt)
314
- - Change indent width from 3 to 2.
330
+ - Change indent width from 3 to 2. (by @ryotarai)
315
331
 
316
332
  ## v1.1.24
317
333
 
318
334
  Bugfixes
319
335
 
320
- - Make `node` accessible from define block.
336
+ - Make `node` accessible from define block. (by @ryotarai)
321
337
 
322
338
  ## v1.1.23
323
339
 
324
340
  Feature
325
341
 
326
- - Validate node attributes by `Node#validate!`
342
+ - Validate node attributes by `Node#validate!` (by @ryotarai)
327
343
 
328
344
  ## v1.1.22
329
345
 
330
346
  Improvements
331
347
 
332
- - `source :auto` accepts a template without .erb extention.
348
+ - `source :auto` accepts a template without .erb extention. (by @ryotarai)
333
349
 
334
350
  ## v1.1.21
335
351
 
@@ -342,7 +358,7 @@ Bugfixes
342
358
 
343
359
  Features
344
360
 
345
- - `source :auto` of remote_file and template resources.
361
+ - `source :auto` of remote_file and template resources. (by @ryotarai)
346
362
  - details: https://github.com/itamae-kitchen/itamae/issues/94
347
363
 
348
364
  ## v1.1.19
@@ -350,22 +366,22 @@ Features
350
366
  Features
351
367
 
352
368
  - `verify` attribute
353
- - command will be executed after running resource action.
369
+ - command will be executed after running resource action. (by @ryotarai)
354
370
  - If it fails, Itamae will abort (notifications will not be executed)
355
371
 
356
372
  Improvements
357
373
 
358
374
  - [`--vagrant` option without `--host` assumes the VM name `default` (by @muratayusuke)](https://github.com/itamae-kitchen/itamae/pull/91)
359
- - `delayed` is a valid notification timing.
375
+ - `delayed` is a valid notification timing. (by @ryotarai)
360
376
  - same as Chef
361
- - If invalid notification timing is provided, an error will be raised.
377
+ - If invalid notification timing is provided, an error will be raised. (by @ryotarai)
362
378
 
363
379
  ## v1.1.18
364
380
 
365
381
  Improvements
366
382
 
367
383
  - [Add remove action to package resource (by @eagletmt)](https://github.com/itamae-kitchen/itamae/pull/92)
368
- - Colorize diff output of file resource
384
+ - Colorize diff output of file resource (by @ryotarai)
369
385
  - removed lines in red
370
386
  - inserted lines in green
371
387
 
@@ -373,58 +389,59 @@ Improvements
373
389
 
374
390
  Bugfixes
375
391
 
376
- - Do not remove space char in output of diff.
392
+ - Do not remove space char in output of diff. (by @ryotarai)
377
393
 
378
394
  ## v1.1.16
379
395
 
380
396
  Features
381
397
 
382
- - `source` attribute of `gem_package` resource.
398
+ - `source` attribute of `gem_package` resource. (by @ryotarai)
383
399
 
384
400
  ## v1.1.15
385
401
 
386
402
  Features
387
403
 
388
- - Implement `gem_package` resource.
404
+ - Implement `gem_package` resource. (by @ryotarai)
389
405
 
390
406
  ## v1.1.14
391
407
 
392
408
  Improvements
393
409
 
394
- - Start a service only if the service is not running.
395
- - Stop a service only if the service is running.
410
+ - Start a service only if the service is not running. (by @ryotarai)
411
+ - Stop a service only if the service is running. (by @ryotarai)
396
412
 
397
413
  ## v1.1.13
398
414
 
399
415
  Improvements
400
416
 
401
- - [Set executed attr of execute resource for logging purpose.](https://github.com/itamae-kitchen/itamae/pull/86)
402
- - [Colorize diff output of file resource green.](https://github.com/itamae-kitchen/itamae/pull/87)
417
+ - [Set executed attr of execute resource for logging purpose. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/86)
418
+ - [Colorize diff output of file resource green. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/87)
403
419
 
404
420
  ## v1.1.12
405
421
 
406
422
  Bugfixes
407
423
 
408
- - [Update home directory of user resource if changed.](https://github.com/itamae-kitchen/itamae/commit/0b5ad5245af8a7849d36d0598f06b7adb9ac025a)
424
+ - [Update home directory of user resource if changed. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/commit/0b5ad5245af8a7849d36d0598f06b7adb9ac025a)
409
425
 
410
426
  ## v1.1.11
411
427
 
412
428
  Bugfixes
413
429
 
414
- - [Do not include recipes which are already included.](https://github.com/itamae-kitchen/itamae/pull/85)
430
+ - [Do not include recipes which are already included. (by @ryotarai)](https://github.com/itamae-kitchen/itamae/pull/85)
415
431
  - This may break backward compatibility.
416
432
 
417
433
  ## v1.1.10
418
434
 
419
435
  Feature
420
436
 
421
- - `--dot` option to write dependency graph of recipes (Experimental)
437
+ - `--dot` option to write dependency graph of recipes
438
+ - Compatibility can be broken because this is experimental feature
422
439
 
423
440
  ## v1.1.9
424
441
 
425
442
  Improvements
426
443
 
427
- - Show template file path when rendering the template fails.
444
+ - Show template file path when rendering the template fails. (by @ryotarai)
428
445
 
429
446
  ## v1.1.8
430
447
 
@@ -436,7 +453,7 @@ Improvements
436
453
 
437
454
  Bugfixes
438
455
 
439
- - Fix a typo bug
456
+ - Fix a typo bug (by @ryotarai)
440
457
 
441
458
  ## v1.1.6 (yanked)
442
459
 
@@ -452,8 +469,8 @@ Bugfixes
452
469
 
453
470
  Bugfixes
454
471
 
455
- - Clear current attributes before each action.
456
- - Turn on updated-flag after each action.
472
+ - Clear current attributes before each action. (by @ryotarai)
473
+ - Turn on updated-flag after each action. (by @ryotarai)
457
474
 
458
475
  ## v1.1.4
459
476
 
@@ -473,17 +490,17 @@ Features
473
490
 
474
491
  Features
475
492
 
476
- - `user` resource accepts group name (String) as its `gid`.
493
+ - `user` resource accepts group name (String) as its `gid`. (by @ryotarai)
477
494
 
478
495
  ## v1.1.1
479
496
 
480
497
  Features
481
498
 
482
- - New resource `remote_directory` which transfers a directory from local to remote like `remote_file` resource. (Thanks to @k0kubun)
499
+ - New resource `remote_directory` which transfers a directory from local to remote like `remote_file` resource. (by @k0kubun)
483
500
  - https://github.com/ryotarai/itamae/pull/66
484
501
 
485
502
  ## v1.1.0
486
503
 
487
504
  Incompatible changes
488
505
 
489
- - `uid` and `gid` attributes of `user` resource accept only Integer. (https://github.com/ryotarai/itamae/pull/65)
506
+ - [`uid` and `gid` attributes of `user` resource accept only Integer. (by @ryotarai)](https://github.com/ryotarai/itamae/pull/65)
data/itamae.gemspec CHANGED
@@ -30,4 +30,5 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "pry-byebug"
31
31
  spec.add_development_dependency "docker-api", "~> 1.20"
32
32
  spec.add_development_dependency "fakefs"
33
+ spec.add_development_dependency "fluent-logger"
33
34
  end
data/lib/itamae.rb CHANGED
@@ -3,6 +3,8 @@ require "itamae/runner"
3
3
  require "itamae/cli"
4
4
  require "itamae/recipe"
5
5
  require "itamae/resource"
6
+ require "itamae/handler"
7
+ require "itamae/handler_proxy"
6
8
  require "itamae/recipe_children"
7
9
  require "itamae/logger"
8
10
  require "itamae/node"
data/lib/itamae/cli.rb CHANGED
@@ -17,7 +17,7 @@ module Itamae
17
17
  end
18
18
 
19
19
  def self.define_exec_options
20
- option :dot, type: :string, default: nil, desc: "[EXPERIMENTAL] Only write dependency graph in DOT", banner: "PATH"
20
+ option :recipe_graph, type: :string, desc: "[EXPERIMENTAL] Write recipe dependency graph in DOT", banner: "PATH"
21
21
  option :node_json, type: :string, aliases: ['-j']
22
22
  option :node_yaml, type: :string, aliases: ['-y']
23
23
  option :dry_run, type: :boolean, aliases: ['-n']
@@ -0,0 +1,21 @@
1
+ require 'itamae/handler/base'
2
+
3
+ module Itamae
4
+ module Handler
5
+ def self.from_type(type)
6
+ first_time = true
7
+
8
+ class_name = type.split('_').map(&:capitalize).join
9
+ self.const_get(class_name)
10
+ rescue NameError
11
+ require "itamae/handler/#{type}"
12
+
13
+ if first_time
14
+ first_time = false
15
+ retry
16
+ else
17
+ raise
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ require 'socket'
2
+
3
+ module Itamae
4
+ module Handler
5
+ class Base
6
+ attr_reader :recipes, :resources, :actions
7
+
8
+ def initialize(options)
9
+ @options = options
10
+
11
+ @recipes = []
12
+ @resources = []
13
+ @actions = []
14
+ end
15
+
16
+ def event(type, payload = {})
17
+ case type
18
+ when :recipe_started
19
+ @recipes << payload
20
+ when :recipe_completed, :recipe_failed
21
+ @recipes.pop
22
+ when :resource_started
23
+ @resources << payload
24
+ when :resource_completed, :resource_failed
25
+ @resources.pop
26
+ when :action_started
27
+ @actions << payload
28
+ when :action_completed, :action_failed
29
+ @actions.pop
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def hostname
36
+ @hostname ||= @options['hostname'] || Socket.gethostname
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,10 @@
1
+ module Itamae
2
+ module Handler
3
+ class Debug < Base
4
+ def event(type, payload = {})
5
+ super
6
+ Itamae.logger.info("EVENT:#{type} #{payload}")
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ module Itamae
2
+ module Handler
3
+ class Fluentd < Base
4
+ attr_accessor :fluent_logger # for test
5
+
6
+ def initialize(*)
7
+ super
8
+ load_fluent_logger
9
+ end
10
+
11
+ def event(type, payload = {})
12
+ super
13
+
14
+ unless @fluent_logger.post(type, payload.merge(hostname: hostname))
15
+ Itamae.logger.warn "Sending logs to Fluentd failed: #{@fluent_logger.last_error}"
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def load_fluent_logger
22
+ begin
23
+ require 'fluent-logger'
24
+ rescue LoadError
25
+ raise "Loading fluent-logger gem failed. Please install 'fluent-logger' gem to use fluentd handler."
26
+ end
27
+
28
+ @fluent_logger = Fluent::Logger::FluentLogger.new(tag_prefix, host: fluentd_host, port: fluentd_port)
29
+ end
30
+
31
+ def tag_prefix
32
+ @options['tag_prefix'] || 'itamae_server'
33
+ end
34
+
35
+ def fluentd_host
36
+ @options['host'] || 'localhost'
37
+ end
38
+
39
+ def fluentd_port
40
+ (@options['port'] || 24224).to_i
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ module Itamae
2
+ module Handler
3
+ class Json < Base
4
+ def initialize(*)
5
+ super
6
+ require 'time'
7
+ open_file
8
+ end
9
+
10
+ def event(type, payload = {})
11
+ super
12
+ @f.puts({'time' => Time.now.iso8601, 'event' => type, 'payload' => payload}.to_json)
13
+ end
14
+
15
+ private
16
+
17
+ def open_file
18
+ @f = open(@options.fetch('path'), 'a')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ module Itamae
2
+ class HandlerProxy
3
+ def initialize
4
+ @instances = []
5
+ end
6
+
7
+ def register_instance(instance)
8
+ @instances << instance
9
+ end
10
+
11
+ def event(*args, &block)
12
+ if block_given?
13
+ _event_with_block(*args, &block)
14
+ else
15
+ _event(*args)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def _event(*args)
22
+ @instances.each do |i|
23
+ i.event(*args)
24
+ end
25
+ end
26
+
27
+ def _event_with_block(event_name, *args, &block)
28
+ event("#{event_name}_started".to_sym, *args)
29
+ block.call
30
+ rescue
31
+ event("#{event_name}_failed".to_sym, *args)
32
+ raise
33
+ else
34
+ event("#{event_name}_completed".to_sym, *args)
35
+ end
36
+ end
37
+ end
38
+
data/lib/itamae/recipe.rb CHANGED
@@ -61,9 +61,11 @@ module Itamae
61
61
  def run
62
62
  show_banner
63
63
 
64
- Itamae.logger.with_indent do
65
- @children.run
66
- run_delayed_notifications
64
+ @runner.handler.event(:recipe, path: @path) do
65
+ Itamae.logger.with_indent do
66
+ @children.run
67
+ run_delayed_notifications
68
+ end
67
69
  end
68
70
  end
69
71
 
@@ -60,24 +60,24 @@ module Itamae
60
60
  end
61
61
 
62
62
  # returns dependencies graph in DOT
63
- def deps_in_dot
63
+ def dependency_in_dot
64
64
  result = ""
65
65
  result << "digraph recipes {\n"
66
66
  result << " rankdir=LR;\n"
67
- result << _deps_in_dot
67
+ result << _dependency_in_dot
68
68
  result << "}"
69
69
 
70
70
  result
71
71
  end
72
72
 
73
- def _deps_in_dot
73
+ def _dependency_in_dot
74
74
  result = ""
75
75
 
76
76
  recipes(recursive: false).each do |recipe|
77
77
  recipe.children.recipes(recursive: false).each do |child_recipe|
78
78
  result << %{ "#{recipe.path}" -> "#{child_recipe.path}";\n}
79
79
  end
80
- result << recipe.children._deps_in_dot
80
+ result << recipe.children._dependency_in_dot
81
81
  end
82
82
 
83
83
  result
@@ -6,6 +6,7 @@ require 'itamae/resource/remote_directory'
6
6
  require 'itamae/resource/remote_file'
7
7
  require 'itamae/resource/directory'
8
8
  require 'itamae/resource/template'
9
+ require 'itamae/resource/http_request'
9
10
  require 'itamae/resource/execute'
10
11
  require 'itamae/resource/service'
11
12
  require 'itamae/resource/link'
@@ -121,26 +121,31 @@ module Itamae
121
121
  end
122
122
 
123
123
  def run(specific_action = nil)
124
- Itamae.logger.debug "#{resource_type}[#{resource_name}]"
125
-
126
- Itamae.logger.with_indent_if(Itamae.logger.debug?) do
127
- if do_not_run_because_of_only_if?
128
- Itamae.logger.debug "#{resource_type}[#{resource_name}] Execution skipped because of only_if attribute"
129
- return
130
- elsif do_not_run_because_of_not_if?
131
- Itamae.logger.debug "#{resource_type}[#{resource_name}] Execution skipped because of not_if attribute"
132
- return
133
- end
124
+ runner.handler.event(:resource, resource_type: resource_type, resource_name: resource_name) do
125
+ Itamae.logger.debug "#{resource_type}[#{resource_name}]"
126
+
127
+ Itamae.logger.with_indent_if(Itamae.logger.debug?) do
128
+ if do_not_run_because_of_only_if?
129
+ Itamae.logger.debug "#{resource_type}[#{resource_name}] Execution skipped because of only_if attribute"
130
+ return
131
+ elsif do_not_run_because_of_not_if?
132
+ Itamae.logger.debug "#{resource_type}[#{resource_name}] Execution skipped because of not_if attribute"
133
+ return
134
+ end
135
+
136
+ [specific_action || attributes.action].flatten.each do |action|
137
+ run_action(action)
138
+ end
134
139
 
135
- [specific_action || attributes.action].flatten.each do |action|
136
- run_action(action)
140
+ verify unless runner.dry_run?
141
+ if updated?
142
+ notify
143
+ runner.handler.event(:resource_updated)
144
+ end
137
145
  end
138
146
 
139
- verify unless runner.dry_run?
140
- notify if updated?
147
+ @updated = false
141
148
  end
142
-
143
- @updated = false
144
149
  rescue Backend::CommandExecutionError
145
150
  Itamae.logger.error "#{resource_type}[#{resource_name}] Failed."
146
151
  exit 2
@@ -151,15 +156,7 @@ module Itamae
151
156
  end
152
157
 
153
158
  def resource_type
154
- humps = []
155
- self.class.name.split("::").last.each_char do |c|
156
- if "A" <= c && c <= "Z"
157
- humps << c.downcase
158
- else
159
- humps.last << c
160
- end
161
- end
162
- humps.join('_')
159
+ self.class.name.split("::").last.scan(/[A-Z][^A-Z]+/).map(&:downcase).join('_')
163
160
  end
164
161
 
165
162
  private
@@ -167,45 +164,50 @@ module Itamae
167
164
  alias_method :current, :current_attributes
168
165
 
169
166
  def run_action(action)
170
- original_attributes = @attributes # preserve and restore later
171
- @current_action = action
167
+ runner.handler.event(:action, action: action) do
168
+ original_attributes = @attributes # preserve and restore later
169
+ @current_action = action
172
170
 
173
- clear_current_attributes
171
+ clear_current_attributes
174
172
 
175
- Itamae.logger.debug "#{resource_type}[#{resource_name}] action: #{action}"
173
+ Itamae.logger.debug "#{resource_type}[#{resource_name}] action: #{action}"
176
174
 
177
- return if action == :nothing
175
+ return if action == :nothing
178
176
 
179
- Itamae.logger.with_indent_if(Itamae.logger.debug?) do
180
- Itamae.logger.debug "(in pre_action)"
181
- pre_action
177
+ Itamae.logger.with_indent_if(Itamae.logger.debug?) do
178
+ Itamae.logger.debug "(in pre_action)"
179
+ pre_action
182
180
 
183
- Itamae.logger.debug "(in set_current_attributes)"
184
- set_current_attributes
181
+ Itamae.logger.debug "(in set_current_attributes)"
182
+ set_current_attributes
185
183
 
186
- Itamae.logger.debug "(in show_differences)"
187
- show_differences
184
+ Itamae.logger.debug "(in show_differences)"
185
+ show_differences
188
186
 
189
- method_name = "action_#{action}"
190
- if runner.dry_run?
191
- unless respond_to?(method_name)
192
- Itamae.logger.error "action #{action.inspect} is unavailable"
193
- end
194
- else
195
- args = [method_name]
196
- if method(method_name).arity == 1
197
- # for plugin compatibility
198
- args << runner.options
187
+ method_name = "action_#{action}"
188
+ if runner.dry_run?
189
+ unless respond_to?(method_name)
190
+ Itamae.logger.error "action #{action.inspect} is unavailable"
191
+ end
192
+ else
193
+ args = [method_name]
194
+ if method(method_name).arity == 1
195
+ # for plugin compatibility
196
+ args << runner.options
197
+ end
198
+
199
+ public_send(*args)
199
200
  end
200
201
 
201
- public_send(*args)
202
+ if different?
203
+ updated!
204
+ runner.handler.event(:attribute_changed, from: @current_attributes, to: @attributes)
205
+ end
202
206
  end
203
207
 
204
- updated! if different?
208
+ @current_action = nil
209
+ @attributes = original_attributes
205
210
  end
206
-
207
- @current_action = nil
208
- @attributes = original_attributes
209
211
  end
210
212
 
211
213
  def clear_current_attributes
@@ -50,8 +50,8 @@ module Itamae
50
50
 
51
51
  super
52
52
 
53
- if current.exist && @temppath
54
- show_file_diff
53
+ if @temppath
54
+ compare_file
55
55
  end
56
56
  end
57
57
 
@@ -113,8 +113,14 @@ module Itamae
113
113
 
114
114
  private
115
115
 
116
- def show_file_diff
117
- diff = run_command(["diff", "-u", attributes.path, @temppath], error: false)
116
+ def compare_file
117
+ compare_to = if current.exist
118
+ attributes.path
119
+ else
120
+ '/dev/null'
121
+ end
122
+
123
+ diff = run_command(["diff", "-u", compare_to, @temppath], error: false)
118
124
  if diff.exit_status == 0
119
125
  # no change
120
126
  Itamae.logger.debug "file content will not change"
@@ -132,6 +138,7 @@ module Itamae
132
138
  Itamae.logger.info line.chomp
133
139
  end
134
140
  end
141
+ runner.handler.event(:file_content_changed, diff: diff.stdout)
135
142
  end
136
143
  end
137
144
 
@@ -33,13 +33,12 @@ module Itamae
33
33
  cmd << attributes.repository << attributes.destination
34
34
  run_command(cmd)
35
35
  new_repository = true
36
- else
37
- run_command_in_repo(['git', 'fetch', 'origin'])
38
36
  end
39
37
 
40
38
  target = if attributes.revision
41
39
  get_revision(attributes.revision)
42
40
  else
41
+ fetch_origin!
43
42
  run_command_in_repo("git ls-remote origin HEAD | cut -f1").stdout.strip
44
43
  end
45
44
 
@@ -52,6 +51,7 @@ module Itamae
52
51
  deploy_old_created = true
53
52
  end
54
53
 
54
+ fetch_origin!
55
55
  run_command_in_repo(["git", "checkout", target, "-b", DEPLOY_BRANCH])
56
56
 
57
57
  if deploy_old_created
@@ -82,6 +82,12 @@ module Itamae
82
82
  def get_revision(branch)
83
83
  run_command_in_repo("git rev-list #{shell_escape(branch)} | head -n1").stdout.strip
84
84
  end
85
+
86
+ def fetch_origin!
87
+ return if @origin_fetched
88
+ @origin_fetched = true
89
+ run_command_in_repo(['git', 'fetch', 'origin'])
90
+ end
85
91
  end
86
92
  end
87
93
  end
@@ -0,0 +1,19 @@
1
+ require 'itamae'
2
+ require 'open-uri'
3
+
4
+ module Itamae
5
+ module Resource
6
+ class HttpRequest < File
7
+ UrlNotFoundError = Class.new(StandardError)
8
+
9
+ define_attribute :headers, type: Hash, default: {}
10
+ define_attribute :url, type: String, required: true
11
+
12
+ def pre_action
13
+ attributes.content = open(attributes.url, attributes.headers).read
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/itamae/runner.rb CHANGED
@@ -11,17 +11,7 @@ module Itamae
11
11
  backend = Backend.create(backend_type, options)
12
12
  runner = self.new(backend, options)
13
13
  runner.load_recipes(recipe_files)
14
-
15
- if dot_file = options[:dot]
16
- runner.save_dependency_graph(dot_file)
17
- return
18
- end
19
-
20
14
  runner.run
21
-
22
- if profile = options[:profile]
23
- runner.save_profile(profile)
24
- end
25
15
  end
26
16
  end
27
17
 
@@ -30,11 +20,14 @@ module Itamae
30
20
  attr_reader :node
31
21
  attr_reader :tmpdir
32
22
  attr_reader :children
23
+ attr_reader :handler
33
24
 
34
25
  def initialize(backend, options)
35
26
  @backend = backend
36
27
  @options = options
37
28
 
29
+ prepare_handler
30
+
38
31
  @node = create_node
39
32
  @tmpdir = "/tmp/itamae_tmp"
40
33
  @children = RecipeChildren.new
@@ -58,8 +51,16 @@ module Itamae
58
51
  end
59
52
 
60
53
  def run
54
+ if recipe_graph_file = options[:recipe_graph]
55
+ save_dependency_graph(recipe_graph_file)
56
+ end
57
+
61
58
  children.run
62
59
  @backend.finalize
60
+
61
+ if profile = options[:profile]
62
+ save_profile(profile)
63
+ end
63
64
  end
64
65
 
65
66
  def dry_run?
@@ -67,9 +68,9 @@ module Itamae
67
68
  end
68
69
 
69
70
  def save_dependency_graph(path)
70
- Itamae.logger.info "Writing dependency graph in DOT to #{path}..."
71
+ Itamae.logger.info "Writing recipe dependency graph to #{path}..."
71
72
  open(path, 'w') do |f|
72
- f.write(runner.children.deps_in_dot)
73
+ f.write(children.dependency_in_dot)
73
74
  end
74
75
  end
75
76
 
@@ -108,5 +109,16 @@ module Itamae
108
109
 
109
110
  Node.new(hash, @backend)
110
111
  end
112
+
113
+ def prepare_handler
114
+ @handler = HandlerProxy.new
115
+ (@options[:handlers] || []).each do |handler|
116
+ type = handler.delete('type')
117
+ unless type
118
+ raise "#{type} field is not set"
119
+ end
120
+ @handler.register_instance(Handler.from_type(type).new(handler))
121
+ end
122
+ end
111
123
  end
112
124
  end
@@ -1 +1 @@
1
- 1.8.0
1
+ 1.9.0
@@ -70,6 +70,16 @@ describe file('/tmp/never_exist2') do
70
70
  it { should_not be_file }
71
71
  end
72
72
 
73
+ describe file('/tmp/http_request.html') do
74
+ it { should be_file }
75
+ its(:content) { should match(/"from": "itamae"/) }
76
+ end
77
+
78
+ describe file('/tmp/http_request_headers.html') do
79
+ it { should be_file }
80
+ its(:content) { should match(/"User-Agent": "Itamae"/) }
81
+ end
82
+
73
83
  describe file('/tmp/notifies') do
74
84
  it { should be_file }
75
85
  its(:content) { should eq("2431") }
@@ -156,6 +156,17 @@ end
156
156
 
157
157
  ######
158
158
 
159
+ http_request "/tmp/http_request.html" do
160
+ url "https://httpbin.org/get?from=itamae"
161
+ end
162
+
163
+ http_request "/tmp/http_request_headers.html" do
164
+ headers "User-Agent" => "Itamae"
165
+ url "https://httpbin.org/get"
166
+ end
167
+
168
+ ######
169
+
159
170
  service "cron" do
160
171
  action :stop
161
172
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Itamae::Handler::Base do
4
+ subject(:handler) { described_class.new({}) }
5
+
6
+ context "when receiving recipe_started event" do
7
+ it "stores the payload" do
8
+ subject.event(:recipe_started, :payload)
9
+ expect(subject.recipes).to eq([:payload])
10
+ end
11
+ end
12
+
13
+ context "when receiving recipe_completed event" do
14
+ before do
15
+ subject.event(:recipe_started, :payload)
16
+ end
17
+
18
+ it "pops the payload" do
19
+ subject.event(:recipe_completed, :payload)
20
+ expect(subject.recipes).to eq([])
21
+ end
22
+ end
23
+
24
+ context "when receiving recipe_failed event" do
25
+ before do
26
+ subject.event(:recipe_started, :payload)
27
+ end
28
+
29
+ it "pops the payload" do
30
+ subject.event(:recipe_failed, :payload)
31
+ expect(subject.recipes).to eq([])
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'itamae/handler/fluentd'
3
+
4
+ describe Itamae::Handler::Fluentd do
5
+ subject(:handler) do
6
+ described_class.new(options).tap do |h|
7
+ h.fluent_logger = fluent_logger
8
+ end
9
+ end
10
+ let(:options) { {'hostname' => 'me'} }
11
+ let(:fluent_logger) { Fluent::Logger::TestLogger.new }
12
+
13
+ describe '#event' do
14
+ it 'posts a record to fluent logger' do
15
+ subject.event(:type, {arg: 'value'})
16
+ expect(fluent_logger.queue).to eq([{arg: 'value', hostname: 'me'}])
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module Itamae
4
+ describe HandlerProxy do
5
+ let(:handler) { instance_double(Handler::Base) }
6
+ before { subject.register_instance(handler) }
7
+
8
+ describe "#event" do
9
+ context "with block" do
10
+ context "when the block completes" do
11
+ it "fires *_started and *_completed events" do
12
+ expect(handler).to receive(:event).with(:name_started, :arg)
13
+ expect(handler).to receive(:event).with(:name_completed, :arg)
14
+ subject.event(:name, :arg) { }
15
+ end
16
+ end
17
+
18
+ context "when the block fails" do
19
+ it "fires *_started and *_failed events" do
20
+ expect(handler).to receive(:event).with(:name_started, :arg)
21
+ expect(handler).to receive(:event).with(:name_failed, :arg)
22
+ expect {
23
+ subject.event(:name, :arg) { raise }
24
+ }.to raise_error
25
+ end
26
+ end
27
+ end
28
+
29
+ context "without block" do
30
+ it "fires the event" do
31
+ expect(handler).to receive(:event).with(:name, :arg)
32
+ subject.event(:name, :arg)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ module Itamae
4
+ describe Handler do
5
+ describe ".from_type" do
6
+ it "returns handler class" do
7
+ expect(described_class.from_type('debug')).to eq(Handler::Debug)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -100,14 +100,15 @@ end
100
100
  describe TestResource do
101
101
  subject(:resource) { described_class.new(recipe, "name") }
102
102
 
103
- let(:commands) { double(:commands) }
103
+ let(:handler) { Itamae::HandlerProxy.new }
104
104
  let(:runner) do
105
105
  instance_double(Itamae::Runner).tap do |r|
106
106
  allow(r).to receive(:dry_run?).and_return(false)
107
+ allow(r).to receive(:handler).and_return(handler)
107
108
  end
108
109
  end
109
110
  let(:recipe) do
110
- double(:recipe).tap do |r|
111
+ instance_double(Itamae::Recipe).tap do |r|
111
112
  allow(r).to receive(:runner).and_return(runner)
112
113
  end
113
114
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itamae
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Arai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-07 00:00:00.000000000 Z
11
+ date: 2015-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -184,6 +184,20 @@ dependencies:
184
184
  - - ">="
185
185
  - !ruby/object:Gem::Version
186
186
  version: '0'
187
+ - !ruby/object:Gem::Dependency
188
+ name: fluent-logger
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
187
201
  description:
188
202
  email:
189
203
  - ryota.arai@gmail.com
@@ -221,6 +235,12 @@ files:
221
235
  - lib/itamae/generators/templates/role/default.rb
222
236
  - lib/itamae/generators/templates/role/files/.keep
223
237
  - lib/itamae/generators/templates/role/templates/.keep
238
+ - lib/itamae/handler.rb
239
+ - lib/itamae/handler/base.rb
240
+ - lib/itamae/handler/debug.rb
241
+ - lib/itamae/handler/fluentd.rb
242
+ - lib/itamae/handler/json.rb
243
+ - lib/itamae/handler_proxy.rb
224
244
  - lib/itamae/logger.rb
225
245
  - lib/itamae/node.rb
226
246
  - lib/itamae/notification.rb
@@ -234,6 +254,7 @@ files:
234
254
  - lib/itamae/resource/gem_package.rb
235
255
  - lib/itamae/resource/git.rb
236
256
  - lib/itamae/resource/group.rb
257
+ - lib/itamae/resource/http_request.rb
237
258
  - lib/itamae/resource/link.rb
238
259
  - lib/itamae/resource/local_ruby_block.rb
239
260
  - lib/itamae/resource/package.rb
@@ -261,6 +282,10 @@ files:
261
282
  - spec/integration/recipes/templates/template_auto.erb
262
283
  - spec/integration/spec_helper.rb
263
284
  - spec/unit/lib/itamae/backend_spec.rb
285
+ - spec/unit/lib/itamae/handler/base_spec.rb
286
+ - spec/unit/lib/itamae/handler/fluentd_spec.rb
287
+ - spec/unit/lib/itamae/handler_proxy_spec.rb
288
+ - spec/unit/lib/itamae/handler_spec.rb
264
289
  - spec/unit/lib/itamae/node_spec.rb
265
290
  - spec/unit/lib/itamae/recipe_spec.rb
266
291
  - spec/unit/lib/itamae/resource/base_spec.rb
@@ -309,6 +334,10 @@ test_files:
309
334
  - spec/integration/recipes/templates/template_auto.erb
310
335
  - spec/integration/spec_helper.rb
311
336
  - spec/unit/lib/itamae/backend_spec.rb
337
+ - spec/unit/lib/itamae/handler/base_spec.rb
338
+ - spec/unit/lib/itamae/handler/fluentd_spec.rb
339
+ - spec/unit/lib/itamae/handler_proxy_spec.rb
340
+ - spec/unit/lib/itamae/handler_spec.rb
312
341
  - spec/unit/lib/itamae/node_spec.rb
313
342
  - spec/unit/lib/itamae/recipe_spec.rb
314
343
  - spec/unit/lib/itamae/resource/base_spec.rb