smart_proxy_dynflow_core 0.2.1 → 0.2.6

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
- SHA1:
3
- metadata.gz: '08a1626af21a13a55a6cd092d7aa9f8d65e21db8'
4
- data.tar.gz: 8ca74216c0cb587d61b7c0049454b9a1204fa8c0
2
+ SHA256:
3
+ metadata.gz: 84ea792e8e6d9f6ddcd145428485d5faadf92da27acd184fa42956fa4873e7fd
4
+ data.tar.gz: 07adc8b3c623462086d0797455afaf822e27212bcdcda345a950df7e49296814
5
5
  SHA512:
6
- metadata.gz: 72a360aa24771a1bc0fc6d01a6aac0aa92e526c127487b7ff33d0afc80d53b72d1a83f3f585e0fe507ba846a9c50d58840369d464b5e9913b709591c6651154f
7
- data.tar.gz: f67485e909fedc9b7651c46cf5a9d16ae521cc6cadb78688a4a38a570b0f6889d336d254030d065fdff6ee126514b760b9677da9f1eb6f317993e567ad70856c
6
+ metadata.gz: 989f9619b041039a3897de03cac1edc5ce1415a19792b3a5b2e907b174b97472b3a56f19cd5cab9977c26e5d5c83c38636afe8c49186dbd2bfce1c7e3dbfcc84
7
+ data.tar.gz: 7caa3ee4ddce3560970bd8f7a7b8e2b99dd96f1fae456e78475673ec98478e0c608e5feb29442b7046e4eed07e61f0d9a009dade6646e534f6ef6f033192f572
data/Gemfile CHANGED
@@ -7,16 +7,15 @@ group :development do
7
7
  end
8
8
 
9
9
  group :test do
10
- gem 'smart_proxy_dynflow', :path => '.'
11
10
  gem 'smart_proxy', :git => "https://github.com/theforeman/smart-proxy", :branch => "develop"
11
+ gem 'smart_proxy_dynflow', :path => '.'
12
12
 
13
13
  if RUBY_VERSION < '2.1'
14
14
  gem 'public_suffix', '< 3'
15
- gem 'rubocop', '< 0.51.0'
16
15
  gem 'rainbow', '< 3'
17
16
  else
18
- gem 'rubocop', '~> 0.52.1'
19
17
  gem 'public_suffix'
18
+ gem 'rubocop', '~> 0.52.1'
20
19
  end
21
20
 
22
21
  if RUBY_VERSION < '2.2'
@@ -27,11 +26,11 @@ group :test do
27
26
  end
28
27
 
29
28
  if RUBY_VERSION < '2.2'
30
- gem 'sinatra', '< 2'
31
29
  gem 'rack', '>= 1.1', '< 2.0.0'
30
+ gem 'sinatra', '< 2'
32
31
  else
33
- gem 'sinatra'
34
32
  gem 'rack', '>= 1.1'
33
+ gem 'sinatra'
35
34
  end
36
35
 
37
36
  # load bundler.d
@@ -4,10 +4,9 @@ Documentation=https://github.com/theforeman/smart_proxy_dynflow
4
4
  After=network.target remote-fs.target nss-lookup.target
5
5
 
6
6
  [Service]
7
- Type=forking
7
+ Type=notify
8
8
  User=foreman-proxy
9
- PIDFile=/var/run/foreman-proxy/smart_proxy_dynflow_core.pid
10
- ExecStart=/usr/bin/smart_proxy_dynflow_core -d -p /var/run/foreman-proxy/smart_proxy_dynflow_core.pid
9
+ ExecStart=/usr/bin/smart_proxy_dynflow_core --no-daemonize
11
10
  EnvironmentFile=-/etc/sysconfig/smart_proxy_dynflow_core
12
11
 
13
12
  [Install]
@@ -1,4 +1,7 @@
1
+ raise LoadError, 'Ruby >= 2.1 is required' unless RUBY_VERSION >= '2.1'
2
+
1
3
  require 'dynflow'
4
+ require 'smart_proxy_dynflow_core/task_launcher_registry'
2
5
  require 'foreman_tasks_core'
3
6
  require 'smart_proxy_dynflow_core/log'
4
7
  require 'smart_proxy_dynflow_core/settings'
@@ -7,7 +10,9 @@ require 'smart_proxy_dynflow_core/helpers'
7
10
  require 'smart_proxy_dynflow_core/callback'
8
11
  require 'smart_proxy_dynflow_core/api'
9
12
 
10
- SmartProxyDynflowCore::Core.after_initialize do |dynflow_core|
11
- ForemanTasksCore.dynflow_setup(dynflow_core.world)
13
+ module SmartProxyDynflowCore
14
+ Core.after_initialize do |dynflow_core|
15
+ ForemanTasksCore.dynflow_setup(dynflow_core.world)
16
+ end
17
+ Core.register_silencer_matchers ForemanTasksCore.silent_dead_letter_matchers
12
18
  end
