smart_proxy_dynflow_core 0.2.4 → 0.3.2

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
2
  SHA256:
3
- metadata.gz: 360ced6b9efefcab091ac6870ce28c0c7a1d4282a97bad433c60662180470e94
4
- data.tar.gz: da8dcce85083a3db1afe73bbf14e0cbbe9af2b203909b3e6f64ca3dec6578e63
3
+ metadata.gz: ae61c912ffbb4027b1445e41995bbe66a97089c6f498c612b180da1ac91b248b
4
+ data.tar.gz: 7ce93f5bde709fab044af950c9b6b8664e60f2d173b3147a1beabd3da694fa32
5
5
  SHA512:
6
- metadata.gz: 76dc5c88f56a0c16a93e474b46480033d7a23177a5c6d7d0fe8630caaebdca8882179314638e9246573f17a657d79c2abbca48a02b759d5b2deccb7686f8a828
7
- data.tar.gz: 4378d3f1c210e996f67dff3c49176838246cbfa97512c18b8ea307fb1c5de34099ce7bc5675c46c90a1886c677015820ae835411993ed12e20f2fb7cf60280f3
6
+ metadata.gz: 40f546771cd25e48148fe50041544f663799f757d2aedf0635cc41de0a8b540228d8e116fa81b1d5cfe24913d2e75ac5a9912e9bac2813b8b2506ff894458d54
7
+ data.tar.gz: 00167adcc5eb1f24f65efa798fa00875bf0db221ba8aa1515d512a168e2c67c407391237f0a6770a1747b3519c5e632cbbb746d0eb1e797e65b967642e4a19d5
data/Gemfile CHANGED
@@ -10,28 +10,14 @@ group :test do
10
10
  gem 'smart_proxy', :git => "https://github.com/theforeman/smart-proxy", :branch => "develop"
11
11
  gem 'smart_proxy_dynflow', :path => '.'
12
12
 
13
- if RUBY_VERSION < '2.1'
14
- gem 'public_suffix', '< 3'
15
- gem 'rainbow', '< 3'
16
- else
17
- gem 'public_suffix'
18
- gem 'rubocop', '~> 0.52.1'
19
- end
20
-
21
- if RUBY_VERSION < '2.2'
22
- gem 'rack-test', '< 0.8'
23
- else
24
- gem 'rack-test'
25
- end
13
+ gem 'public_suffix'
14
+ gem 'rack-test'
15
+ gem 'rubocop', '~> 0.52.1'
26
16
  end
27
17
 
28
- if RUBY_VERSION < '2.2'
29
- gem 'rack', '>= 1.1', '< 2.0.0'
30
- gem 'sinatra', '< 2'
31
- else
32
- gem 'rack', '>= 1.1'
33
- gem 'sinatra'
34
- end
18
+ gem 'logging-journald', '~> 2.0', :platforms => [:ruby], :require => false
19
+ gem 'rack', '>= 1.1'
20
+ gem 'sinatra'
35
21
 
36
22
  # load bundler.d
37
23
  Dir["#{File.dirname(__FILE__)}/bundler.d/*.rb"].each do |bundle|
@@ -39,11 +39,27 @@
39
39
  # Specify versions like: '1.1', or '1.2'
40
40
  #:tls_disabled_versions: []
41
41
 
42
- # File to log to, leave empty for logging to STDOUT
43
- # :log_file: /var/log/foreman-proxy/smart_proxy_dynflow_core.log
42
+ # File to log to, leave empty for stdout or use STDOUT, STDERR, SYSLOG or JOURNAL
43
+ #:log_file: /var/log/foreman-proxy/smart_proxy_dynflow_core.log
44
44
 
45
45
  # Log level, one of UNKNOWN, FATAL, ERROR, WARN, INFO, DEBUG
