foreman-tasks 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
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