13
- SmartProxyDynflowCore::Core.register_silencer_matchers ForemanTasksCore.silent_dead_letter_matchers
@@ -3,11 +3,17 @@ require 'multi_json'
3
3
 
4
4
  module SmartProxyDynflowCore
5
5
  class Api < ::Sinatra::Base
6
+ TASK_UPDATE_REGEXP_PATH = %r{/tasks/(\S+)/(update|done)}
6
7
  helpers Helpers
7
8
 
8
9
  before do
9
- logger = Log.instance
10
- authorize_with_token || authorize_with_ssl_client
10
+ if match = request.path_info.match(TASK_UPDATE_REGEXP_PATH)
11
+ task_id = match[1]
12
+ action = match[2]
13
+ authorize_with_token(task_id: task_id, clear: action == 'done')
14
+ else
15
+ authorize_with_ssl_client
16
+ end
11
17
  content_type :json
12
18
  end
13
19
 
@@ -21,6 +27,13 @@ module SmartProxyDynflowCore
21
27
  MultiJson.dump(result)
22
28
  end
23
29
 
30
+ post "/tasks/launch/?" do
31
+ params = MultiJson.load(request.body.read)
32
+ launcher = launcher_class(params).new(world, callback_host(params, request), params.fetch('options', {}))
33
+ launcher.launch!(params['input'])
34
+ launcher.results.to_json
35
+ end
36
+
24
37
  post "/tasks/?" do
25
38
  params = MultiJson.load(request.body.read)
