Class: ForemanHook::HostRename
- Inherits:
-
Object
- Object
- ForemanHook::HostRename
- Defined in:
- lib/foreman_hooks/host_rename.rb
Instance Attribute Summary collapse
-
#database_path ⇒ Object
Returns the value of attribute database_path.
Instance Method Summary collapse
-
#check_script(path) ⇒ Object
Do additional sanity checking on a hook script.
-
#debug(message) ⇒ Object
Convenience methods for writing to the logfile.
-
#execute_hook_action ⇒ Object
Update the database based on the foreman_hook.
- #execute_rename_action ⇒ Object
-
#foreman_uri(path) ⇒ Object
Given an absolute [
path
] within the Foreman API, return the full URI. -
#initialize(opts = {}) ⇒ HostRename
constructor
A new instance of HostRename.
-
#initialize_database ⇒ Object
Initialize an empty database.
- #install(hookdir = nil) ⇒ Object
- #log_level=(level) ⇒ Object
- #notice(message) ⇒ Object
-
#open_database ⇒ Object
Open a database connection.
- #open_logfile ⇒ Object
-
#parse_config(conffile = nil) ⇒ Object
Parse the configuration file.
- #parse_hook_data ⇒ Object
-
#rename? ⇒ Boolean
Check if the host has been renamed.
- #run ⇒ Object
-
#symbolize(obj) ⇒ Object
Given a nested hash, convert all keys from String to Symbol type Based on stackoverflow.com/questions/800122/best-way-to-convert-strings-to-symbols-in-hash.
-
#sync_host_table ⇒ Object
Get all the host IDs and FQDNs and populate the host table.
- #uninstall(hookdir = nil) ⇒ Object
-
#validate_database ⇒ Object
Do additional sanity checking on the database path.
- #warn(message) ⇒ Object
Constructor Details
#initialize(opts = {}) ⇒ HostRename
Returns a new instance of HostRename.
227 228 229 230 231 232 233 234 235 236 |
# File 'lib/foreman_hooks/host_rename.rb', line 227 def initialize(opts = {}) if opts.has_key? :config f = Tempfile.new('hook-settings') f.write(opts[:config].to_yaml) f.close parse_config(f.path) else parse_config end end |
Instance Attribute Details
#database_path ⇒ Object
Returns the value of attribute database_path.
37 38 39 |
# File 'lib/foreman_hooks/host_rename.rb', line 37 def database_path @database_path end |
Instance Method Details
#check_script(path) ⇒ Object
Do additional sanity checking on a hook script
90 91 92 93 94 95 |
# File 'lib/foreman_hooks/host_rename.rb', line 90 def check_script(path) binary=path.split(' ')[0] raise "#{path} does not exist" unless File.exist? binary raise "#{path} is not executable" unless File.executable? binary path end |
#debug(message) ⇒ Object
Convenience methods for writing to the logfile
223 |
# File 'lib/foreman_hooks/host_rename.rb', line 223 def debug() ; @log.debug() ; end |
#execute_hook_action ⇒ Object
Update the database based on the foreman_hook
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/foreman_hooks/host_rename.rb', line 146 def execute_hook_action @rename = false name = @rec['host']['name'] id = @rec['host']['id'] case @action when 'create' sql = "insert into host (id, name) values (?, ?)" params = [id, name] when 'update' # Check if we are renaming the host @old_name = @db.get_first_row('select name from host where id = ?', id)[0] if @old_name.nil? warn 'received an update for a non-existent host' else @rename = @old_name != name end debug "checking for a rename: old=#{@old_name} new=#{name} rename?=#{@rename}" sql = 'update host set name = ? where id = ?' params = [name, id] when 'destroy' sql = 'delete from host where id = ?' params = [id] else raise ArgumentError, "unsupported action: #{ARGV[0]}" end debug "updating database; id=#{id} name=#{name} sql=#{sql}" stm = @db.prepare sql stm.bind_params *params stm.execute end |
#execute_rename_action ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/foreman_hooks/host_rename.rb', line 185 def execute_rename_action raise 'old_name is nil' if @old_name.nil? raise 'new_name is nil' if @rec['host']['name'].nil? cmd = @rename_hook_command + ' ' + @old_name + ' ' + @rec['host']['name'] debug "Running the rename hook action: #{cmd}" open('|' + cmd, 'w+') do |subprocess| subprocess.write @rec.to_json end rc = $?.exitstatus warn "Hook exited with status #{rc}" if rc != 0 end |
#foreman_uri(path) ⇒ Object
Given an absolute [path
] within the Foreman API, return the full URI
98 99 100 101 102 |
# File 'lib/foreman_hooks/host_rename.rb', line 98 def foreman_uri(path) raise ArgumentError, 'path must start with a /' unless path =~ /^\// ['https://', @foreman_user, ':', @foreman_password, '@', @foreman_host, '/api/v2', path].join('') end |
#initialize_database ⇒ Object
Initialize an empty database
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/foreman_hooks/host_rename.rb', line 117 def initialize_database @db = SQLite3::Database.new @database_path File.chmod 0600, @database_path begin @db.execute 'drop table if exists host;' @db.execute <<-SQL create table host ( id INT, name varchar(254) ); SQL sync_host_table rescue File.unlink @database_path raise end end |
#install(hookdir = nil) ⇒ Object
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/foreman_hooks/host_rename.rb', line 251 def install(hookdir = nil) hookdir ||= '/usr/share/foreman/config/hooks/host/managed' raise "hook directory not found" unless File.exist? hookdir %w(create update destroy).each do |event| path = "#{hookdir}/#{event}" raise "path not found: #{path}" unless File.exist? path hook = "#{path}/99_host_rename" next if File.exist? hook f = File.open(hook, 'w') f.puts '#!/bin/sh' f.puts 'exec scl enable ruby193 "/usr/bin/foreman_hooks-host_rename $*"' f.close File.chmod 0755, hook end sysconfdir = '/etc/foreman_hooks-host_rename' Dir.mkdir sysconfdir unless File.exist? sysconfdir puts 'The hook has been installed. Please restart Apache to activate the hook.' end |
#log_level=(level) ⇒ Object
203 204 205 206 |
# File 'lib/foreman_hooks/host_rename.rb', line 203 def log_level=(level) @log_level = level @log.level = level end |
#notice(message) ⇒ Object
224 |
# File 'lib/foreman_hooks/host_rename.rb', line 224 def notice() ; @log.notice() ; end |
#open_database ⇒ Object
Open a database connection. If the database does not exist, initialize it.
136 137 138 139 140 141 142 143 |
# File 'lib/foreman_hooks/host_rename.rb', line 136 def open_database if File.exist? @database_path validate_database @db = SQLite3::Database.new @database_path else initialize_database end end |
#open_logfile ⇒ Object
208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/foreman_hooks/host_rename.rb', line 208 def open_logfile @log = Logger.new(@log_path, 10, 1024000) case @log_level when 'debug' @log.level = Logger::DEBUG when 'warn' @log.level = Logger::WARN when 'info' @log.level = Logger::INFO else raise 'Unsupported log_level' end end |
#parse_config(conffile = nil) ⇒ Object
Parse the configuration file
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/foreman_hooks/host_rename.rb', line 49 def parse_config(conffile = nil) conffile ||= Dir.glob([ "/etc/foreman_hooks-host_rename/settings.yaml", "#{confdir}/settings.yaml"])[0] raise "Could not locate the configuration file" if conffile.nil? # Parse the configuration file config = { hook_user: 'foreman', database_path: '/var/tmp/db/foreman_hooks-host_rename.db', log_path: '/var/tmp/foreman_hooks-host_rename.log', log_level: 'warn', rename_hook_command: '/bin/true', }.merge(symbolize(YAML.load(File.read(conffile)))) config.each do |k,v| instance_variable_set("@#{k}",v) end # Validate the schema document = Kwalify::Yaml.load_file(conffile) schema = Kwalify::Yaml.load_file("#{confdir}/schema.yaml") validator = Kwalify::Validator.new(schema) errors = validator.validate(document) if errors && !errors.empty? puts "WARNING: The following errors were found in #{conffile}:" for e in errors puts "[#{e.path}] #{e.}" end raise "Errors in the configuration file" end check_script @rename_hook_command end |
#parse_hook_data ⇒ Object
197 198 199 200 201 |
# File 'lib/foreman_hooks/host_rename.rb', line 197 def parse_hook_data @action = ARGV[0] # one of: create, update, destroy @rec = JSON.parse $stdin.read debug "action=#{@action} rec=#{@rec.inspect}" end |
#rename? ⇒ Boolean
Check if the host has been renamed
181 182 183 |
# File 'lib/foreman_hooks/host_rename.rb', line 181 def rename? @rename end |
#run ⇒ Object
238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/foreman_hooks/host_rename.rb', line 238 def run open_logfile begin open_database parse_hook_data execute_hook_action execute_rename_action if rename? rescue Exception => e @log.error e. @log.error e.backtrace.to_yaml end end |
#symbolize(obj) ⇒ Object
Given a nested hash, convert all keys from String to Symbol type Based on stackoverflow.com/questions/800122/best-way-to-convert-strings-to-symbols-in-hash
42 43 44 45 46 |
# File 'lib/foreman_hooks/host_rename.rb', line 42 def symbolize(obj) return obj.inject({}){|memo,(k,v)| memo[k.to_sym] = symbolize(v); memo} if obj.is_a? Hash return obj.inject([]){|memo,v | memo << symbolize(v); memo} if obj.is_a? Array return obj end |
#sync_host_table ⇒ Object
Get all the host IDs and FQDNs and populate the host table
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/foreman_hooks/host_rename.rb', line 105 def sync_host_table uri = foreman_uri('/hosts?per_page=9999999') debug "Loading hosts from #{uri}" json = RestClient.get uri debug "Got JSON: #{json}" JSON.parse(json)['results'].each do |rec| @db.execute "insert into host (id,name) values ( ?, ? )", rec['id'], rec['name'] end end |
#uninstall(hookdir = nil) ⇒ Object
270 271 272 273 274 275 276 277 278 |
# File 'lib/foreman_hooks/host_rename.rb', line 270 def uninstall(hookdir = nil) hookdir ||= '/usr/share/foreman/config/hooks/host/managed' %w(create update destroy).each do |event| hook = "#{hookdir}/#{event}/99_host_rename" #puts "removing #{hook}.." File.unlink hook if File.exist? hook end puts 'The hook has been uninstalled. Please restart Apache to deactivate the hook.' end |
#validate_database ⇒ Object
Do additional sanity checking on the database path
84 85 86 87 |
# File 'lib/foreman_hooks/host_rename.rb', line 84 def validate_database db = @database_path raise "bad mode of #{db}" unless File.world_readable?(db).nil? end |
#warn(message) ⇒ Object
225 |
# File 'lib/foreman_hooks/host_rename.rb', line 225 def warn() ; @log.warn() ; end |