itamae 1.8.0 → 1.9.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: 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