26
39
  trigger_task(::Dynflow::Utils.constantize(params['action_name']),
@@ -39,15 +52,30 @@ module SmartProxyDynflowCore
39
52
  tasks_count(params['state']).to_json
40
53
  end
41
54
 
42
- post "/tasks/:task_id/done" do |task_id|
55
+ # capturing post "/tasks/:task_id/(update|done)"
56
+ post TASK_UPDATE_REGEXP_PATH do |task_id, _action|
43
57
  data = MultiJson.load(request.body.read)
44
- complete_task(task_id, data)
58
+ dispatch_external_event(task_id, data)
59
+ end
60
+
61
+ get "/tasks/operations" do
62
+ TaskLauncherRegistry.operations.to_json
45
63
  end
46
64
 
47
65
  private
48
66
 
49
67
  def callback_host(params, request)
50
- params.fetch('action_input', {})['proxy_url'] || request.env.values_at('HTTP_X_FORWARDED_FOR', 'HTTP_HOST').compact.first
68
+ params.fetch('action_input', {})['proxy_url'] ||
69
+ request.env.values_at('HTTP_X_FORWARDED_FOR', 'HTTP_HOST').compact.first
70
+ end
71
+
72
+ def launcher_class(params)
73
+ operation = params.fetch('operation')
74
+ if TaskLauncherRegistry.key?(operation)
75
+ TaskLauncherRegistry.fetch(operation)
76
+ else
77
+ halt 404, MultiJson.dump(:error => "Unknown operation '#{operation}' requested.")
78
+ end
51
79
  end
52
80
  end
53
81
  end
@@ -1,5 +1,6 @@
1
1
  module SmartProxyDynflowCore
2
2
  class BundlerHelper
3
+ # rubocop:disable Metrics/PerceivedComplexity
3
4
  def self.require_groups(*groups)
4
5
  if File.exist?(File.expand_path('../../../Gemfile.in', __FILE__))
5
6
  # If there is a Gemfile.in file, we will not use Bundler but BundlerExt
@@ -25,5 +26,6 @@ module SmartProxyDynflowCore
25
26
  Bundler.require(*groups)
26
27
  end
27
28
  end
29
+ # rubocop:enable Metrics/PerceivedComplexity
28
30
  end
29
31
  end
@@ -1,23 +1,52 @@
1
1
  require 'rest-client'
2
2
 
3
+ # rubocop:disable Lint/HandleExceptions
3
4
  begin
4
5
  require 'smart_proxy_dynflow/callback'
5
6
  rescue LoadError
6
7
  end
8
+ # rubocop:enable Lint/HandleExceptions
7
9
 
8
10
  module SmartProxyDynflowCore
9
11
  module Callback
10
- class Action < Dynflow::Action
11
- def plan(callback, data)
12
- plan_self(:callback => callback, :data => data)
13
- end
12
+ class Request
13
+ class << self
14
+ def send_to_foreman_tasks(callback_info, data)
15
+ self.new.callback(prepare_payload(callback_info, data))
16
+ end
14
17
 
15
- def run
16
- Request.send_to_foreman_tasks(input[:callback], input[:data])
18
+ # rubocop:disable Metrics/PerceivedComplexity
19
+ def ssl_options
20
+ return @ssl_options if defined? @ssl_options
21
+ @ssl_options = {}
22
+ settings = Settings.instance
23
+ return @ssl_options unless URI.parse(settings.foreman_url).scheme == 'https'
24
+
25
+ @ssl_options[:verify_ssl] = OpenSSL::SSL::VERIFY_PEER
26
+
27
+ private_key_file = settings.foreman_ssl_key || settings.ssl_private_key
28
+ if private_key_file
29
+ private_key = File.read(private_key_file)
30
+ @ssl_options[:ssl_client_key] = OpenSSL::PKey::RSA.new(private_key)
31
+ end
32
+ certificate_file = settings.foreman_ssl_cert || settings.ssl_certificate
33
+ if certificate_file
34
+ certificate = File.read(certificate_file)
35
+ @ssl_options[:ssl_client_cert] = OpenSSL::X509::Certificate.new(certificate)
36
+ end
37
+ ca_file = settings.foreman_ssl_ca || settings.ssl_ca_file
38
+ @ssl_options[:ssl_ca_file] = ca_file if ca_file
39
+ @ssl_options
40
+ end
41
+ # rubocop:enable Metrics/PerceivedComplexity
42
+
43
+ private
44
+
45
+ def prepare_payload(callback, data)
46
+ { :callback => callback, :data => data }.to_json
47
+ end
17
48
  end
18
- end
19
49
 
20
- class Request
21
50
  def callback(payload)
22
51
  response = callback_resource.post(payload, :content_type => :json)
23
52
  if response.code.to_s != "200"
@@ -26,43 +55,12 @@ module SmartProxyDynflowCore
26
55
  response
27
56
  end
28
57
 
29
- def self.send_to_foreman_tasks(callback_info, data)
30
- self.new.callback(self.prepare_payload(callback_info, data))
31
- end
32
-
33
58
  private
34
59
 
35
- def self.prepare_payload(callback, data)
36
- { :callback => callback, :data => data }.to_json
37
- end
38
-
39
60
  def callback_resource
40
61
  @resource ||= RestClient::Resource.new(Settings.instance.foreman_url + '/foreman_tasks/api/tasks/callback',
41
62
  self.class.ssl_options)
42
63
  end
43
-
44
- def self.ssl_options
45
- return @ssl_options if defined? @ssl_options
46
- @ssl_options = {}
47
- settings = Settings.instance
48
- return @ssl_options unless URI.parse(settings.foreman_url).scheme == 'https'
49
-
50
- @ssl_options[:verify_ssl] = OpenSSL::SSL::VERIFY_PEER
51
-
52
- private_key_file = settings.foreman_ssl_key || settings.ssl_private_key
53
- if private_key_file
54
- private_key = File.read(private_key_file)
55
- @ssl_options[:ssl_client_key] = OpenSSL::PKey::RSA.new(private_key)
56
- end
57
- certificate_file = settings.foreman_ssl_cert || settings.ssl_certificate
58
- if certificate_file
59
- certificate = File.read(certificate_file)
60
- @ssl_options[:ssl_client_cert] = OpenSSL::X509::Certificate.new(certificate)
61
- end
62
- ca_file = settings.foreman_ssl_ca || settings.ssl_ca_file
63
- @ssl_options[:ssl_ca_file] = ca_file if ca_file
64
- @ssl_options
65
- end
66
64
  end
67
65
 
68
66
  class Action < ::Dynflow::Action
@@ -1,6 +1,5 @@
1
1
  module SmartProxyDynflowCore
2
2
  class Core
3
-
4
3
  attr_accessor :world, :accepted_cert_serial
5
4
 
6
5
  def initialize
@@ -25,7 +24,8 @@ module SmartProxyDynflowCore
25
24
 
26
25
  db_file = Settings.instance.database
27
26
  if db_file.nil? || db_file.empty?
28
- Log.instance.warn "Could not open DB for dynflow at '#{db_file}', will keep data in memory. Restart will drop all dynflow data."
27
+ Log.instance.warn "Could not open DB for dynflow at '#{db_file}', " \
28
+ "will keep data in memory. Restart will drop all dynflow data."
29
29
  else
30
30
  db_conn_string += "/#{db_file}"
31
31
  end
@@ -44,7 +44,7 @@ module SmartProxyDynflowCore
44
44
  config.persistence_adapter = persistence_adapter
45
45
  config.execution_plan_cleaner = execution_plan_cleaner
46
46
  # TODO: There has to be a better way
47
- matchers = config.silent_dead_letter_matchers.call().concat(self.class.silencer_matchers)
47
+ matchers = config.silent_dead_letter_matchers.call.concat(self.class.silencer_matchers)
48
48
  config.silent_dead_letter_matchers = matchers
49
49
  yield config if block_given?
50
50
  end
@@ -4,13 +4,14 @@ module SmartProxyDynflowCore
4
4
  SmartProxyDynflowCore::Core.world
5
5
  end
6
6
 
7
- def authorize_with_token
7
+ def authorize_with_token(task_id:, clear: true)
8
8
  if request.env.key? 'HTTP_AUTHORIZATION'
9
9
  if defined?(::ForemanTasksCore)
10
10
  auth = request.env['HTTP_AUTHORIZATION']
11
11
  basic_prefix = /\ABasic /
12
12
  if !auth.to_s.empty? && auth =~ basic_prefix &&
13
- ForemanTasksCore::OtpManager.authenticate(auth.gsub(basic_prefix, ''))
13
+ ForemanTasksCore::OtpManager.authenticate(auth.gsub(basic_prefix, ''),
14
+ expected_user: task_id, clear: clear)
14
15
  Log.instance.debug('authorized with token')
15
16
  return true
16
17
  end
@@ -21,7 +22,7 @@ module SmartProxyDynflowCore
21
22
  end
22
23
 
23
24
  def authorize_with_ssl_client
24
- if %w(yes on 1).include? request.env['HTTPS'].to_s
25
+ if %w[yes on 1].include? request.env['HTTPS'].to_s
25
26
  if request.env['SSL_CLIENT_CERT'].to_s.empty?
26
27
  Log.instance.error "No client SSL certificate supplied"
27
28
  halt 403, MultiJson.dump(:error => "No client SSL certificate supplied")
@@ -63,7 +64,7 @@ module SmartProxyDynflowCore
63
64
  { :count => tasks.count, :state => state }
64
65
  end
65
66
 
66
- def complete_task(task_id, params)
67
+ def dispatch_external_event(task_id, params)
67
68
  world.event(task_id,
68
69
  params['step_id'].to_i,
69
70
  ::ForemanTasksCore::Runner::ExternalEvent.new(params))
@@ -1,9 +1,13 @@
1
1
  require 'webrick/https'
2
2
  require 'smart_proxy_dynflow_core/bundler_helper'
3
3
  require 'smart_proxy_dynflow_core/settings'
4
- require 'smart_proxy_dynflow_core/webrick-patch'
4
+ require 'smart_proxy_dynflow_core/sd_notify'
5
+
5
6
  module SmartProxyDynflowCore
6
7
  class Launcher
8
+ CIPHERS = ['ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384',
9
+ 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256',
10
+ 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA'].freeze
7
11
 
8
12
  def self.launch!(options)
9
13
  self.new.start options
@@ -15,6 +19,7 @@ module SmartProxyDynflowCore
15
19
  install_usr1_trap
16
20
  Rack::Server.new(rack_settings).start do |_server|
17
21
  SmartProxyDynflowCore::Core.ensure_initialized
22
+ SmartProxyDynflowCore::SdNotify.new.tap { |sd| sd.ready if sd.active? }
18
23
  end
19
24
  end
20
25
 
@@ -79,11 +84,12 @@ module SmartProxyDynflowCore
79
84
  :AccessLog => [[Log.instance, WEBrick::AccessLog::COMMON_LOG_FORMAT]],
80
85
  :Logger => Log.instance,
81
86
  :daemonize => Settings.instance.daemonize,
82
- :pid => Settings.instance.pid_file,
87
+ :pid => Settings.instance.daemonize && Settings.instance.pid_file,
83
88
  :server => :webrick
84
89
  }
85
90
  end
86
91
 
92
+ # rubocop:disable Metrics/PerceivedComplexity
87
93
  def https_app
88
94
  ssl_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
89
95
  ssl_options |= OpenSSL::SSL::OP_CIPHER_SERVER_PREFERENCE if defined?(OpenSSL::SSL::OP_CIPHER_SERVER_PREFERENCE)
@@ -91,10 +97,11 @@ module SmartProxyDynflowCore
91
97
  ssl_options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
92
98
  ssl_options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
93
99
  ssl_options |= OpenSSL::SSL::OP_NO_TLSv1 if defined?(OpenSSL::SSL::OP_NO_TLSv1)
100
+ ssl_options |= OpenSSL::SSL::OP_NO_TLSv1_1 if defined?(OpenSSL::SSL::OP_NO_TLSv1_1)
94
101
 
95
102
  if Settings.instance.tls_disabled_versions
96
103
  Settings.instance.tls_disabled_versions.each do |version|
97
- constant = OpenSSL::SSL.const_get("OP_NO_TLSv#{version.to_s.gsub(/\./, '_')}") rescue nil
104
+ constant = OpenSSL::SSL.const_get("OP_NO_TLSv#{version.to_s.tr('.', '_')}") rescue nil
98
105
 
99
106
  if constant
100
107
  Log.instance.info "TLSv#{version} will be disabled."
@@ -111,9 +118,11 @@ module SmartProxyDynflowCore
111
118
  :SSLPrivateKey => ssl_private_key,
112
119
  :SSLCertificate => ssl_certificate,
113
120
  :SSLCACertificateFile => Settings.instance.ssl_ca_file,
121
+ :SSLCiphers => CIPHERS - SmartProxyDynflowCore::Settings.instance.ssl_disabled_ciphers,
114
122
  :SSLOptions => ssl_options
115
123
  }