46
- # :log_level: ERROR
46
+ #:log_level: ERROR
47
+
48
+ # The maximum size of a log file before it's rolled (in MiB) or zero to disable file rolling
49
+ # and rely on logrotate or similar tool
50
+ #:file_rolling_size: 0
51
+
52
+ # The maximum age of a log file before it's rolled (in seconds). Also accepts 'daily', 'weekly', or 'monthly'.
53
+ #:file_rolling_age: weekly
54
+
55
+ # Number of log files to keep
56
+ #:file_rolling_keep: 6
57
+
58
+ # Logging pattern for file-based loging
59
+ #:file_logging_pattern: '%d %.8X{request} [%.1l] %m'
60
+
61
+ # Logging pattern for syslog or journal loging
62
+ #:system_logging_pattern: '%.8X{request} [%.1l] %m'
47
63
 
48
64
  # Maximum age of execution plans to keep before having them cleaned
49
65
  # by the execution plan cleaner (in seconds), defaults to 24 hours
@@ -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,6 +1,7 @@
1
- raise LoadError, 'Ruby >= 2.1 is required' unless RUBY_VERSION >= '2.1'
2
-
3
1
  require 'dynflow'
2
+ require 'smart_proxy_dynflow_core/request_id_middleware'
3
+ require 'smart_proxy_dynflow_core/logger_middleware'
4
+ require 'smart_proxy_dynflow_core/middleware/keep_current_request_id'
4
5
  require 'smart_proxy_dynflow_core/task_launcher_registry'
5
6
  require 'foreman_tasks_core'
6
7
  require 'smart_proxy_dynflow_core/log'
@@ -6,6 +6,14 @@ module SmartProxyDynflowCore
6
6
  TASK_UPDATE_REGEXP_PATH = %r{/tasks/(\S+)/(update|done)}
7
7
  helpers Helpers
8
8
 
9
+ configure do
10
+ if Settings.instance.standalone
11
+ ::Sinatra::Base.set :logging, false
12
+ ::Sinatra::Base.use ::SmartProxyDynflowCore::RequestIdMiddleware
13
+ ::Sinatra::Base.use ::SmartProxyDynflowCore::LoggerMiddleware
14
+ end
15
+ end
16
+
9
17
  before do
10
18
  if match = request.path_info.match(TASK_UPDATE_REGEXP_PATH)
11
19
  task_id = match[1]
@@ -1,6 +1,5 @@
1
1
  module SmartProxyDynflowCore
2
2
  class BundlerHelper
3
- # rubocop:disable Metrics/PerceivedComplexity
4
3
  def self.require_groups(*groups)
5
4
  if File.exist?(File.expand_path('../../../Gemfile.in', __FILE__))
6
5
  # If there is a Gemfile.in file, we will not use Bundler but BundlerExt
@@ -15,7 +15,6 @@ module SmartProxyDynflowCore
15
15
  self.new.callback(prepare_payload(callback_info, data))
16
16
  end
17
17
 
18
- # rubocop:disable Metrics/PerceivedComplexity
19
18
  def ssl_options
20
19
  return @ssl_options if defined? @ssl_options
21
20
  @ssl_options = {}
@@ -15,7 +15,9 @@ module SmartProxyDynflowCore
15
15
 
16
16
  def create_world(&block)
17
17
  config = default_world_config(&block)
18
- ::Dynflow::World.new(config)
18
+ world = ::Dynflow::World.new(config)
19
+ world.middleware.use ::Actions::Middleware::KeepCurrentRequestID
20
+ world
19
21
  end
20
22
 
21
23
  def persistence_conn_string
@@ -1,22 +1,28 @@
1
1
  require 'webrick/https'
2
2
  require 'smart_proxy_dynflow_core/bundler_helper'
3
3
  require 'smart_proxy_dynflow_core/settings'
4
- # mute Ruby redefinition warnings when running embedded
5
- require 'smart_proxy_dynflow_core/webrick-patch' unless defined?(::Proxy::Launcher)
4
+ require 'sd_notify'
6
5
 
