Skip to content

Commit

Permalink
First version, somewhat hacky
Browse files Browse the repository at this point in the history
  • Loading branch information
GregSutcliffe committed Aug 2, 2013
0 parents commit 0b12f60
Show file tree
Hide file tree
Showing 10 changed files with 909 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Gemfile
@@ -0,0 +1,17 @@
source "http://rubygems.org"

gemspec

FOREMAN_GEMFILE=File.expand_path('../test/foreman_app/Gemfile', __FILE__)
unless File.exist?(FOREMAN_GEMFILE)
puts <<MESSAGE
Foreman source code is not present. To get the latest version, run:
rake test:foreman_prepare
and try again.
MESSAGE

else
self.instance_eval(Bundler.read_file(FOREMAN_GEMFILE))
end
619 changes: 619 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions README.md
@@ -0,0 +1,49 @@
# Foreman Default Hostgroup Plugin

A quick plugin to set a default hostgroup on hosts which check-in via Puppet without
a Hostgroup set.

## Installation

Usual Rails Engine installation - add to your Gemfile:

gem 'foreman_default_hostgroup', :git => 'https://github.com/GregSutcliffe/foreman_default_hostgroup'

then run `bundle update` and restart Foreman

## Usage

Go to `Settings -> DefaultHostgroup` and enter the name of the default hostgroup. Leaving
this blank disables the plugin.

Once set, any upload to `/fact_values/create` for a Host with no Hostgroup set will
cause the Hostgroup to be set to the value in the Settings. THis happens *before* the
ENC data is downloaded, meaning it applies for a Host's very first run.

## TODO

* Make this work for report uploads
* Test with nested hostgroups
* Tests

## Contributing

Fork and send me a Pull Request. Thanks!

## Copyright

Copyright (c) 2013 Greg Sutcliffe

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

111 changes: 111 additions & 0 deletions Rakefile
@@ -0,0 +1,111 @@
# encoding: utf-8

require 'rubygems'
require 'rake'
require 'fileutils'

task :default => :test

ENGINE_DIR = File.expand_path('..', __FILE__)
FOREMAN_DIR = 'test/foreman_app'

namespace :test do
desc "Download latest foreman devel source and install dependencies"
task :foreman_prepare do
foreman_repo = 'https://github.com/theforeman/foreman.git'
foreman_gemfile = File.join(FOREMAN_DIR, "Gemfile")
unless File.exists?(foreman_gemfile)
puts "Foreman source code is not present at #{FOREMAN_DIR}"
puts "Downloading latest Foreman development branch into #{FOREMAN_DIR}..."
FileUtils.mkdir_p(FOREMAN_DIR)

unless system("git clone #{foreman_repo} #{FOREMAN_DIR}")
puts "Error while getting latest Foreman code from #{foreman_repo} into #{FOREMAN_DIR}"
fail
end
end

gemfile_content = File.read(foreman_gemfile)
unless gemfile_content.include?('FOREMAN_GEMFILE')
puts 'Preparing Gemfile'
gemfile_content.gsub!('__FILE__', 'FOREMAN_GEMFILE')
gemfile_content.insert(0, "FOREMAN_GEMFILE = __FILE__ unless defined? FOREMAN_GEMFILE\n")
File.open(foreman_gemfile, 'w') { |f| f << gemfile_content }
end

settings_file = "#{FOREMAN_DIR}/config/settings.yaml"
unless File.exists?(settings_file)
puts 'Preparing settings file'
FileUtils.copy("#{settings_file}.example", settings_file)
settings_content = File.read(settings_file)
settings_content.sub!('organizations_enabled: false', 'organizations_enabled: true')
settings_content << ":puppetgem: true\n"
File.open(settings_file, 'w') { |f| f << settings_content }
end

db_file = "#{FOREMAN_DIR}/config/database.yml"
unless File.exists?(db_file)
puts 'Preparing database file'
FileUtils.copy("#{db_file}.example", db_file)
end

["#{ENGINE_DIR}/.bundle/config", "#{FOREMAN_DIR}/.bundle/config"].each do |bundle_file|
unless File.exists?(bundle_file)
FileUtils.mkdir_p(File.dirname(bundle_file))
puts 'Preparing bundler configuration'
File.open(bundle_file, 'w') { |f| f << <<FILE }
---
BUNDLE_WITHOUT: console:development:fog:jsonp:libvirt:mysql:mysql2:ovirt:postgresql:vmware
FILE
end
end

local_gemfile = "#{FOREMAN_DIR}/bundler.d/Gemfile.local.rb"
unless File.exist?(local_gemfile)
File.open(local_gemfile, 'w') { |f| f << <<GEMFILE }
gem "puppet"
gem "facter"
GEMFILE
end

puts 'Installing dependencies...'
unless system('bundle install')
fail
end
end

task :db_prepare do
unless File.exists?(FOREMAN_DIR)
puts <<MESSAGE
Foreman source code not prepared. Run
rake test:foreman_prepare
to download foreman source and its dependencies
MESSAGE
fail
end