116
124
  end
125
+ # rubocop:enable Metrics/PerceivedComplexity
117
126
 
118
127
  def https_enabled?
119
128
  Settings.instance.use_https
@@ -122,14 +131,16 @@ module SmartProxyDynflowCore
122
131
  def ssl_private_key
123
132
  OpenSSL::PKey::RSA.new(File.read(Settings.instance.ssl_private_key))
124
133
  rescue Exception => e
125
- Log.instance.fatal "Unable to load private SSL key. Are the values correct in settings.yml and do permissions allow reading?: #{e}"
134
+ Log.instance.fatal "Unable to load private SSL key. Are the values "\
135
+ "correct in settings.yml and do permissions allow reading?: #{e}"
126
136
  raise e
127
137
  end
128
138
 
129
139
  def ssl_certificate
130
140
  OpenSSL::X509::Certificate.new(File.read(Settings.instance.ssl_certificate))
131
141
  rescue Exception => e
132
- Log.instance.fatal "Unable to load SSL certificate. Are the values correct in settings.yml and do permissions allow reading?: #{e}"
142
+ Log.instance.fatal "Unable to load SSL certificate. Are the values " \
143
+ "correct in settings.yml and do permissions allow reading?: #{e}"
133
144
  raise e
134
145
  end
135
146
 