7
6
  module SmartProxyDynflowCore
8
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
11
+
9
12
  def self.launch!(options)
10
13
  self.new.start options
11
14
  end
12
15
 
13
16
  def start(options)
14
- load_settings!(options)
15
17
  Settings.instance.standalone = true
18
+ load_settings!(options)
16
19
  install_usr1_trap
17
20
  Rack::Server.new(rack_settings).start do |_server|
18
21
  SmartProxyDynflowCore::Core.ensure_initialized
22
+ ::SdNotify.ready
19
23
  end
24
+ Log.instance.info "Finished shutting down"
25
+ Logging.shutdown
20
26
  end
21
27
 
22
28
  def load_settings!(options = {})
@@ -49,7 +55,7 @@ module SmartProxyDynflowCore
49
55
 
50
56
  def install_usr1_trap
51
57
  trap(:USR1) do
52
- Log.instance.roll_log
58
+ Log.reopen
53
59
  end
54
60
  end
55
61
 
@@ -77,15 +83,14 @@ module SmartProxyDynflowCore
77
83
  :app => app,
78
84
  :Host => Settings.instance.listen,
79
85
  :Port => Settings.instance.port,
80
- :AccessLog => [[Log.instance, WEBrick::AccessLog::COMMON_LOG_FORMAT]],
86
+ :AccessLog => [],
81
87
  :Logger => Log.instance,
82
88
  :daemonize => Settings.instance.daemonize,
83
- :pid => Settings.instance.pid_file,
89
+ :pid => Settings.instance.daemonize && Settings.instance.pid_file,
84
90
  :server => :webrick
85
91
  }
86
92
  end
87
93
 
88
- # rubocop:disable Metrics/PerceivedComplexity
89
94
  def https_app
90
95
  ssl_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
91
96
  ssl_options |= OpenSSL::SSL::OP_CIPHER_SERVER_PREFERENCE if defined?(OpenSSL::SSL::OP_CIPHER_SERVER_PREFERENCE)
@@ -93,17 +98,16 @@ module SmartProxyDynflowCore
93
98
  ssl_options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
94
99
  ssl_options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
95
100
  ssl_options |= OpenSSL::SSL::OP_NO_TLSv1 if defined?(OpenSSL::SSL::OP_NO_TLSv1)
101
+ ssl_options |= OpenSSL::SSL::OP_NO_TLSv1_1 if defined?(OpenSSL::SSL::OP_NO_TLSv1_1)
96
102
 
97
- if Settings.instance.tls_disabled_versions
98
- Settings.instance.tls_disabled_versions.each do |version|
99
- constant = OpenSSL::SSL.const_get("OP_NO_TLSv#{version.to_s.tr('.', '_')}") rescue nil
103
+ Settings.instance.tls_disabled_versions&.each do |version|
104
+ constant = OpenSSL::SSL.const_get("OP_NO_TLSv#{version.to_s.tr('.', '_')}") rescue nil
100
105
 
101
- if constant
102
- Log.instance.info "TLSv#{version} will be disabled."
103
- ssl_options |= constant
104
- else
105
- Log.instance.warn "TLSv#{version} was not found."
106
- end
106
+ if constant
107
+ Log.instance.info "TLSv#{version} will be disabled."
108
+ ssl_options |= constant
109
+ else
110
+ Log.instance.warn "TLSv#{version} was not found."
107
111
  end
108
112
  end
109
113
 
@@ -113,6 +117,7 @@ module SmartProxyDynflowCore
113
117
  :SSLPrivateKey => ssl_private_key,
114
118
  :SSLCertificate => ssl_certificate,
115
119
  :SSLCACertificateFile => Settings.instance.ssl_ca_file,
120
+ :SSLCiphers => CIPHERS - SmartProxyDynflowCore::Settings.instance.ssl_disabled_ciphers,
116
121
  :SSLOptions => ssl_options
