foreman-tasks 0.10.0 → 0.10.1

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +0 -2
  3. data/app/assets/javascripts/{trigger_form.js → foreman_tasks/trigger_form.js} +0 -0
  4. data/app/controllers/foreman_tasks/recurring_logics_controller.rb +6 -1
  5. data/app/controllers/foreman_tasks/tasks_controller.rb +16 -2
  6. data/app/lib/actions/proxy_action.rb +7 -0
  7. data/app/models/foreman_tasks/task/dynflow_task.rb +19 -4
  8. data/app/models/foreman_tasks/task/summarizer.rb +3 -1
  9. data/app/views/common/_trigger_form.html.erb +1 -1
  10. data/app/views/foreman_tasks/recurring_logics/index.html.erb +1 -2
  11. data/app/views/foreman_tasks/tasks/dashboard/_latest_tasks_in_error_warning.html.erb +1 -1
  12. data/app/views/foreman_tasks/tasks/dashboard/_tasks_status.html.erb +2 -0
  13. data/app/views/foreman_tasks/tasks/index.html.erb +1 -2
  14. data/config/routes.rb +1 -0
  15. data/foreman-tasks.gemspec +1 -3
  16. data/lib/foreman_tasks.rb +2 -1
  17. data/lib/foreman_tasks/dynflow.rb +2 -108
  18. data/lib/foreman_tasks/dynflow/configuration.rb +7 -142
  19. data/lib/foreman_tasks/dynflow/persistence.rb +3 -2
  20. data/lib/foreman_tasks/engine.rb +2 -2
  21. data/lib/foreman_tasks/version.rb +1 -1
  22. data/test/controllers/recurring_logics_controller_test.rb +14 -0
  23. data/test/controllers/tasks_controller_test.rb +17 -0
  24. data/test/unit/otp_manager_test.rb +70 -0
  25. metadata +12 -43
  26. data/bin/dynflow-executor +0 -71
  27. data/bin/foreman-tasks +0 -5
  28. data/deploy/foreman-tasks.init +0 -231
  29. data/deploy/foreman-tasks.service +0 -16
  30. data/deploy/foreman-tasks.sysconfig +0 -26
  31. data/lib/foreman_tasks/dynflow/daemon.rb +0 -143
  32. data/lib/foreman_tasks/tasks/dynflow.rake +0 -7
  33. data/test/unit/daemon_test.rb +0 -86