# once we are Ruby19 only, switch to block variant of cd
pwd = FileUtils.pwd
FileUtils.cd(FOREMAN_DIR)
unless system('rake db:test:prepare RAILS_ENV=test')
puts "Migrating database first"
system('rake db:migrate db:schema:dump db:test:prepare RAILS_ENV=test') || fail
end
FileUtils.cd(pwd)
end

task :set_loadpath do
%w[lib test].each do |dir|
$:.unshift(File.expand_path(dir, ENGINE_DIR))
end
end

task :all => [:db_prepare, :set_loadpath] do
Dir.glob('test/**/*_test.rb') { |f| require f.sub('test/','') unless f.include? '/foreman_app/' }
end

end

task :test => 'test:all'
18 changes: 18 additions & 0 deletions app/models/setting/default_hostgroup.rb
@@ -0,0 +1,18 @@
class Setting::DefaultHostgroup < ::Setting
BLANK_ATTRS << 'default_hostgroup'

def self.load_defaults
# Check the table exists
return unless super

Setting.transaction do
[
self.set('default_hostgroup', 'The default Hostgroup to place new Hosts in', ''),
].compact.each { |s| self.create s.update(:category => 'Setting::DefaultHostgroup')}
end

true

end

end
24 changes: 24 additions & 0 deletions foreman_discovery.gemspec
@@ -0,0 +1,24 @@
$:.push File.expand_path("../lib", __FILE__)

# Maintain your gem's version:
require "foreman_default_hostgroup/version"

# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = %q{foreman_default_hostgroup}
s.version = ForemanDefaultHostgroup::VERSION
s.authors = ["Greg Sutcliffe"]
s.email = %q{gsutclif@redhat.com}
s.description = %q{Adds the option to specify a default hostgroup for new hosts created from facts/reports}
s.extra_rdoc_files = [
"LICENSE",
"README.md"
]
s.files = Dir["{app,extra,config,db,lib}/**/*"] + ["LICENSE", "Rakefile", "README.md"]
s.test_files = Dir["test/**/*"]
s.homepage = %q{http://github.com/GregSutcliffe/foreman_default_hostgroup}
s.licenses = ["GPL-3"]
s.summary = %q{Default Hostgroup Plugin for Foreman}

s.add_dependency "deface"
end
44 changes: 44 additions & 0 deletions lib/default_hostgroup_managed_host_patch.rb
@@ -0,0 +1,44 @@
require 'yaml'
module DefaultHostgroupManagedHostPatch
def self.included(base)
base.extend ClassMethods
base.class_eval do
class << self
alias_method_chain :importHostAndFacts, :apply_hostgroup
end
end
end

module ClassMethods
def importHostAndFacts_with_apply_hostgroup yaml
importHostAndFacts_without_apply_hostgroup yaml
Rails.logger.debug "DefaultHostgroup: performing Hostgroup check"
# The aliased method just returns true/false so we have to reparse the yaml
# to find the host
unless Setting[:default_hostgroup] == ''
facts = YAML::load yaml
case facts
when Puppet::Node::Facts
certname = facts.name
name = facts.values["fqdn"].downcase
when Hash
certname = facts["clientcert"] || facts["certname"]
name = facts["fqdn"].downcase
end
h=nil
if name == certname or certname.nil?
h = Host.find_by_name name
else
h = Host.find_by_certname certname
h ||= Host.find_by_name name
end
# Now we can update it
if h.hostgroup.nil?
h.hostgroup = Hostgroup.find_by_name(Setting[:default_hostgroup])
h.save
Rails.logger.debug "DefaultHostgroup: added #{h.name} to #{h.hostgroup.name}"
end
end
end
end
end
4 changes: 4 additions & 0 deletions lib/foreman_default_hostgroup.rb
@@ -0,0 +1,4 @@
require 'foreman_default_hostgroup/engine'

module ForemanDefaultHostgroup
end
20 changes: 20 additions & 0 deletions lib/foreman_default_hostgroup/engine.rb
@@ -0,0 +1,20 @@
require 'deface'
require 'default_hostgroup_managed_host_patch'

module ForemanDefaultHostgroup
#Inherit from the Rails module of the parent app (Foreman), not the plugin.
#Thus, inherits from ::Rails::Engine and not from Rails::Engine
class Engine < ::Rails::Engine

# Load this before the Foreman config initizializers, so that the Setting.descendants
# list includes the plugin STI setting class
initializer 'foreman_discovery.load_default_settings', :before => :load_config_initializers do |app|
require_dependency File.expand_path("../../../app/models/setting/default_hostgroup.rb", __FILE__) if (Setting.table_exists? rescue(false))
end

config.to_prepare do
::Host::Managed.send :include, DefaultHostgroupManagedHostPatch
end

end
end
3 changes: 3 additions & 0 deletions lib/foreman_default_hostgroup/version.rb
@@ -0,0 +1,3 @@
module ForemanDefaultHostgroup
VERSION = "0.0.1"
end

0 comments on commit 0b12f60

Please sign in to comment.