hybrid_platforms_conductor 32.17.1 → 32.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +3 -0
  4. data/bin/last_deploys +4 -1
  5. data/bin/nodes_to_deploy +5 -5
  6. data/docs/config_dsl.md +22 -0
  7. data/docs/gen/mermaid/README.md-0.png +0 -0
  8. data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
  9. data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
  10. data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
  11. data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
  12. data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
  13. data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
  14. data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
  15. data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
  16. data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
  17. data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
  18. data/docs/plugins.md +25 -0
  19. data/docs/plugins/log/remote_fs.md +26 -0
  20. data/lib/hybrid_platforms_conductor/actions_executor.rb +8 -1
  21. data/lib/hybrid_platforms_conductor/deployer.rb +96 -104
  22. data/lib/hybrid_platforms_conductor/hpc_plugins/log/my_log_plugin.rb.sample +100 -0
  23. data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +179 -0
  24. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +7 -20
  25. data/lib/hybrid_platforms_conductor/log.rb +31 -0
  26. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  27. data/spec/hybrid_platforms_conductor_test.rb +22 -6
  28. data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +24 -4
  29. data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +187 -212
  30. data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +223 -0
  31. data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +1 -1
  32. data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +146 -98
  33. data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +240 -83
  34. data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +2 -1
  35. data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +40 -53
  36. data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +2 -2
  37. data/spec/hybrid_platforms_conductor_test/test_log_no_read_plugin.rb +82 -0
  38. data/spec/hybrid_platforms_conductor_test/test_log_plugin.rb +103 -0
  39. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d66286a0b94c89bde4c7557a1b707158095363ccb854e3af5bdf951fe9065ee
4
- data.tar.gz: fa1976b8f50dd96a1717ec596540f3ae0cbb35c3b0d44b55e46e53f40e8a460d
3
+ metadata.gz: b724f6cb69633133e800d381ee1d0bfdd1a1107d7fc388fe1dcbcf423480ca9d
4
+ data.tar.gz: 3252bc11e083295c2694df60a9af790d8b01cbe851baebbe1d8e75b656e0acd3
5
5
  SHA512:
6
- metadata.gz: 2f2e172771aa4925c790d2faa57aaeca5da59914806787f8b19774af9a58ffb3e76766b66997e55a97602e05eeb7395f04c1f866c7a0acb17656adb87fdab8a2
7
- data.tar.gz: f61b8ede205e1cbbb863b2261fb7f8ad01d57b3cc319eec1fada0dcbcb99ce14384a5d74bbfaf86ef0aa5e3c0fbd5568933bf5ddf0c99e7deaa5e3db900e7e28
6
+ metadata.gz: 43793a4b3f8ec9a1353b4c075289dfcd77574b64a481754db68e1affa1c599500a3c29d8fa12b31c13dd69b47c5a2840f52aef80045fbec8be7a363ca4eb90b7
7
+ data.tar.gz: 0451da97325093d7a59684de1ffc77856f4baf5c3a4c76853e6df4492c7cfb1d52cbf9405c0d44b1d8af643e61f64569fc305ed61204be26f081591bdccb6d43
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [v32.18.0](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v32.17.1...v32.18.0) (2021-06-14 15:01:02)
2
+
3
+ ## Global changes
4
+ ### Patches
5
+
6
+ * [[Feature(log_remote_fs)] [#60] Add new plugins type log with a first log plugin remote_fs to extend deployment logs save functionality](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/20187c6da577c932b5205204187af883140995fe)
7
+
8
+ ## Changes for log_remote_fs
9
+ ### Features
10
+
11
+ * [[Feature(log_remote_fs)] [#60] Add new plugins type log with a first log plugin remote_fs to extend deployment logs save functionality](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/20187c6da577c932b5205204187af883140995fe)
12
+
1
13
  # [v32.17.1](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v32.17.0...v32.17.1) (2021-06-03 16:20:09)
2
14
 
3
15
  ### Patches
data/README.md CHANGED
@@ -263,6 +263,7 @@ participant PlatformHandler as Platform Handler
263
263
  participant PlatformRepo as Platform repository (ie Chef)
264
264
  participant Connector as Connector (ie SSH)
265
265
  participant Node as Provisioned node (my_node)
266
+ participant Log as Log
266
267
 
267
268
  Deploy->>+CMDB: Get services to be deployed on my_node
268
269
  CMDB->>+PlatformHandler: Get my_node metadata from the platform
@@ -276,6 +277,8 @@ Deploy->>+Connector: Connect to my_node to execute actions
276
277
  Connector->>+Node: Execute actions through SSH to deploy my_web_app on my_node
277
278
  Node-->>-Connector: my_web_app is deployed successfully
278
279
  Connector-->>-Deploy: Close connection
280
+ Deploy->>+Log: Save deployment logs
281
+ Log-->>-Deploy: Deployment logs saved
279
282
  ```
280
283
  </details>
281
284
  <!-- Mermaid generator - Section end -->
data/bin/last_deploys CHANGED
@@ -36,7 +36,10 @@ sorted_deploy_info = Hash[
36
36
  deployer.deployment_info_from(nodes_handler.select_nodes(executable.selected_nodes.empty? ? [{ all: true }] : executable.selected_nodes)).
37
37
  map do |node, deploy_info|
38
38
  decorated_deploy_info = deploy_info.merge(node: node)
39
- decorated_deploy_info[:date] = deploy_info[:date].strftime('%F %T') if deploy_info.key?(:date)
39
+ if deploy_info.key?(:deployment_info)
40
+ decorated_deploy_info.merge!(deploy_info[:deployment_info])
41
+ decorated_deploy_info[:date] = deploy_info[:date].strftime('%F %T') if deploy_info.key?(:date)
42
+ end
40
43
  decorated_deploy_info[:services] = deploy_info[:services].join(', ') if deploy_info.key?(:services)
41
44
  [node, decorated_deploy_info]
42
45
  end
data/bin/nodes_to_deploy CHANGED
@@ -60,16 +60,16 @@ unless ignore_deploy_info
60
60
  if node_deploy_info.key?(:error)
61
61
  executable.log_warn "[ #{node} ] - Deployment in error: #{node_deploy_info[:error]}"
62
62
  true
63
- elsif !node_deploy_info.key?(:exit_status) || node_deploy_info[:exit_status] != '0'
63
+ elsif !node_deploy_info.key?(:exit_status) || node_deploy_info[:exit_status] != 0
64
64
  executable.log_warn "[ #{node} ] - Last deployment did not end successfully: #{node_deploy_info[:exit_status]}"
65
65
  true
66
- elsif node_deploy_info.key?(:repo_name_0)
66
+ elsif node_deploy_info[:deployment_info].key?(:repo_name_0)
67
67
  node_impacted = false
68
68
  # Loop over all possible repositories concerned by this deployment
69
69
  repo_idx = 0
70
- while node_deploy_info.key?("repo_name_#{repo_idx}".to_sym) do
71
- repo_name = node_deploy_info["repo_name_#{repo_idx}".to_sym]
72
- commit_id = node_deploy_info["commit_id_#{repo_idx}".to_sym]
70
+ while node_deploy_info[:deployment_info].key?("repo_name_#{repo_idx}".to_sym) do
71
+ repo_name = node_deploy_info[:deployment_info]["repo_name_#{repo_idx}".to_sym]
72
+ commit_id = node_deploy_info[:deployment_info]["commit_id_#{repo_idx}".to_sym]
73
73
  impacted_nodes = cache_impacted_nodes.dig(repo_name, commit_id)
74
74
  if impacted_nodes.nil?
75
75
  begin
data/docs/config_dsl.md CHANGED
@@ -13,6 +13,7 @@ This DSL can also be completed by plugins. Check [the plugins documentations](pl
13
13
  * [`hybrid_platforms_dir`](#hybrid_platforms_dir)
14
14
  * [`tests_provisioner`](#tests_provisioner)
15
15
  * [`expect_tests_to_fail`](#expect_tests_to_fail)
16
+ * [`send_logs_to`](#send_logs_to)
16
17
  * [`retry_deploy_for_errors_on_stdout`](#retry_deploy_for_errors_on_stdout)
17
18
  * [`retry_deploy_for_errors_on_stderr`](#retry_deploy_for_errors_on_stderr)
18
19
  * [`packaging_timeout`](#packaging_timeout)
@@ -200,6 +201,27 @@ for_nodes('/tst/') do
200
201
  end
201
202
  ```
202
203
 
204
+ <a name="send_logs_to"></a>
205
+ ## `send_logs_to`
206
+
207
+ Set the list of [log plugins](plugins.md#log) to use to save logs.
208
+ By default (if no plugins is specifically set) the [log plugin `remote_fs`](plugins/log/remote_fs.md) is being used.
209
+
210
+ Takes the list of log plugin names, as symbols, as a parameter.
211
+
212
+ Can be applied to subset of nodes using the [`for_nodes` DSL method](#for_nodes).
213
+
214
+ Examples:
215
+ ```ruby
216
+ # By default, everything gets logged on the nodes
217
+ send_logs_to :remote_fs
218
+
219
+ # All our production nodes also have their logs uploaded on our logs servers
220
+ for_nodes('/prd/') do
221
+ send_logs_to :datadog_log_server, :loggly
222
+ end
223
+ ```
224
+
203
225
  <a name="retry_deploy_for_errors_on_stdout"></a>
204
226
  ## `retry_deploy_for_errors_on_stdout`
205
227
 
Binary file
data/docs/plugins.md CHANGED
@@ -10,6 +10,7 @@ Following are all possible plugin types and the plugins shipped by default with
10
10
  * [`action`](#action)
11
11
  * [`cmdb`](#cmdb)
12
12
  * [`connector`](#connector)
13
+ * [`log`](#log)
13
14
  * [`platform_handler`](#platform_handler)
14
15
  * [`provisioner`](#provisioner)
15
16
  * [`report`](#report)
@@ -79,6 +80,30 @@ Plugins shipped by default:
79
80
  * [`local`](plugins/connector/local.md)
80
81
  * [`ssh`](plugins/connector/ssh.md)
81
82
 
83
+ <a name="log"></a>
84
+ ## Logs
85
+
86
+ Save deployment logs to a given medium (files, log servers...).
87
+
88
+ Corresponding plugin type: `log`.
89
+
90
+ These plugins give ways for the [`Deployer`](../lib/hybrid_platforms_conductor/deployer.rb) to save logs output from services deployments on nodes.
91
+ Information that can be saved is:
92
+ * The deployment stdout.
93
+ * The deployment stderr.
94
+ * The deployment exit status.
95
+ * The list of services that have been deployed.
96
+ * Some deployment metadata (like git commits information that have been deployed).
97
+
98
+ Examples of log plugins are:
99
+ * Remote file system: Save logs on the node's remote file system (useful for local debugging).
100
+ * Log servers: Send logs to log servers.
101
+
102
+ Check the [sample plugin file](../lib/hybrid_platforms_conductor/hpc_plugins/log/my_log_plugin.rb.sample) to know more about the API that needs to be implemented by such plugins.
103
+
104
+ Plugins shipped by default:
105
+ * [`remote_fs`](plugins/log/remote_fs.md)
106
+
82
107
  <a name="platform_handler"></a>
83
108
  ## Platform Handlers
84
109
 
@@ -0,0 +1,26 @@
1
+ # Log plugin: `remote_fs`
2
+
3
+ The `remote_fs` log plugin saves deployment logs in each remote node that has been deployed, in the `/var/log/deployments` directory.
4
+
5
+ ## Config DSL extension
6
+
7
+ None
8
+
9
+ ## Used credentials
10
+
11
+ | Credential | Usage
12
+ | --- | --- |
13
+
14
+ ## Used Metadata
15
+
16
+ | Metadata | Type | Usage
17
+ | --- | --- | --- |
18
+
19
+ ## Used environment variables
20
+
21
+ | Variable | Usage
22
+ | --- | --- |
23
+
24
+ ## External tools dependencies
25
+
26
+ None
@@ -102,7 +102,14 @@ module HybridPlatformsConductor
102
102
  # * *progress_name* (String): Name to display on the progress bar [default: 'Executing actions']
103
103
  # Result::
104
104
  # * Hash<String, [Integer or Symbol, String, String]>: Exit status code (or Symbol in case of error or dry run), standard output and error for each node.
105
- def execute_actions(actions_per_nodes, timeout: nil, concurrent: false, log_to_dir: "#{@config.hybrid_platforms_dir}/run_logs", log_to_stdout: true, progress_name: 'Executing actions')
105
+ def execute_actions(
106
+ actions_per_nodes,
107
+ timeout: nil,
108
+ concurrent: false,
109
+ log_to_dir: "#{@config.hybrid_platforms_dir}/run_logs",
110
+ log_to_stdout: true,
111
+ progress_name: 'Executing actions'
112
+ )
106
113
  # Keep a list of nodes that will need remote access
107
114
  nodes_needing_connectors = []
108
115
  # Compute the ordered list of actions per selected node
@@ -21,12 +21,19 @@ module HybridPlatformsConductor
21
21
  # Extend the Config DSL
22
22
  module ConfigDSLExtension
23
23
 
24
+ # List of log plugins. Each info has the following properties:
25
+ # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
26
+ # * *log_plugins* (Array<Symbol>): List of log plugins to be used to store deployment logs.
27
+ # Array< Hash<Symbol, Object> >
28
+ attr_reader :deployment_logs
29
+
24
30
  # Integer: Timeout (in seconds) for packaging repositories
25
31
  attr_reader :packaging_timeout_secs
26
32
 
27
33
  # Mixin initializer
28
34
  def init_deployer_config
29
35
  @packaging_timeout_secs = 60
36
+ @deployment_logs = []
30
37
  end
31
38
 
32
39
  # Set the packaging timeout
@@ -37,6 +44,17 @@ module HybridPlatformsConductor
37
44
  @packaging_timeout_secs = packaging_timeout_secs
38
45
  end
39
46
 
47
+ # Set the deployment log plugins to be used
48
+ #
49
+ # Parameters::
50
+ # * *log_plugins* (Symbol or Array<Symbol>): The list of (or single) log plugins to be used
51
+ def send_logs_to(*log_plugins)
52
+ @deployment_logs << {
53
+ nodes_selectors_stack: current_nodes_selectors_stack,
54
+ log_plugins: log_plugins.flatten
55
+ }
56
+ end
57
+
40
58
  end
41
59
 
42
60
  include LoggerHelpers
@@ -94,6 +112,20 @@ module HybridPlatformsConductor
94
112
  @services_handler = services_handler
95
113
  @secrets = []
96
114
  @provisioners = Plugins.new(:provisioner, logger: @logger, logger_stderr: @logger_stderr)
115
+ @log_plugins = Plugins.new(
116
+ :log,
117
+ logger: @logger,
118
+ logger_stderr: @logger_stderr,
119
+ init_plugin: proc do |plugin_class|
120
+ plugin_class.new(
121
+ logger: @logger,
122
+ logger_stderr: @logger_stderr,
123
+ config: @config,
124
+ nodes_handler: @nodes_handler,
125
+ actions_executor: @actions_executor
126
+ )
127
+ end
128
+ )
97
129
  # Default values
98
130
  @use_why_run = false
99
131
  @timeout = nil
@@ -355,72 +387,31 @@ module HybridPlatformsConductor
355
387
  # * *nodes* (Array<String>): Nodes to get info from
356
388
  # Result::
357
389
  # * Hash<String, Hash<Symbol,Object>: The deployed info, per node name.
358
- # Properties are defined by the Deployer#save_logs method, and additionally to them the following properties can be set:
359
- # * *error* (String): Optional property set in case of error
390
+ # * *error* (String): Error string in case deployment logs could not be retrieved. If set then further properties will be ignored. [optional]
391
+ # * *services* (Array<String>): List of services deployed on the node
392
+ # * *deployment_info* (Hash<Symbol,Object>): Deployment metadata
393
+ # * *exit_status* (Integer or Symbol): Deployment exit status
394
+ # * *stdout* (String): Deployment stdout
395
+ # * *stderr* (String): Deployment stderr
360
396
  def deployment_info_from(*nodes)
397
+ nodes = nodes.flatten
361
398
  @actions_executor.max_threads = 64
362
- Hash[@actions_executor.
363
- execute_actions(
364
- Hash[nodes.flatten.map do |node|
365
- [
366
- node,
367
- { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
368
- ]
369
- end],
370
- log_to_stdout: false,
371
- concurrent: true,
372
- timeout: 10,
373
- progress_name: 'Getting deployment info'
374
- ).
375
- map do |node, (exit_status, stdout, stderr)|
376
- # Expected format for stdout:
377
- # Property1: Value1
378
- # ...
379
- # PropertyN: ValueN
380
- # ===== STDOUT =====
381
- # ...
382
- deploy_info = {}
383
- if exit_status.is_a?(Symbol)
384
- deploy_info[:error] = "Error: #{exit_status}\n#{stderr}"
385
- else
386
- stdout_lines = stdout.split("\n")
387
- if stdout_lines.first =~ /No such file or directory/
388
- deploy_info[:error] = '/var/log/deployments missing'
389
- else
390
- stdout_lines.each do |line|
391
- if line =~ /^([^:]+): (.+)$/
392
- key_str, value = $1, $2
393
- key = key_str.to_sym
394
- # Type-cast some values
395
- case key_str
396
- when 'date'
397
- # Date and time values
398
- # Thu Nov 23 18:43:01 UTC 2017
399
- deploy_info[key] = Time.parse(value)
400
- when 'debug'
401
- # Boolean values
402
- # Yes
403
- deploy_info[key] = (value == 'Yes')
404
- when /^diff_files_.+$/, 'services'
405
- # Array of strings
406
- # my_file.txt, other_file.txt
407
- deploy_info[key] = value.split(', ')
408
- else
409
- deploy_info[key] = value
410
- end
411
- else
412
- deploy_info[:unknown_lines] = [] unless deploy_info.key?(:unknown_lines)
413
- deploy_info[:unknown_lines] << line
414
- end
415
- end
416
- end
417
- end
418
- [
419
- node,
420
- deploy_info
421
- ]
422
- end
423
- ]
399
+ read_actions_results = @actions_executor.execute_actions(
400
+ Hash[nodes.map do |node|
401
+ master_log_plugin = @log_plugins[log_plugins_for(node).first]
402
+ master_log_plugin.respond_to?(:actions_to_read_logs) ? [node, master_log_plugin.actions_to_read_logs(node)] : nil
403
+ end.compact],
404
+ log_to_stdout: false,
405
+ concurrent: true,
406
+ timeout: 10,
407
+ progress_name: 'Read deployment logs'
408
+ )
409
+ Hash[nodes.map do |node|
410
+ [
411
+ node,
412
+ @log_plugins[log_plugins_for(node).first].logs_for(node, *(read_actions_results[node] || [nil, nil, nil]))
413
+ ]
414
+ end]
424
415
  end
425
416
 
426
417
  # Parse stdout and stderr of a given deploy run and get the list of tasks with their status
@@ -584,47 +575,48 @@ module HybridPlatformsConductor
584
575
  # * *services* (Hash<String, Array<String>>): List of services that have been deployed, per node
585
576
  def save_logs(logs, services)
586
577
  section "Saving deployment logs for #{logs.size} nodes" do
587
- Dir.mktmpdir('hybrid_platforms_conductor-logs') do |tmp_dir|
588
- ssh_user = @actions_executor.connector(:ssh).ssh_user
589
- @actions_executor.execute_actions(
590
- Hash[logs.map do |node, (exit_status, stdout, stderr)|
591
- # Create a log file to be scp with all relevant info
592
- now = Time.now.utc
593
- log_file = "#{tmp_dir}/#{node}_#{now.strftime('%F_%H%M%S')}_#{ssh_user}"
594
- services_info = @services_handler.log_info_for(node, services[node])
595
- File.write(
596
- log_file,
597
- services_info.merge(
598
- date: now.strftime('%F %T'),
599
- user: ssh_user,
600
- debug: log_debug? ? 'Yes' : 'No',
601
- services: services[node].join(', '),
602
- exit_status: exit_status
603
- ).map { |property, value| "#{property}: #{value}" }.join("\n") +
604
- "\n===== STDOUT =====\n" +
605
- (stdout || '') +
606
- "\n===== STDERR =====\n" +
607
- (stderr || '')
608
- )
609
- [
610
- node,
611
- {
612
- remote_bash: "#{ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "}mkdir -p /var/log/deployments",
613
- scp: {
614
- log_file => '/var/log/deployments',
615
- :sudo => ssh_user != 'root',
616
- :owner => 'root',
617
- :group => 'root'
618
- }
619
- }
620
- ]
621
- end],
622
- timeout: 10,
623
- concurrent: true,
624
- log_to_dir: nil
625
- )
626
- end
578
+ ssh_user = @actions_executor.connector(:ssh).ssh_user
579
+ @actions_executor.execute_actions(
580
+ Hash[logs.map do |node, (exit_status, stdout, stderr)|
581
+ [
582
+ node,
583
+ log_plugins_for(node).
584
+ map do |log_plugin|
585
+ @log_plugins[log_plugin].actions_to_save_logs(
586
+ node,
587
+ services[node],
588
+ @services_handler.log_info_for(node, services[node]).merge(
589
+ date: Time.now.utc.strftime('%F %T'),
590
+ user: ssh_user
591
+ ),
592
+ exit_status,
593
+ stdout,
594
+ stderr
595
+ )
596
+ end.
597
+ flatten(1)
598
+ ]
599
+ end],
600
+ timeout: 10,
601
+ concurrent: true,
602
+ log_to_dir: nil,
603
+ progress_name: 'Saving logs'
604
+ )
605
+ end
606
+ end
607
+
608
+ # Get the list of log plugins to be used for a given node
609
+ #
610
+ # Parameters::
611
+ # * *node* (String): The node for which log plugins are queried
612
+ # Result::
613
+ # * Array<Symbol>: The list of log plugins
614
+ def log_plugins_for(node)
615
+ node_log_plugins = @nodes_handler.select_confs_for_node(node, @config.deployment_logs).inject([]) do |log_plugins, deployment_logs_info|
616
+ log_plugins + deployment_logs_info[:log_plugins]
627
617
  end
618
+ node_log_plugins << :remote_fs if node_log_plugins.empty?
619
+ node_log_plugins
628
620
  end
629
621
 
630
622
  end