117
122
  }
118
123
  end
@@ -1,61 +1,126 @@
1
- require 'logger'
1
+ require 'logging'
2
2
 
3
3
  module SmartProxyDynflowCore
4
- class Log < ::Logger
5
- alias_method :write, :debug
4
+ class ReopenAppender < ::Logging::Appender
5
+ def initialize(name, logger, opts = {})
6
+ @reopen = false
7
+ @logger = logger
8
+ super(name, opts)
9
+ end
6
10
 
7
- class << self
8
- def instance
9
- if @logger.nil?
10
- @logger = self.new log_file
11
- @logger.level = log_level
12
- end
13
- @logger
14
- end
11
+ def set(status = true)
12
+ @reopen = status
13
+ end
15
14
 
16
- def instance=(logger)
17
- @logger = logger
15
+ def append(_event)
16
+ if @reopen
17
+ Logging.reopen
18
+ @reopen = false
18
19
  end
20
+ end
21
+ end
22
+
23
+ class Log
24
+ BASE_LOG_SIZE = 1024 * 1024 # 1 MiB
25
+ LOGGER_NAME = 'dynflow-core'.freeze
26
+
27
+ begin
28
+ require 'syslog/logger'
29
+ @syslog_available = true
30
+ rescue LoadError
31
+ @syslog_available = false
32
+ end
19
33
 
34
+ class << self
20
35
  def reload!
36
+ Logging.logger[LOGGER_NAME].appenders.each(&:close)
37
+ Logging.logger[LOGGER_NAME].clear_appenders
21
38
  @logger = nil
22
39
  instance
23
40
  end
24
41
 
25
- def log_level
26
- if Settings.instance.loaded && Settings.instance.log_level
27
- ::Logger.const_get(Settings.instance.log_level.upcase)
28
- else
29
- Logger::WARN
42
+ def reopen
43
+ return if @logger.nil? || @reopen.nil?
44
+ if Settings.instance.log_file !~ /^(STDOUT|SYSLOG|JOURNALD?)$/i
45
+ @reopen.set
30
46
  end
31
47
  end
32
48
 
33
- def log_file
34
- if Settings.instance.loaded && Settings.instance.log_file
35
- Settings.instance.log_file
49
+ def instance
50
+ return ::Proxy::LogBuffer::Decorator.instance unless Settings.instance.standalone
51
+ return @logger if @logger
52
+ layout = Logging::Layouts.pattern(pattern: Settings.instance.file_logging_pattern + "\n")
53
+ notime_layout = Logging::Layouts.pattern(pattern: Settings.instance.system_logging_pattern + "\n")
54
+ log_file = Settings.instance.log_file || ''
55
+ @logger = Logging.logger[LOGGER_NAME]
56
+ @reopen = ReopenAppender.new("Reopen dummy appender", @logger)
57
+ @logger.add_appenders(@reopen)
58
+ if !Settings.instance.loaded || log_file.casecmp('STDOUT').zero?
59
+ @logger.add_appenders(Logging.appenders.stdout(LOGGER_NAME, layout: layout))
60
+ elsif log_file.casecmp('SYSLOG').zero?
61
+ unless @syslog_available
62
+ puts "Syslog is not supported on this platform, use STDOUT or a file"
63
+ exit(1)
64
+ end
65
+ @logger.add_appenders(Logging.appenders.syslog(LOGGER_NAME, layout: notime_layout, facility: ::Syslog::Constants::LOG_LOCAL5))
66
+ elsif log_file.casecmp('JOURNAL').zero? || log_file.casecmp('JOURNALD').zero?
67
+ begin
68
+ @logger.add_appenders(Logging.appenders.journald(LOGGER_NAME, LOGGER_NAME: :proxy_logger, layout: notime_layout, facility: ::Syslog::Constants::LOG_LOCAL5))
69
+ rescue NoMethodError
70
+ @logger.add_appenders(Logging.appenders.stdout(LOGGER_NAME, layout: layout))
71
+ @logger.warn "Journald is not available on this platform. Falling back to STDOUT."
72
+ end
36
73
  else