@@ -141,7 +152,7 @@ module SmartProxyDynflowCore
141
152
  Dir[File.join(dir, 'settings.d', '*.yml')].each { |path| Settings.load_plugin_settings(path) }
142
153
  true
143
154
  end
144
- ForemanTasksCore::SettingsLoader.settings_registry.keys.each do |settings_keys|
155
+ ForemanTasksCore::SettingsLoader.settings_registry.each_key do |settings_keys|
145
156
  settings = settings_keys.inject({}) do |h, settings_key|
146
157
  if SETTINGS.plugins.key?(settings_key.to_s)
147
158
  h.merge(SETTINGS.plugins[settings_key.to_s].to_h)
@@ -2,7 +2,6 @@ require 'logger'
2
2
 
3
3
  module SmartProxyDynflowCore
4
4
  class Log < ::Logger
5
-
6
5
  alias_method :write, :debug
7
6
 
8
7
  class << self
@@ -42,25 +41,45 @@ module SmartProxyDynflowCore
42
41
 
43
42
  def initialize(file, *rest)
44
43
  @file = file
45
- @fd = @file.kind_of?(IO) ? @file : File.open(@file, 'a')
44
+ @fd = @file.is_a?(IO) ? @file : File.open(@file, 'a')
46
45
  @fd.sync = true
47
46
  super(@fd, rest)
48
47
  end
49
48
 
50
49
  def roll_log
51
- unless @file.kind_of? IO
50
+ unless @file.is_a? IO
52
51
  @fd.reopen @file, 'a'
53
52
  @fd.sync = true
54
53
  end
55
54
  end
56
55
 
56
+ class ProxyStructuredFormater < ::Dynflow::LoggerAdapters::Formatters::Abstract
57
+ def call(_severity, _datetime, _prog_name, message)
58
+ if message.is_a?(::Exception)
59
+ subject = "#{message.message} (#{message.class})"
60
+ if @base.respond_to?(:exception)
61
+ @base.exception("Error details", message)
62
+ subject
63
+ else
64
+ "#{subject}\n#{message.backtrace.join("\n")}"
65
+ end
66
+ else
67
+ message
68
+ end
69
+ end
70
+
71
+ def format(message)
72
+ call(nil, nil, nil, message)
73
+ end
74
+ end
75
+
57
76
  class ProxyAdapter < ::Dynflow::LoggerAdapters::Simple
58
- def initialize(logger, level = Logger::DEBUG, formatters = [::Dynflow::LoggerAdapters::Formatters::Exception])
77
+ def initialize(logger, level = Logger::DEBUG, _formatters = [])
59
78
  @logger = logger
60
79
  @logger.level = level
61
- @logger.formatter = method(:formatter).to_proc
62
- @action_logger = apply_formatters ProgNameWrapper.new(@logger, ' action'), formatters
63
- @dynflow_logger = apply_formatters ProgNameWrapper.new(@logger, 'dynflow'), formatters
80
+ @logger.formatter = ProxyStructuredFormater.new(@logger)
81
+ @action_logger = apply_formatters(ProgNameWrapper.new(@logger, ' action'), [ProxyStructuredFormater])
82
+ @dynflow_logger = apply_formatters(ProgNameWrapper.new(@logger, 'dynflow'), [ProxyStructuredFormater])
64
83
  end
65
84
  end
66
85
  end
