lib/config_skeleton.rb in config_skeleton-0.3.1 vs lib/config_skeleton.rb in config_skeleton-0.4.0

- old
+ new

@@ -3,10 +3,11 @@ require 'frankenstein' require 'logger' require 'rb-inotify' require 'service_skeleton' require 'tempfile' +require 'digest/md5' # Framework for creating config generation systems. # # There are many systems which require some sort of configuration file to # operate, and need that configuration to by dynamic over time. The intent @@ -21,12 +22,11 @@ # 1. Declare all the environment variables you care about, with the # ServiceSkeleton declaration methods `string`, `integer`, etc. # # 1. Implement service-specific config generation and reloading code, by # overriding the private methods #config_file, #config_data, and #reload_server -# (and also potentially #config_ok?, #sleep_duration, #before_regenerate_config, and -# #after_regenerate_config). +# (and also potentially #config_ok?, #sleep_duration, #before_regenerate_config, and #after_regenerate_config). # See the documentation for those methods for what they need to do. # # 1. Setup any file watchers you want with .watch and #watch. # # 1. Instantiate your new class, passing in an environment hash, and then call @@ -364,20 +364,27 @@ end # Run code before the config is regenerated and the config_file # is written. # + # @param force_reload [Boolean] Whether the regenerate_config was called with force_reload + # @param existing_config_hash [String] MD5 hash of the config file before regeneration. + # # @note this can optionally be implemented by subclasses. # - def before_regenerate_config(force_reload); end + def before_regenerate_config(force_reload:, existing_config_hash:); end - # Run code after the config is regenerated and if the regeneration - # was forced the new config has been cycled in. + # Run code after the config is regenerated and potentially a new file is written. # + # @param force_reload [Boolean] Whether the regenerate_config was called with force_reload + # @param config_was_different [Boolean] Whether the diff of the old and new config was different. + # @param config_was_cycled [Boolean] Whether a new config file was cycled in. + # @param new_config_hash [String] MD5 hash of the new config file after write. + # # @note this can optionally be implemented by subclasses. # - def after_regenerate_config(force_reload); end + def after_regenerate_config(force_reload:, config_was_different:, config_was_cycled:, new_config_hash:); end # Verify that the currently running config is acceptable. # # In the event that a generated config is "bad", it may be possible to detect # that the server hasn't accepted the new config, and if so, the config can @@ -456,36 +463,50 @@ # received, for instance), set `force_reload: true` and we'll be really insistent. # # @return [void] # def regenerate_config(force_reload: false) - before_regenerate_config(force_reload) + existing_config_hash = Digest::MD5.hexdigest(File.read(config_file)) + before_regenerate_config(force_reload: force_reload, existing_config_hash: existing_config_hash) logger.debug(logloc) { "force? #{force_reload.inspect}" } tmpfile = Tempfile.new(service_name, File.dirname(config_file)) logger.debug(logloc) { "Tempfile is #{tmpfile.path}" } unless (new_config = instrumented_config_data).nil? File.write(tmpfile.path, new_config) tmpfile.close - logger.debug(logloc) { require 'digest/md5'; "Existing config hash: #{Digest::MD5.hexdigest(File.read(config_file))}, new config hash: #{Digest::MD5.hexdigest(File.read(tmpfile.path))}" } + new_config_hash = Digest::MD5.hexdigest(File.read(tmpfile.path)) + logger.debug(logloc) do + "Existing config hash: #{existing_config_hash}, new config hash: #{new_config_hash}" + end + match_perms(config_file, tmpfile.path) - diff = Diffy::Diff.new(config_file, tmpfile.path, source: 'files', context: 3, include_diff_info: true) - if diff.to_s != "" - logger.info(logloc) { "Config has changed. Diff:\n#{diff.to_s}" } + diff = Diffy::Diff.new(config_file, tmpfile.path, source: 'files', context: 3, include_diff_info: true).to_s + config_was_different = diff != "" + + if config_was_different + logger.info(logloc) { "Config has changed. Diff:\n#{diff}" } end if force_reload logger.debug(logloc) { "Forcing config reload because force_reload == true" } end - if force_reload || diff.to_s != "" + config_was_cycled = false + if force_reload || config_was_different cycle_config(tmpfile.path) + config_was_cycled = true end end - after_regenerate_config(force_reload) + after_regenerate_config( + force_reload: force_reload, + config_was_different: config_was_different, + config_was_cycled: config_was_cycled, + new_config_hash: new_config_hash + ) ensure metrics.last_change_timestamp.set({}, File.stat(config_file).mtime.to_f) tmpfile.close rescue nil tmpfile.unlink rescue nil end