37
- $stdout
74
+ begin
75
+ keep = Settings.instance.file_rolling_keep
76
+ size = BASE_LOG_SIZE * Settings.instance.file_rolling_size
77
+ age = Settings.instance.file_rolling_age
78
+ if size.positive?
79
+ @logger.add_appenders(Logging.appenders.rolling_file(LOGGER_NAME, layout: layout, filename: log_file, keep: keep, size: size, age: age, roll_by: 'number'))
80
+ else
81
+ @logger.add_appenders(Logging.appenders.file(LOGGER_NAME, layout: layout, filename: log_file))
82
+ end
83
+ rescue ArgumentError => ae
84
+ @logger.add_appenders(Logging.appenders.stdout(LOGGER_NAME, layout: layout))
85
+ @logger.warn "Log file #{log_file} cannot be opened. Falling back to STDOUT: #{ae}"
86
+ end
38
87
  end
88
+ @logger.level = ::Logging.level_num(Settings.instance.log_level)
89
+ @logger
39
90
  end
40
- end
41
91
 
42
- def initialize(file, *rest)
43
- @file = file
44
- @fd = @file.is_a?(IO) ? @file : File.open(@file, 'a')
45
- @fd.sync = true
46
- super(@fd, rest)
47
- end
92
+ def with_fields(fields = {})
93
+ ::Logging.ndc.push(fields) do
94
+ yield
95
+ end
96
+ end
48
97
 
49
- def roll_log
50
- unless @file.is_a? IO
51
- @fd.reopen @file, 'a'
52
- @fd.sync = true
98
+ # Standard way for logging exceptions to get the most data in the log. By default
99
+ # it logs via warn level, this can be changed via options[:level]
100
+ def exception(context_message, exception, options = {})
101
+ level = options[:level] || :warn
102
+ unless ::Logging::LEVELS.keys.include?(level.to_s)
103
+ raise "Unexpected log level #{level}, expected one of #{::Logging::LEVELS.keys}"
104
+ end
105
+ # send class, message and stack as structured fields in addition to message string
106
+ backtrace = exception.backtrace ? exception.backtrace : []
107
+ extra_fields = {
108
+ exception_class: exception.class.name,
109
+ exception_message: exception.message,
110
+ exception_backtrace: backtrace
111
+ }
112
+ extra_fields[:foreman_code] = exception.code if exception.respond_to?(:code)
113
+ with_fields(extra_fields) do
114
+ @logger.public_send(level) do
115
+ ([context_message, "#{exception.class}: #{exception.message}"] + backtrace).join("\n")
116
+ end
117
+ end
53
118
  end
54
119
  end
55
120
 
56
121
  class ProxyStructuredFormater < ::Dynflow::LoggerAdapters::Formatters::Abstract
57
- def call(_severity, _datetime, _prog_name, message)
58
- if message.is_a?(::Exception)
122
+ def format(message)
123
+ if message.is_a?(Exception)
59
124
  subject = "#{message.message} (#{message.class})"
60
125
  if @base.respond_to?(:exception)
61
126
  @base.exception("Error details", message)
@@ -64,22 +129,17 @@ module SmartProxyDynflowCore
64
129
  "#{subject}\n#{message.backtrace.join("\n")}"
65
130
  end
66
131
  else
67
- message
132
+ @original_formatter.call(severity, datetime, prog_name, message)
68
133
  end
69
134
  end
70
-
71
- def format(message)
72
- call(nil, nil, nil, message)
73
- end
74
135
  end
75
136
 
76
137
  class ProxyAdapter < ::Dynflow::LoggerAdapters::Simple
77
138
  def initialize(logger, level = Logger::DEBUG, _formatters = [])