@@ -0,0 +1,33 @@
1
+ # Shamelessly taken from theforeman/smart-proxy @ 99e9e5b
2
+ # kudos to domcleal
3
+
4
+ require 'socket'
5
+
6
+ # Implementation of libsystemd's sd_notify API, sends current state via socket
7
+ module SmartProxyDynflowCore
8
+ class SdNotify
9
+ def active?
10
+ !ENV['NOTIFY_SOCKET'].nil?
11
+ end
12
+
13
+ def notify(message)
14
+ create_socket.tap do |socket|
15
+ socket.sendmsg(message.chomp + "\n") # ensure trailing \n
16
+ socket.close
17
+ end
18
+ end
19
+
20
+ def ready(state = 1)
21
+ notify("READY=#{state}")
22
+ end
23
+
24
+ private
25
+
26
+ def create_socket
27
+ raise 'Missing NOTIFY_SOCKET environment variable, is this process running under systemd?' unless active?
28
+ Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM, 0).tap do |socket|
29
+ socket.connect(Socket.pack_sockaddr_un(ENV['NOTIFY_SOCKET']))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -19,37 +19,36 @@ end
19
19
 
20
20
  module SmartProxyDynflowCore
21
21
  class Settings < OpenStruct
22
-
23
22
  DEFAULT_SETTINGS = {
24
- :database => '/var/lib/foreman-proxy/dynflow/dynflow.sqlite',
25
- :foreman_url => 'https://127.0.0.1:3000',
26
- :console_auth => true,
27
- :listen => '127.0.0.1',
28
- :port => '8008',
29
- :use_https => false,
30
- :ssl_ca_file => nil,
31
- :ssl_private_key => nil,
32
- :ssl_certificate => nil,
33
- :ssl_disabled_ciphers => [],
34
- :tls_disabled_versions => [],
35
- :foreman_ssl_ca => nil,
36
- :foreman_ssl_key => nil,
37
- :foreman_ssl_cert => nil,
38
- :standalone => false,
39
- :log_file => '/var/log/foreman-proxy/smart_proxy_dynflow_core.log',
40
- :log_level => :ERROR,
41
- :plugins => {},
42
- :pid_file => '/var/run/foreman-proxy/smart_proxy_dynflow_core.pid',
43
- :daemonize => false,
44
- :execution_plan_cleaner_age => 60 * 60 * 24,
45
- :loaded => false
46
- }
23
+ :database => '/var/lib/foreman-proxy/dynflow/dynflow.sqlite',
24
+ :foreman_url => 'https://127.0.0.1:3000',
25
+ :console_auth => true,
26
+ :listen => '127.0.0.1',
27
+ :port => '8008',
28
+ :use_https => false,
29
+ :ssl_ca_file => nil,
30
+ :ssl_private_key => nil,
31
+ :ssl_certificate => nil,
32
+ :ssl_disabled_ciphers => [],
33
+ :tls_disabled_versions => [],
34
+ :foreman_ssl_ca => nil,
35
+ :foreman_ssl_key => nil,
36
+ :foreman_ssl_cert => nil,
37
+ :standalone => false,
38
+ :log_file => '/var/log/foreman-proxy/smart_proxy_dynflow_core.log',
39
+ :log_level => :ERROR,
40
+ :plugins => {},
41
+ :pid_file => '/var/run/foreman-proxy/smart_proxy_dynflow_core.pid',
42
+ :daemonize => false,
43
+ :execution_plan_cleaner_age => 60 * 60 * 24,
44
+ :loaded => false
45
+ }.freeze
47
46
 
48
- PROXY_SETTINGS = [:ssl_ca_file, :ssl_certificate, :ssl_private_key, :foreman_url,
49
- :foreman_ssl_ca, :foreman_ssl_cert, :foreman_ssl_key,
50
- :log_file, :log_level, :ssl_disabled_ciphers]
51
- PLUGIN_SETTINGS = [:database, :core_url, :console_auth,
52
- :execution_plan_cleaner_age]
47
+ PROXY_SETTINGS = %i[ssl_ca_file ssl_certificate ssl_private_key foreman_url
48
+ foreman_ssl_ca foreman_ssl_cert foreman_ssl_key
49
+ log_file log_level ssl_disabled_ciphers].freeze
50
+ PLUGIN_SETTINGS = %i[database core_url console_auth
51
+ execution_plan_cleaner_age].freeze
53
52
 
54
53
  def initialize(settings = {})
55
54
  super(DEFAULT_SETTINGS.merge(settings))
@@ -60,7 +59,7 @@ module SmartProxyDynflowCore
60
59
  end
61
60
 
62
61
  def self.load_global_settings(path)
63
- if File.exists? File.join(path)
62
+ if File.exist? File.join(path)
64
63
  YAML.load_file(path).each do |key, value|
65
64
  SETTINGS[key] = value
66
65
  end
@@ -87,7 +86,7 @@ module SmartProxyDynflowCore
87
86
  PLUGIN_SETTINGS.each do |key|
88
87
  SETTINGS[key] = settings[key] if settings.key?(key)
89
88
  end
90
- SETTINGS.plugins.values.each { |plugin| plugin.load_settings_from_proxy }
89
+ SETTINGS.plugins.values.each(&:load_settings_from_proxy)
91
90
  Settings.loaded!
92
91
  end
93
92
 