@@ -1,16 +0,0 @@
1
- [Unit]
2
- Description=Foreman jobs daemon
3
- Documentation=https://github.com/theforeman/foreman-tasks
4
- After=network.target remote-fs.target nss-lookup.target
5
-
6
- [Service]
7
- Type=forking
8
- User=foreman
9
- TimeoutSec=600
10
- WorkingDirectory=/usr/share/foreman
11
- ExecStart=/usr/bin/foreman-tasks start
12
- ExecStop=/usr/bin/foreman-tasks stop
13
- EnvironmentFile=-/etc/sysconfig/foreman-tasks
14
-
15
- [Install]
16
- WantedBy=multi-user.target
@@ -1,26 +0,0 @@
1
- FOREMAN_USER=foreman
2
- BUNDLER_EXT_HOME=/usr/share/foreman
3
- RAILS_RELATIVE_URL_ROOT=$FOREMAN_PREFIX
4
- RAILS_ENV=production
5
- FOREMAN_LOGGING=warn
6
- FOREMAN_LOGGING_SQL=warn
7
- FOREMAN_TASK_PARAMS="-p foreman"
8
- FOREMAN_LOG_DIR=/var/log/foreman
9
-
10
- RUBY_GC_MALLOC_LIMIT=4000100
11
- RUBY_GC_MALLOC_LIMIT_MAX=16000100
12
- RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=1.1
13
- RUBY_GC_OLDMALLOC_LIMIT=16000100
14
- RUBY_GC_OLDMALLOC_LIMIT_MAX=16000100
15
-
16
- #Set the number of executors you want to run
17
- #EXECUTORS_COUNT=1
18
-
19
- #Set memory limit for executor process, before it's restarted automatically
20
- #EXECUTOR_MEMORY_LIMIT=2gb
21
-
22
- #Set delay before first memory polling to let executor initialize (in sec)
23
- #EXECUTOR_MEMORY_MONITOR_DELAY=7200 #default: 2 hours
24
-
25
- #Set memory polling interval, process memory will be checked every N seconds.
26
- #EXECUTOR_MEMORY_MONITOR_INTERVAL=60
@@ -1,143 +0,0 @@
1
- require 'fileutils'
2
- require 'daemons'
3
- require 'get_process_mem'
4
- require 'dynflow/watchers/memory_consumption_watcher'
5
-
6
- module ForemanTasks
7
- class Dynflow::Daemon
8
- attr_reader :dynflow_memory_watcher_class,
9
- :daemons_class
10
-
11
- # make Daemon dependency injection ready for testing purposes
12
- def initialize(
13
- dynflow_memory_watcher_class = ::Dynflow::Watchers::MemoryConsumptionWatcher,
14
- daemons_class = ::Daemons
15
- )
16
- @dynflow_memory_watcher_class = dynflow_memory_watcher_class
17
- @daemons_class = daemons_class
18
- end
19
-
20
- # load the Rails environment and initialize the executor
21
- # in this thread.
22
- def run(foreman_root = Dir.pwd, options = {})
23
- STDERR.puts('Starting Rails environment')
24
- foreman_env_file = File.expand_path('./config/environment.rb', foreman_root)
25
- unless File.exist?(foreman_env_file)
26
- raise "#{foreman_root} doesn't seem to be a foreman root directory"
27
- end
28
-
29
- STDERR.puts("Starting dynflow with the following options: #{options}")
30
-
31
- ForemanTasks.dynflow.executor!
32
-
33
- if options[:memory_limit] > 0
34
- ForemanTasks.dynflow.config.on_init do |world|
35
- memory_watcher = initialize_memory_watcher(world, options[:memory_limit], options)
36
- world.terminated.on_completion do
37
- STDERR.puts("World has been terminated")
38
- memory_watcher = nil # the object can be disposed
39
- end
40
- end
41
- end
42
-
43
- require foreman_env_file
44
- STDERR.puts("Everything ready for world: #{(ForemanTasks.dynflow.initialized? ? ForemanTasks.dynflow.world.id : nil)}")
45
- sleep
46
- ensure
47
- STDERR.puts('Exiting')
48
- end
49
-
50
- # run the executor as a daemon
51
- def run_background(command = 'start', options = {})
52
- options = default_options.merge(options)
53
- FileUtils.mkdir_p(options[:pid_dir])
54
- begin
55
- require 'daemons'
56
- rescue LoadError
57
- raise "You need to add gem 'daemons' to your Gemfile if you wish to use it."
58
- end
59
-
60
- unless %w[start stop restart run].include?(command)
61
- raise "Command exptected to be 'start', 'stop', 'restart', 'run', was #{command.inspect}"
62
- end
63
-
64
- STDERR.puts("Dynflow Executor: #{command} in progress")
65
-
66
- options[:executors_count].times do
67
- daemons_class.run_proc(
68
- options[:process_name],
69
- daemons_options(command, options)
70
- ) do |*_args|
71
- begin
72
- ::Logging.reopen
73
- run(options[:foreman_root], options)
74
- rescue => e
75
- STDERR.puts e.message
76
- Foreman::Logging.exception('Failed running foreman-tasks daemon', e)
77
- exit 1
78
- end
79
- end
80
- end
81
- end
82
-
83
- protected
84
-
85
- def world
86
- ForemanTasks.dynflow.world
87
- end
88
-
89
- private
90
-
91
- def daemons_options(command, options)
92
- {
93
- :multiple => true,
94
- :dir => options[:pid_dir],
95
- :log_dir => options[:log_dir],
96
- :dir_mode => :normal,
97
- :monitor => true,
98
- :log_output => true,
99
- :log_output_syslog => true,
100
- :monitor_interval => [options[:memory_polling_interval] / 2, 30].min,
101
- :ARGV => [command]
102
- }
103
- end
104
-
105
- def default_options
106
- {
107
- foreman_root: Dir.pwd,
108
- process_name: 'dynflow_executor',
109
- pid_dir: "#{Rails.root}/tmp/pids",
110
- log_dir: File.join(Rails.root, 'log'),
111
- wait_attempts: 300,
112
- wait_sleep: 1,
113
- executors_count: (ENV['EXECUTORS_COUNT'] || 1).to_i,
114
- memory_limit: begin
115
- (ENV['EXECUTOR_MEMORY_LIMIT'] || '').to_gb.gigabytes
116
- rescue RuntimeError
117
- ENV['EXECUTOR_MEMORY_LIMIT'].to_i
118
- end,
119
- memory_init_delay: (ENV['EXECUTOR_MEMORY_MONITOR_DELAY'] || 7200).to_i, # 2 hours
120
- memory_polling_interval: (ENV['EXECUTOR_MEMORY_MONITOR_INTERVAL'] || 60).to_i
121
- }
122
- end
123
-
124
- def initialize_memory_watcher(world, memory_limit, options)
125
- watcher_options = {}
126
- watcher_options[:polling_interval] = options[:memory_polling_interval]
127
- watcher_options[:initial_wait] = options[:memory_init_delay]
128
- watcher_options[:memory_checked_callback] = ->(current_memory, memory_limit) { log_memory_within_limit(current_memory, memory_limit) }
129
- watcher_options[:memory_limit_exceeded_callback] = ->(current_memory, memory_limit) { log_memory_limit_exceeded(current_memory, memory_limit) }
130
- dynflow_memory_watcher_class.new(world, memory_limit, watcher_options)
131
- end
132
-
133
- def log_memory_limit_exceeded(current_memory, memory_limit)
134
- message = "Memory level exceeded, registered #{current_memory} bytes, which is greater than #{memory_limit} limit."
135
- Foreman::Logging.logger('foreman-tasks').error(message)
136
- end
137
-
138
- def log_memory_within_limit(current_memory, memory_limit)
139
- message = "Memory level OK, registered #{current_memory} bytes, which is less than #{memory_limit} limit."
140
- Foreman::Logging.logger('foreman-tasks').debug(message)
141
- end
142
- end
143
- end
@@ -1,7 +0,0 @@
1
- namespace :foreman_tasks do
2
- namespace :dynflow do
3
- task :executor do
4
- ForemanTasks::Dynflow::Daemon.new.run
5
- end
6
- end
7
- end
@@ -1,86 +0,0 @@
1
- require 'test_helper'
2
-
3
- class DaemonTest < ActiveSupport::TestCase
4
- setup do
5
- @dynflow_memory_watcher = mock('memory_watcher')
6
- @daemons = mock('daemons')
7
- @daemon = ForemanTasks::Dynflow::Daemon.new(
8
- @dynflow_memory_watcher,
9
- @daemons
10
- )
11
- @world_class = mock('dummy world factory')
12
- @dummy_world = Dynflow::Testing::DummyWorld.new
13
- @dummy_world.stubs(:auto_execute)
14
- @dummy_world.stubs(:terminated).returns(Concurrent.event)
15
- @world_class.stubs(:new).returns(@dummy_world)
16
- @dynflow = ForemanTasks::Dynflow.new(@world_class)
17
- ForemanTasks.stubs(:dynflow).returns(@dynflow)
18
- @dynflow.require!
19
- end
20
-
21
- test 'run command creates a watcher if memory_limit option specified' do
22
- current_folder = File.expand_path('../', __FILE__)
23
-
24
- @dynflow_memory_watcher.expects(:new).with do |_world, memory_limit, _watcher_options|
25
- memory_limit == 1000
26
- end
27
- @daemon.stubs(:sleep).returns(true) # don't pause the execution
28
-
29
- @daemon.run(current_folder, memory_limit: 1000)
30
- # initialization should be performed inside the foreman environment,
31
- # which is mocked here
32
- @dynflow.initialize!
33
- end
34
-
35
- test 'run command sets parameters to watcher' do
36
- current_folder = File.expand_path('../', __FILE__)
37
-
38
- @dynflow_memory_watcher.expects(:new).with do |_world, memory_limit, watcher_options|
39
- memory_limit == 1000 &&
40
- watcher_options[:polling_interval] == 100 &&
41
- watcher_options[:initial_wait] == 200
42
- end
43
- @daemon.stubs(:sleep).returns(true) # don't pause the execution
44
-
45
- @daemon.run(
46
- current_folder,
47
- memory_limit: 1000,
48
- memory_polling_interval: 100,
49
- memory_init_delay: 200
50
- )
51
- # initialization should be performed inside the foreman environment,
52
- # which is mocked here
53
- @dynflow.initialize!
54
- end
55
-
56
- test 'run_background command executes run with all params set as a daemon' do
57
- @daemon.expects(:run).twice.with do |_folder, options|
58
- options[:memory_limit] == 1000 &&
59
- options[:memory_init_delay] == 100 &&
60
- options[:memory_polling_interval] == 200
61
- end
62
- @daemons.expects(:run_proc).twice.yields
63
-
64
- @daemon.run_background(
65
- 'start',
66
- executors_count: 2,
67
- memory_limit: 1000,
68
- memory_init_delay: 100,
69
- memory_polling_interval: 200
70
- )
71
- end
72
-
73
- test 'default options read values from ENV' do
74
- ENV['EXECUTORS_COUNT'] = '2'
75
- ENV['EXECUTOR_MEMORY_LIMIT'] = '1gb'
76
- ENV['EXECUTOR_MEMORY_MONITOR_DELAY'] = '3'
77
- ENV['EXECUTOR_MEMORY_MONITOR_INTERVAL'] = '4'
78
-
79
- actual = @daemon.send(:default_options)
80
-
81
- assert_equal 2, actual[:executors_count]
82
- assert_equal 1.gigabytes, actual[:memory_limit]
83
- assert_equal 3, actual[:memory_init_delay]
84
- assert_equal 4, actual[:memory_polling_interval]
85
- end
86
- end