78
139
  @logger = logger
79
140
  @logger.level = level
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])
141
+ @action_logger = apply_formatters(ProgNameWrapper.new(@logger, ' action'), [])
142
+ @dynflow_logger = apply_formatters(ProgNameWrapper.new(@logger, 'dynflow'), [])
83
143
  end
84
144
  end
85
145
  end
@@ -0,0 +1,31 @@
1
+ module SmartProxyDynflowCore
2
+ class LoggerMiddleware
3
+ def initialize(app)
4
+ @logger = SmartProxyDynflowCore::Log.instance
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ before = Time.now.to_f
10
+ status = 500
11
+ env['rack.logger'] = @logger
12
+ @logger.info { "Started #{env['REQUEST_METHOD']} #{env['PATH_INFO']} #{env['QUERY_STRING']}" }
13
+ @logger.debug { 'Headers: ' + env.select { |k, v| k.start_with? 'HTTP_' }.inspect }
14
+ if @logger.debug? && env['rack.input']
15
+ body = env['rack.input'].read
16
+ @logger.debug('Body: ' + body) unless body.empty?
17
+ env['rack.input'].rewind
18
+ end
19
+ status, = @app.call(env)
20
+ rescue Exception => e
21
+ Log.exception "Error processing request '#{::Logging.mdc['request']}", e
22
+ raise e
23
+ ensure
24
+ @logger.info do
25
+ after = Time.now.to_f
26
+ duration = (after - before) * 1000
27
+ "Finished #{env['REQUEST_METHOD']} #{env['PATH_INFO']} with #{status} (#{duration.round(2)} ms)"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,59 @@
1
+ module Actions
2
+ module Middleware
3
+ class KeepCurrentRequestID < Dynflow::Middleware
4
+ def delay(*args)
5
+ pass(*args).tap { store_current_request_id }
6
+ end
7
+
8
+ def plan(*args)
9
+ with_current_request_id do
10
+ pass(*args).tap { store_current_request_id }
11
+ end
12
+ end
13
+
14
+ def run(*args)
15
+ restore_current_request_id { pass(*args) }
16
+ end
17
+
18
+ def finalize
19
+ restore_current_request_id { pass }
20
+ end
21
+
22
+ # Run all execution plan lifecycle hooks as the original request_id
23
+ def hook(*args)
24
+ restore_current_request_id { pass(*args) }
25
+ end
26
+
27
+ private
28
+
29
+ def with_current_request_id
30
+ if action.input[:current_request_id].nil?
31
+ yield
32
+ else
33
+ restore_current_request_id { yield }
34
+ end
35
+ end
36
+
37
+ def store_current_request_id
38
+ action.input[:current_request_id] = ::Logging.mdc['request']
39
+ end
40
+
41
+ def restore_current_request_id
42
+ unless (restored_id = action.input[:current_request_id]).nil?
43
+ old_id = ::Logging.mdc['request']
44
+ if !old_id.nil? && old_id != restored_id
45
+ action.action_logger.warn('Changing request id %{request_id} to saved id %{saved_id}' % { :saved_id => restored_id, :request_id => old_id })
46
+ end
47
+ ::Logging.mdc['request'] = restored_id
48
+ end
49
+ yield
50
+ ensure
51
+ # Reset to original request id only when not nil
52
+ # Otherwise, keep the id until it's cleaned in Dynflow's run_user_code block
53
+ # so that it will stay valid for the rest of the processing of the current step
54
+ # (even outside of the middleware lifecycle)
55
+ ::Logging.mdc['request'] = old_id unless old_id.nil?
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,18 @@
1
+ module SmartProxyDynflowCore
2
+ class RequestIdMiddleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ ::Logging.mdc['remote_ip'] = env['REMOTE_ADDR']
9
+ if env.has_key?('HTTP_X_REQUEST_ID')
10
+ ::Logging.mdc['request'] = env['HTTP_X_REQUEST_ID']
11
+ else
12
+ ::Logging.mdc['request'] = SecureRandom.uuid
13
+ end
14
+ status, header, body = @app.call(env)
15
+ [status, header, ::Rack::BodyProxy.new(body) { ::Logging.mdc.clear }]
16
+ end
17
+ end
18
+ end
@@ -1,22 +1,5 @@
1
1
  require 'ostruct'