@@ -0,0 +1,31 @@
1
+ module SmartProxyDynflowCore
2
+ class TaskLauncherRegistry
3
+ class << self
4
+ def register(name, launcher)
5
+ registry[name] = launcher
6
+ end
7
+
8
+ def fetch(name, default = nil)
9
+ if default.nil?
10
+ registry.fetch(name)
11
+ else
12
+ registry.fetch(name, default)
13
+ end
14
+ end
15
+
16
+ def key?(name)
17
+ registry.key?(name)
18
+ end
19
+
20
+ def operations
21
+ registry.keys
22
+ end
23
+
24
+ private
25
+
26
+ def registry
27
+ @registry ||= {}
28
+ end
29
+ end
30
+ end
31
+ end
@@ -17,7 +17,7 @@ module SmartProxyDynflowCore
17
17
  config.auto_terminate = false
18
18
  config.logger_adapter = ::Dynflow::LoggerAdapters::Simple.new $stderr, DYNFLOW_TESTING_LOG_LEVEL
19
19
  config.execution_plan_cleaner = nil
20
- block.call(config) if block
20
+ yield(config) if block
21
21
  end
22
22
  end
23
23
  end
@@ -1,3 +1,3 @@
1
1
  module SmartProxyDynflowCore
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.6'.freeze
3
3
  end
@@ -1,8 +1,8 @@
1
- # -*- encoding: utf-8 -*-
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'smart_proxy_dynflow_core/version'
5
4
 
5
+ # rubocop:disable Metrics/BlockLength
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "smart_proxy_dynflow_core"
8
8
  gem.version = SmartProxyDynflowCore::VERSION
@@ -22,19 +22,19 @@ Gem::Specification.new do |gem|
22
22
  gem.require_paths = ["lib"]
23
23
  gem.license = 'GPL-3.0'
24
24
 
25
- gem.add_development_dependency "bundler", "~> 1.7"
26
- gem.add_development_dependency "rake", "~> 10.0"
25
+ gem.add_development_dependency "bundler", ">= 1.7"
27
26
  gem.add_development_dependency('minitest')
28
27
  gem.add_development_dependency('mocha', '~> 1')
29
- gem.add_development_dependency('webmock', '~> 1')
30
28
  gem.add_development_dependency('rack-test', '~> 0')
31
- gem.add_development_dependency('rubocop', '~> 0.52.1')
29
+ gem.add_development_dependency "rake", "~> 10.0"
30
+ gem.add_development_dependency('webmock', '~> 1')
32
31
 
33
- gem.add_runtime_dependency('dynflow', "~> 1.0")
34
- gem.add_runtime_dependency('foreman-tasks-core', '>= 0.1.7')
35
- gem.add_runtime_dependency('sequel')
36
- gem.add_runtime_dependency('sqlite3')
37
- gem.add_runtime_dependency('sinatra')
32
+ gem.add_runtime_dependency('dynflow', "~> 1.1")
33
+ gem.add_runtime_dependency('foreman-tasks-core', '>= 0.3.3')
38
34
  gem.add_runtime_dependency('rack')
39
35
  gem.add_runtime_dependency('rest-client')
36
+ gem.add_runtime_dependency('sequel')
37
+ gem.add_runtime_dependency('sinatra')
38
+ gem.add_runtime_dependency('sqlite3')
40
39
  end
40
+ # rubocop:enable Metrics/BlockLength
metadata CHANGED
@@ -1,43 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_dynflow_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-20 00:00:00.000000000 Z
11
+ date: 2020-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.7'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.7'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: minitest
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -67,77 +53,77 @@ dependencies:
67
53
  - !ruby/object:Gem::Version
68
54
  version: '1'
69
55
  - !ruby/object:Gem::Dependency
70
- name: webmock
56
+ name: rack-test
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - "~>"
74
60
  - !ruby/object:Gem::Version
75
- version: '1'
61
+ version: '0'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
66
  - - "~>"
81
67
  - !ruby/object:Gem::Version
82
- version: '1'
68
+ version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
- name: rack-test
70
+ name: rake
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: '0'
75
+ version: '10.0'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '0'
82
+ version: '10.0'
97
83
  - !ruby/object:Gem::Dependency
98
- name: rubocop
84
+ name: webmock
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - "~>"
102
88
  - !ruby/object:Gem::Version
103
- version: 0.52.1
89
+ version: '1'
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
94
  - - "~>"
109
95
  - !ruby/object:Gem::Version
110
- version: 0.52.1
96
+ version: '1'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: dynflow
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
101
  - - "~>"
116
102
  - !ruby/object:Gem::Version
117
- version: '1.0'
103
+ version: '1.1'
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: '1.0'
110
+ version: '1.1'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: foreman-tasks-core
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
115
  - - ">="
130
116
  - !ruby/object:Gem::Version
131
- version: 0.1.7
117
+ version: 0.3.3
132
118
  type: :runtime
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
122
  - - ">="
137
123
  - !ruby/object:Gem::Version
138
- version: 0.1.7
124
+ version: 0.3.3
139
125
  - !ruby/object:Gem::Dependency
140
- name: sequel
126
+ name: rack
141
127
  requirement: !ruby/object:Gem::Requirement
142
128
  requirements:
143
129
  - - ">="
@@ -151,7 +137,7 @@ dependencies:
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0'
153
139
  - !ruby/object:Gem::Dependency
154
- name: sqlite3
140
+ name: rest-client
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
143
  - - ">="
@@ -165,7 +151,7 @@ dependencies:
165
151
  - !ruby/object:Gem::Version
166
152
  version: '0'
167
153
  - !ruby/object:Gem::Dependency
168
- name: sinatra
154
+ name: sequel
169
155
  requirement: !ruby/object:Gem::Requirement
170
156
  requirements:
171
157
  - - ">="
@@ -179,7 +165,7 @@ dependencies:
179
165
  - !ruby/object:Gem::Version
180
166
  version: '0'
181
167
  - !ruby/object:Gem::Dependency
182
- name: rack
168
+ name: sinatra
183
169
  requirement: !ruby/object:Gem::Requirement
184
170
  requirements:
185
171
  - - ">="
@@ -193,7 +179,7 @@ dependencies:
193
179
  - !ruby/object:Gem::Version
194
180
  version: '0'
195
181
  - !ruby/object:Gem::Dependency
196
- name: rest-client
182
+ name: sqlite3
197
183
  requirement: !ruby/object:Gem::Requirement
198
184
  requirements:
199
185
  - - ">="
@@ -228,10 +214,11 @@ files:
228
214
  - lib/smart_proxy_dynflow_core/helpers.rb
229
215
  - lib/smart_proxy_dynflow_core/launcher.rb
230
216
  - lib/smart_proxy_dynflow_core/log.rb
217
+ - lib/smart_proxy_dynflow_core/sd_notify.rb
231
218
  - lib/smart_proxy_dynflow_core/settings.rb
219
+ - lib/smart_proxy_dynflow_core/task_launcher_registry.rb
232
220
  - lib/smart_proxy_dynflow_core/testing.rb
233
221
  - lib/smart_proxy_dynflow_core/version.rb
234
- - lib/smart_proxy_dynflow_core/webrick-patch.rb
235
222
  - smart_proxy_dynflow_core.gemspec
236
223
  homepage: https://github.com/theforeman/smart_proxy_dynflow
237
224
  licenses:
@@ -252,8 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
239
  - !ruby/object:Gem::Version
253
240
  version: '0'
254
241
  requirements: []
255
- rubyforge_project:
256
- rubygems_version: 2.6.12
242
+ rubygems_version: 3.0.3
257
243
  signing_key:
258
244
  specification_version: 4
259
245
  summary: Dynflow runtime for Foreman smart proxy
@@ -1,37 +0,0 @@
1
- require 'webrick/https'
2
-
3
- CIPHERS = ['ECDHE-RSA-AES128-GCM-SHA256','ECDHE-RSA-AES256-GCM-SHA384',
4
- 'ECDHE-RSA-AES128-CBC-SHA','ECDHE-RSA-AES256-CBC-SHA',
5
- 'AES128-GCM-SHA256','AES256-GCM-SHA384','AES128-SHA256',
6
- 'AES256-SHA256','AES128-SHA','AES256-SHA']
7
-
8
- module WEBrick
9
- class GenericServer
10
- def setup_ssl_context(config) # :nodoc:
11
- unless config[:SSLCertificate]
12
- cn = config[:SSLCertName]
13
- comment = config[:SSLCertComment]
14
- cert, key = Utils::create_self_signed_cert(1024, cn, comment)
15
- config[:SSLCertificate] = cert
16
- config[:SSLPrivateKey] = key
17
- end
18
- ctx = OpenSSL::SSL::SSLContext.new
19
- ctx.set_params
20
- ctx.ciphers = (CIPHERS - SmartProxyDynflowCore::Settings.instance.ssl_disabled_ciphers).join(':')
21
- ctx.key = config[:SSLPrivateKey]
22
- ctx.cert = config[:SSLCertificate]
23
- ctx.client_ca = config[:SSLClientCA]
24
- ctx.extra_chain_cert = config[:SSLExtraChainCert]
25
- ctx.ca_file = config[:SSLCACertificateFile]
26
- ctx.ca_path = config[:SSLCACertificatePath]
27
- ctx.cert_store = config[:SSLCertificateStore]
28
- ctx.tmp_dh_callback = config[:SSLTmpDhCallback]
29
- ctx.verify_mode = config[:SSLVerifyClient]
30
- ctx.verify_depth = config[:SSLVerifyDepth]
31
- ctx.verify_callback = config[:SSLVerifyCallback]
32
- ctx.timeout = config[:SSLTimeout]
33
- ctx.options |= config[:SSLOptions] unless config[:SSLOptions].nil?
34
- ctx
35
- end
36
- end
37
- end