2
2
 
3
- # Implement hash-like access for 1.9.3 and older
4
- if RUBY_VERSION.split('.').first.to_i < 2
5
- class OpenStruct
6
- def [](key)
7
- self.send key
8
- end
9
-
10
- def []=(key, value)
11
- self.send "#{key}=", value
12
- end
13
-
14
- def to_h
15
- marshal_dump
16
- end
17
- end
18
- end
19
-
20
3
  module SmartProxyDynflowCore
21
4
  class Settings < OpenStruct
22
5
  DEFAULT_SETTINGS = {
@@ -41,7 +24,12 @@ module SmartProxyDynflowCore
41
24
  :pid_file => '/var/run/foreman-proxy/smart_proxy_dynflow_core.pid',
42
25
  :daemonize => false,
43
26
  :execution_plan_cleaner_age => 60 * 60 * 24,
44
- :loaded => false
27
+ :loaded => false,
28
+ :file_logging_pattern => '%d %.8X{request} [%.1l] %m',
29
+ :system_logging_pattern => '%.8X{request} [%.1l] %m',
30
+ :file_rolling_keep => 6,
31
+ :file_rolling_size => 0,
32
+ :file_rolling_age => 'weekly'
45
33
  }.freeze
46
34
 
47
35
  PROXY_SETTINGS = %i[ssl_ca_file ssl_certificate ssl_private_key foreman_url
@@ -73,13 +61,7 @@ module SmartProxyDynflowCore
73
61
  end
74
62
 
75
63
  def self.load_from_proxy(plugin)
76
- plugin_class = if Proxy::VERSION >= '1.16.0'
77
- plugin
78
- else
79
- # DEPRECATION: Remove this branch when dropping support for smart-proxy < 1.16
80
- plugin[:class]
81
- end
82
- settings = plugin_class.settings.to_h
64
+ settings = plugin.settings.to_h
83
65
  PROXY_SETTINGS.each do |key|
84
66
  SETTINGS[key] = Proxy::SETTINGS[key]
85
67
  end
@@ -1,3 +1,3 @@
1
1
  module SmartProxyDynflowCore
2
- VERSION = '0.2.4'.freeze
2
+ VERSION = '0.3.2'.freeze
3
3
  end
@@ -2,7 +2,6 @@ lib = File.expand_path('../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'smart_proxy_dynflow_core/version'
4
4
 
5
- # rubocop:disable Metrics/BlockLength
6
5
  Gem::Specification.new do |gem|
7
6
  gem.name = "smart_proxy_dynflow_core"
8
7
  gem.version = SmartProxyDynflowCore::VERSION
@@ -16,13 +15,15 @@ Gem::Specification.new do |gem|
16
15
 
17
16
  gem.executables = ['smart_proxy_dynflow_core']
18
17
  gem.files = Dir['lib/smart_proxy_dynflow_core.rb', 'config/settings.yml.example',
19
- 'lib/smart_proxy_dynflow_core/*', 'LICENSE', 'Gemfile',
18
+ 'lib/smart_proxy_dynflow_core/**/*', 'LICENSE', 'Gemfile',
20
19
  'bin/smart_proxy_dynflow_core', 'deploy/*', 'smart_proxy_dynflow_core.gemspec']
21
20
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
21
  gem.require_paths = ["lib"]
23
22
  gem.license = 'GPL-3.0'
24
23
 
25
- gem.add_development_dependency "bundler", "~> 1.7"
24
+ gem.required_ruby_version = '~> 2.5'
25
+
26
+ gem.add_development_dependency "bundler", ">= 1.7"
26
27
  gem.add_development_dependency('minitest')
27
28
  gem.add_development_dependency('mocha', '~> 1')
28
29
  gem.add_development_dependency('rack-test', '~> 0')
@@ -31,10 +32,11 @@ Gem::Specification.new do |gem|
31
32
 
32
33
  gem.add_runtime_dependency('dynflow', "~> 1.1")
33
34
  gem.add_runtime_dependency('foreman-tasks-core', '>= 0.3.3')
35
+ gem.add_runtime_dependency('logging')
34
36
  gem.add_runtime_dependency('rack')
35
37
  gem.add_runtime_dependency('rest-client')
38
+ gem.add_runtime_dependency('sd_notify', '~> 0.1')
36
39
  gem.add_runtime_dependency('sequel')
37
40
  gem.add_runtime_dependency('sinatra')
38
41
  gem.add_runtime_dependency('sqlite3')
39
42
  end
40
- # rubocop:enable Metrics/BlockLength
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_dynflow_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-15 00:00:00.000000000 Z
11
+ date: 1980-01-01 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
27
  - !ruby/object:Gem::Dependency
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: 0.3.3
125
+ - !ruby/object:Gem::Dependency
126
+ name: logging
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: rack
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +164,20 @@ dependencies:
150
164
  - - ">="
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: sd_notify
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.1'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.1'
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: sequel
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -214,33 +242,35 @@ files:
214
242
  - lib/smart_proxy_dynflow_core/helpers.rb
215
243
  - lib/smart_proxy_dynflow_core/launcher.rb
216
244
  - lib/smart_proxy_dynflow_core/log.rb
245
+ - lib/smart_proxy_dynflow_core/logger_middleware.rb
246
+ - lib/smart_proxy_dynflow_core/middleware/keep_current_request_id.rb
247
+ - lib/smart_proxy_dynflow_core/request_id_middleware.rb
217
248
  - lib/smart_proxy_dynflow_core/settings.rb
218
249
  - lib/smart_proxy_dynflow_core/task_launcher_registry.rb
219
250
  - lib/smart_proxy_dynflow_core/testing.rb
220
251
  - lib/smart_proxy_dynflow_core/version.rb
221
- - lib/smart_proxy_dynflow_core/webrick-patch.rb
222
252
  - smart_proxy_dynflow_core.gemspec
223
253
  homepage: https://github.com/theforeman/smart_proxy_dynflow
224
254
  licenses:
225
255
  - GPL-3.0
226
256
  metadata: {}
227
- post_install_message:
257
+ post_install_message:
228
258
  rdoc_options: []
229
259
  require_paths:
230
260
  - lib
231
261
  required_ruby_version: !ruby/object:Gem::Requirement
232
262
  requirements:
233
- - - ">="
263
+ - - "~>"
234
264
  - !ruby/object:Gem::Version
235
- version: '0'
265
+ version: '2.5'
236
266
  required_rubygems_version: !ruby/object:Gem::Requirement
237
267
  requirements:
238
268
  - - ">="
239
269
  - !ruby/object:Gem::Version
240
270
  version: '0'
241
271
  requirements: []
242
- rubygems_version: 3.0.3
243
- signing_key:
272
+ rubygems_version: 3.1.2
273
+ signing_key:
244
274
  specification_version: 4
245
275
  summary: Dynflow runtime for Foreman smart proxy
246
276
  test_files: []
@@ -1,38 +0,0 @@
1
- require 'webrick/https'
2
-
3
- CIPHERS = ['ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384',
4
- 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256',
5
- 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA'].freeze
6
-
7
- module WEBrick
8
- class GenericServer
9
- # rubocop:disable Metrics/AbcSize
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
- # rubocop:enable Metrics/AbcSize
37
- end
38
- end