Revision 611f5bff
Added by Amos Benari over 11 years ago
- ID 611f5bff49c1f06ae9ad0dd42b7566df9a02af2f
Gemfile | ||
---|---|---|
gem "audited-activerecord", "3.0.0.rc1"
|
||
gem "has_many_polymorphs", :git => "https://github.com/jystewart/has_many_polymorphs.git", :ref => '03429a61e511f394e9f96af0c8998268ca99d42b'
|
||
gem "will_paginate", "~> 3.0.2"
|
||
gem "ancestry", "~> 1.2.4"
|
||
gem "ancestry", "~> 1.3"
|
||
gem 'scoped_search', '>= 2.4'
|
||
gem 'net-ldap'
|
||
gem "safemode", "~> 1.0.1"
|
app/controllers/application_controller.rb | ||
---|---|---|
helper 'layout'
|
||
|
||
before_filter :require_ssl, :require_login
|
||
before_filter :require_mail
|
||
before_filter :session_expiry, :update_activity_time, :unless => proc {|c| c.remote_user_provided? || c.api_request? } if SETTINGS[:login]
|
||
before_filter :set_taxonomy, :require_mail
|
||
before_filter :welcome, :only => :index, :unless => :api_request?
|
||
before_filter :authorize
|
||
|
||
... | ... | |
def welcome
|
||
@searchbar = true
|
||
klass = controller_name == "dashboard" ? "Host" : controller_name.camelize.singularize
|
||
eval "#{klass}" rescue nil # We must force an autoload of the model class
|
||
if eval "defined?(#{klass}) and #{klass}.respond_to?(:unconfigured?) and #{klass}.unconfigured?"
|
||
if (klass.constantize.first.nil? rescue false)
|
||
@searchbar = false
|
||
render :welcome rescue nil and return
|
||
end
|
||
... | ... | |
# Force a user to login if authentication is enabled
|
||
# Sets User.current to the logged in user, or to admin if logins are not used
|
||
def require_login
|
||
unless session[:user] and (User.current = User.find(session[:user]))
|
||
unless session[:user] and (User.current = User.unscoped.find(session[:user]))
|
||
# User is not found or first login
|
||
if SETTINGS[:login]
|
||
# authentication is enabled
|
||
... | ... | |
# If REMOTE_USER is provided by the web server then
|
||
# authenticate the user without using password.
|
||
if remote_user_provided?
|
||
user = User.find_by_login(@remote_user)
|
||
user = User.unscoped.find_by_login(@remote_user)
|
||
logger.warn("Failed REMOTE_USER authentication from #{request.remote_ip}") unless user
|
||
# Else, fall back to the standard authentication mechanism,
|
||
# only if it's an API request.
|
||
... | ... | |
render :template => "common/500", :layout => !request.xhr?, :status => 500, :locals => { :exception => exception}
|
||
end
|
||
|
||
def set_taxonomy
|
||
return if User.current.nil?
|
||
|
||
if SETTINGS[:organizations_enabled]
|
||
orgs = Organization.my_organizations
|
||
Organization.current = if orgs.count == 1
|
||
orgs.first
|
||
elsif session[:org_id]
|
||
orgs.find(session[:org_id])
|
||
else
|
||
nil
|
||
end
|
||
end
|
||
|
||
if SETTINGS[:locations_enabled]
|
||
locations = Location.my_locations
|
||
Location.current = if locations.count == 1
|
||
locations.first
|
||
elsif session[:location_id]
|
||
locations.find(session[:location_id])
|
||
else
|
||
nil
|
||
end
|
||
end
|
||
end
|
||
|
||
end
|
app/controllers/fact_values_controller.rb | ||
---|---|---|
skip_before_filter :require_login, :only => :create
|
||
skip_before_filter :authorize, :only => :create
|
||
skip_before_filter :verify_authenticity_token, :only => :create
|
||
skip_before_filter :set_taxonomy, :only => :create
|
||
skip_before_filter :session_expiry, :update_activity_time, :only => :create
|
||
before_filter :set_admin_user, :only => :create
|
||
before_filter :setup_search_options, :only => :index
|
app/controllers/home_controller.rb | ||
---|---|---|
class HomeController < ApplicationController
|
||
skip_before_filter :require_login, :only => [:status]
|
||
skip_before_filter :authorize, :only => [:status]
|
||
skip_before_filter :authorize, :set_taxonomy, :only => [:status]
|
||
skip_before_filter :session_expiry, :update_activity_time, :only => :status
|
||
|
||
def settings
|
app/controllers/hosts_controller.rb | ||
---|---|---|
skip_before_filter :require_login, :only => ANONYMOUS_ACTIONS
|
||
skip_before_filter :require_ssl, :only => ANONYMOUS_ACTIONS
|
||
skip_before_filter :authorize, :only => ANONYMOUS_ACTIONS
|
||
skip_before_filter :set_taxonomy, :only => ANONYMOUS_ACTIONS
|
||
skip_before_filter :session_expiry, :update_activity_time, :only => ANONYMOUS_ACTIONS
|
||
before_filter :set_admin_user, :only => ANONYMOUS_ACTIONS
|
||
|
||
... | ... | |
|
||
def update
|
||
forward_request_url
|
||
if @host.update_attributes(params[:host])
|
||
process_success :success_redirect => host_path(@host), :redirect_xhr => request.xhr?
|
||
else
|
||
load_vars_for_ajax
|
||
offer_to_overwrite_conflicts
|
||
process_error
|
||
Taxonomy.no_taxonomy_scope do
|
||
if @host.update_attributes(params[:host])
|
||
process_success :success_redirect => host_path(@host), :redirect_xhr => request.xhr?
|
||
else
|
||
load_vars_for_ajax
|
||
offer_to_overwrite_conflicts
|
||
process_error
|
||
end
|
||
end
|
||
end
|
||
|
||
... | ... | |
def hostgroup_or_environment_selected
|
||
return head(:method_not_allowed) unless request.xhr?
|
||
|
||
@environment = Environment.find(params[:environment_id]) unless params[:environment_id].empty?
|
||
@hostgroup = Hostgroup.find(params[:hostgroup_id]) unless params[:hostgroup_id].empty?
|
||
@host = Host.find(params[:host_id]) if params[:host_id].to_i > 0
|
||
if @environment or @hostgroup
|
||
@host ||= Host.new
|
||
@host.hostgroup = @hostgroup if @hostgroup
|
||
@host.environment = @environment if @environment
|
||
render :partial => 'puppetclasses/class_selection', :locals => {:obj => (@host)}
|
||
else
|
||
head(:not_found)
|
||
@organization = params[:organization_id] ? Organization.find(params[:organization_id]) : nil
|
||
@location = params[:location_id] ? Location.find(params[:location_id]) : nil
|
||
Taxonomy.as_taxonomy @organization, @location do
|
||
|
||
@environment = Environment.find(params[:environment_id]) unless params[:environment_id].empty?
|
||
@hostgroup = Hostgroup.find(params[:hostgroup_id]) unless params[:hostgroup_id].empty?
|
||
@host = Host.find(params[:host_id]) if params[:host_id].to_i > 0
|
||
if @environment or @hostgroup
|
||
@host ||= Host.new
|
||
@host.hostgroup = @hostgroup if @hostgroup
|
||
@host.environment = @environment if @environment
|
||
render :partial => 'puppetclasses/class_selection', :locals => {:obj => (@host)}
|
||
else
|
||
head(:not_found)
|
||
end
|
||
end
|
||
end
|
||
|
||
... | ... | |
@hostgroup = Hostgroup.find(params[:hostgroup_id]) if params[:hostgroup_id].to_i > 0
|
||
return head(:not_found) unless @hostgroup
|
||
|
||
@architecture = @hostgroup.architecture
|
||
@operatingsystem = @hostgroup.operatingsystem
|
||
@environment = @hostgroup.environment
|
||
@domain = @hostgroup.domain
|
||
@subnet = @hostgroup.subnet
|
||
@organization = params[:organization_id] ? Organization.find(params[:organization_id]) : nil
|
||
@location = params[:location_id] ? Location.find(params[:location_id]) : nil
|
||
Taxonomy.as_taxonomy @organization, @location do
|
||
|
||
@host = Host.new
|
||
@host.hostgroup = @hostgroup
|
||
@host.compute_resource_id = params[:compute_resource_id] if params[:compute_resource_id].present?
|
||
@host.set_hostgroup_defaults
|
||
@architecture = @hostgroup.architecture
|
||
@operatingsystem = @hostgroup.operatingsystem
|
||
@environment = @hostgroup.environment
|
||
@domain = @hostgroup.domain
|
||
@subnet = @hostgroup.subnet
|
||
|
||
@host = Host.new
|
||
@host.hostgroup = @hostgroup
|
||
@host.compute_resource_id = params[:compute_resource_id] if params[:compute_resource_id].present?
|
||
@host.set_hostgroup_defaults
|
||
|
||
render :update do |page|
|
||
[:environment_id, :puppet_ca_proxy_id, :puppet_proxy_id].each do |field|
|
||
page["*[id*=#{field}]"].val(@hostgroup.send(field)) if @hostgroup.send(field).present?
|
||
end
|
||
page['#puppet_klasses'].html(render(:partial => 'puppetclasses/class_selection', :locals => {:obj => @host})) if @environment
|
||
|
||
if SETTINGS[:unattended]
|
||
if @architecture
|
||
page['#os_select'].html(render(:partial => 'common/os_selection/architecture', :locals => {:item => @host}))
|
||
page['#*[id*=architecture_id]'].val(@architecture.id)
|
||
render :update do |page|
|
||
[:environment_id, :puppet_ca_proxy_id, :puppet_proxy_id].each do |field|
|
||
page["*[id*=#{field}]"].val(@hostgroup.send(field)) if @hostgroup.send(field).present?
|
||
end
|
||
page['#puppet_klasses'].html(render(:partial => 'puppetclasses/class_selection', :locals => {:obj => @host})) if @environment
|
||
|
||
page['#media_select'].html(render(:partial => 'common/os_selection/operatingsystem', :locals => {:item => @host})) if @operatingsystem
|
||
if SETTINGS[:unattended]
|
||
if @architecture
|
||
page['#os_select'].html(render(:partial => 'common/os_selection/architecture', :locals => {:item => @host}))
|
||
page['#*[id*=architecture_id]'].val(@architecture.id)
|
||
end
|
||
|
||
if @domain
|
||
page['*[id*=domain_id]'].val(@domain.id)
|
||
if @domain.subnets.any?
|
||
page['#subnet_select'].html(render(:partial => 'common/domain', :locals => {:item => @host}))
|
||
page['#host_subnet_id'].val(@subnet.id).change if @subnet
|
||
page['#sp_subnet'].html(render(:partial => 'hosts/sp_subnet', :locals => {:item => @host}))
|
||
page['#media_select'].html(render(:partial => 'common/os_selection/operatingsystem', :locals => {:item => @host})) if @operatingsystem
|
||
|
||
if @domain
|
||
page['*[id*=domain_id]'].val(@domain.id)
|
||
if @domain.subnets.any?
|
||
page['#subnet_select'].html(render(:partial => 'common/domain', :locals => {:item => @host}))
|
||
page['#host_subnet_id'].val(@subnet.id).change if @subnet
|
||
page['#sp_subnet'].html(render(:partial => 'hosts/sp_subnet', :locals => {:item => @host}))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
def process_taxonomy
|
||
location = organization = nil
|
||
organization = Organization.find(params[:host][:organization_id]) unless params[:host][:organization_id].empty?
|
||
location = Location.find(params[:host][:location_id]) unless params[:host][:location_id].empty?
|
||
return head(:not_found) unless location || organization
|
||
|
||
@host = Host.new(params[:host])
|
||
Taxonomy.as_taxonomy organization, location do
|
||
render :partial => "form"
|
||
end
|
||
end
|
||
|
||
|
||
def template_used
|
||
kinds = params[:provisioning] == 'image' ? [TemplateKind.find_by_name('finish')] : TemplateKind.all
|
||
templates = kinds.map do |kind|
|
||
... | ... | |
|
||
def load_vars_for_ajax
|
||
return unless @host
|
||
|
||
@environment = @host.environment
|
||
@architecture = @host.architecture
|
||
@domain = @host.domain
|
||
... | ... | |
if @host.compute_resource_id && params[:host] && params[:host][:compute_attributes]
|
||
@host.compute_attributes = params[:host][:compute_attributes]
|
||
end
|
||
|
||
end
|
||
|
||
def find_multiple
|
app/controllers/locations_controller.rb | ||
---|---|---|
class LocationsController < ApplicationController
|
||
include Foreman::Controller::AutoCompleteSearch
|
||
|
||
before_filter :find_location, :only => %w{edit update destroy clone}
|
||
skip_before_filter :authorize, :set_taxonomy, :only => %w{select}
|
||
|
||
def index
|
||
begin
|
||
values = Location.my_locations.search_for(params[:search], :order => params[:order])
|
||
rescue => e
|
||
error e.to_s
|
||
values = Location.my_locations.search_for('')
|
||
end
|
||
|
||
respond_to do |format|
|
||
format.html do
|
||
@locations = values.paginate :page => params[:page]
|
||
end
|
||
end
|
||
end
|
||
|
||
def new
|
||
@location = Location.new
|
||
Taxonomy.no_taxonomy_scope do
|
||
# we explicitly render here in order to evaluate the view without taxonomy scope
|
||
render :new
|
||
end
|
||
end
|
||
|
||
def clone
|
||
new = @location.clone
|
||
# copy all the relations
|
||
new.name = ""
|
||
new.users = @location.users
|
||
new.smart_proxies = @location.smart_proxies
|
||
new.subnets = @location.subnets
|
||
new.compute_resources = @location.compute_resources
|
||
new.media = @location.media
|
||
new.domains = @location.domains
|
||
new.media = @location.media
|
||
new.hostgroups = @location.hostgroups
|
||
new.organizations = @location.organizations
|
||
|
||
@location = new
|
||
render :action => :new
|
||
end
|
||
|
||
def create
|
||
@location = Location.new(params[:location])
|
||
|
||
if @location.save
|
||
process_success
|
||
else
|
||
process_error
|
||
end
|
||
end
|
||
|
||
def edit
|
||
Taxonomy.no_taxonomy_scope do
|
||
# we explicitly render here in order to evaluate the view without taxonomy scope
|
||
render :edit
|
||
end
|
||
end
|
||
|
||
def update
|
||
result = Taxonomy.no_taxonomy_scope do
|
||
@location.update_attributes(params[:location])
|
||
end
|
||
if result
|
||
process_success
|
||
else
|
||
process_error
|
||
end
|
||
end
|
||
|
||
def destroy
|
||
if @location.destroy
|
||
process_success
|
||
else
|
||
process_error
|
||
end
|
||
end
|
||
|
||
def select
|
||
@location = params[:id] ? Location.find(params[:id]) : nil
|
||
Location.current = @location
|
||
session[:location_id] = @location ? @location.id : nil
|
||
redirect_back_or_to root_url
|
||
end
|
||
|
||
private
|
||
def find_location
|
||
@location = Location.find(params[:id])
|
||
end
|
||
end
|
app/controllers/organizations_controller.rb | ||
---|---|---|
class OrganizationsController < ApplicationController
|
||
include Foreman::Controller::AutoCompleteSearch
|
||
|
||
before_filter :find_organization, :only => %w{edit update destroy clone}
|
||
skip_before_filter :authorize, :set_taxonomy, :only => %w{select}
|
||
|
||
def index
|
||
begin
|
||
values = Organization.my_organizations.search_for(params[:search], :order => params[:order])
|
||
rescue => e
|
||
error e.to_s
|
||
values = Organization.my_organizations.search_for ""
|
||
end
|
||
|
||
respond_to do |format|
|
||
format.html do
|
||
@organizations = values.paginate :page => params[:page]
|
||
end
|
||
end
|
||
end
|
||
|
||
def new
|
||
@organization = Organization.new
|
||
Taxonomy.no_taxonomy_scope do
|
||
render :new
|
||
end
|
||
end
|
||
|
||
def clone
|
||
new = @organization.clone
|
||
# copy all the relations
|
||
new.name = ""
|
||
new.users = @organization.users
|
||
new.smart_proxies = @organization.smart_proxies
|
||
new.subnets = @organization.subnets
|
||
new.compute_resources = @organization.compute_resources
|
||
new.media = @organization.media
|
||
new.domains = @organization.domains
|
||
new.media = @organization.media
|
||
new.hostgroups = @organization.hostgroups
|
||
new.locations = @organization.locations
|
||
|
||
@organization = new
|
||
render :action => :new
|
||
end
|
||
|
||
def create
|
||
@organization = Organization.new(params[:organization])
|
||
|
||
if @organization.save
|
||
process_success
|
||
else
|
||
process_error
|
||
end
|
||
end
|
||
|
||
def edit
|
||
Taxonomy.no_taxonomy_scope do
|
||
render :edit
|
||
end
|
||
end
|
||
|
||
def update
|
||
result = Taxonomy.no_taxonomy_scope do
|
||
@organization.update_attributes(params[:organization])
|
||
end
|
||
|
||
if result
|
||
process_success
|
||
else
|
||
process_error
|
||
end
|
||
end
|
||
|
||
def destroy
|
||
if @organization.destroy
|
||
process_success
|
||
else
|
||
process_error
|
||
end
|
||
end
|
||
|
||
def select
|
||
@organization = params[:id] ? Organization.find(params[:id]) : nil
|
||
Organization.current = @organization
|
||
session[:org_id] = @organization ? @organization.id : nil
|
||
redirect_back_or_to root_url
|
||
end
|
||
|
||
private
|
||
def find_organization
|
||
@organization = Organization.find(params[:id])
|
||
end
|
||
end
|
app/controllers/reports_controller.rb | ||
---|---|---|
skip_before_filter :require_ssl, :only => :create
|
||
skip_before_filter :authorize, :only => :create
|
||
skip_before_filter :verify_authenticity_token, :only => :create
|
||
skip_before_filter :set_taxonomy, :only => :create
|
||
skip_before_filter :session_expiry, :update_activity_time, :only => :create
|
||
before_filter :set_admin_user, :only => :create
|
||
before_filter :setup_search_options, :only => :index
|
app/controllers/tasks_controller.rb | ||
---|---|---|
class TasksController < ApplicationController
|
||
skip_before_filter :session_expiry, :update_activity_time, :only => [:show]
|
||
skip_before_filter :session_expiry, :update_activity_time, :set_taxonomy, :only => [:show]
|
||
|
||
def show
|
||
id = params[:id]
|
app/controllers/topbar_sweeper.rb | ||
---|---|---|
class TopbarSweeper < ActionController::Caching::Sweeper
|
||
observe [Bookmark, User, UserRole] # This sweeper is going to keep an eye on the Bookmark model
|
||
observe [Bookmark, User, UserRole, Organization, Location] # This sweeper is going to keep an eye on the Bookmark model
|
||
|
||
def after_create(record)
|
||
expire_cache_for(record)
|
||
... | ... | |
expire_cache_for(record)
|
||
end
|
||
|
||
def after_select(record)
|
||
expire_cache_for(record)
|
||
end
|
||
|
||
private
|
||
def expire_cache_for(record)
|
||
expire_fragment("tabs_and_title_records-#{User.current.id}") if User.current
|
app/controllers/unattended_controller.rb | ||
---|---|---|
FINISH_URLS = [:preseed_finish, :jumpstart_finish] + TemplateKind.where("name LIKE ?", "finish").map(&:name)
|
||
|
||
# We dont require any of these methods for provisioning
|
||
skip_before_filter :require_ssl, :require_login, :authorize, :session_expiry, :update_activity_time
|
||
skip_before_filter :require_ssl, :require_login, :authorize, :session_expiry, :update_activity_time, :set_taxonomy
|
||
|
||
# require logged in user to see templates in spoof mode
|
||
before_filter do |c|
|
app/controllers/users_controller.rb | ||
---|---|---|
include Foreman::Controller::AutoCompleteSearch
|
||
|
||
skip_before_filter :require_mail, :only => [:edit, :update, :logout]
|
||
skip_before_filter :require_login, :authorize, :session_expiry, :update_activity_time, :only => [:login, :logout]
|
||
skip_before_filter :require_login, :authorize, :session_expiry, :update_activity_time, :set_taxonomy, :only => [:login, :logout]
|
||
after_filter :update_activity_time, :only => :login
|
||
|
||
attr_accessor :editing_self
|
app/helpers/home_helper.rb | ||
---|---|---|
['Smart Proxies', :smart_proxies]
|
||
]
|
||
|
||
choices += [ [:divider] ]
|
||
if (SETTINGS[:organizations_enabled] or SETTINGS[:locations_enabled])
|
||
choices += [ ['Locations', :locations] ] if SETTINGS[:locations_enabled]
|
||
choices += [ ['Organizations', :organizations] ] if SETTINGS[:organizations_enabled]
|
||
choices += [ [:divider ] ]
|
||
end
|
||
|
||
|
||
if SETTINGS[:unattended]
|
||
choices += [
|
||
['Compute Resources', :compute_resources]
|
||
]
|
||
|
||
choices += [
|
||
[:divider],
|
||
['Architectures', :architectures],
|
||
['Compute Resources', :compute_resources],
|
||
['Domains', :domains],
|
||
['Hardware Models', :models],
|
||
['Installation Media', :media],
|
app/helpers/hosts_helper.rb | ||
---|---|---|
["Operating System", host.os],
|
||
["Host Group", host.hostgroup],
|
||
]
|
||
fields += [["Location", Location.find(host.location_id).name]] unless host.location_id.nil?
|
||
fields += [["Organization", Organization.find(host.organization_id).name]] unless host.organization_id.nil?
|
||
fields += [["Owner", host.owner]] if SETTINGS[:login]
|
||
fields += [["Certificate Name", host.certname]] if Setting[:use_uuid_for_certificates]
|
||
fields
|
app/helpers/organization_helper.rb | ||
---|---|---|
module OrganizationHelper
|
||
end
|
app/helpers/taxonomy_helper.rb | ||
---|---|---|
module TaxonomyHelper
|
||
def show_location_tab?
|
||
SETTINGS[:locations_enabled] && User.current.allowed_to?(:view_locations)
|
||
end
|
||
|
||
def show_organization_tab?
|
||
SETTINGS[:organizations_enabled] && User.current.allowed_to?(:view_organizations)
|
||
end
|
||
|
||
def show_taxonomy_tabs?
|
||
SETTINGS[:locations_enabled] or SETTINGS[:organizations_enabled]
|
||
end
|
||
|
||
def show_add_location_button? count
|
||
count ==0 && User.current.allowed_to?(:create_locations)
|
||
end
|
||
|
||
def show_add_organization_button? count
|
||
count == 0 && User.current.allowed_to?(:create_organizations)
|
||
end
|
||
|
||
def organization_dropdown count
|
||
text = Organization.current.nil? ? "Organizations" : Organization.current.to_label
|
||
if count == 1
|
||
link_to text, "#", :title => "Current Organization"
|
||
else
|
||
link_to((text + content_tag(:span,'', :class=>"caret")).html_safe, "#", :class => "dropdown-toggle", :'data-toggle'=>"dropdown", :title => "Current Organization")
|
||
end
|
||
end
|
||
|
||
def location_dropdown count
|
||
text = Location.current.nil? ? "Locations" : Location.current.to_label
|
||
if count == 1
|
||
link_to text, "#", :title => "Current Location"
|
||
else
|
||
link_to((text + content_tag(:span,'', :class=>"caret")).html_safe, "#", :class => "dropdown-toggle", :'data-toggle'=>"dropdown", :title => "Current Location")
|
||
end
|
||
end
|
||
end
|
app/models/compute_resource.rb | ||
---|---|---|
require 'fog_extensions'
|
||
class ComputeResource < ActiveRecord::Base
|
||
include Taxonomix
|
||
PROVIDERS = %w[ Libvirt Ovirt EC2 Vmware Openstack].delete_if{|p| p == "Libvirt" && !SETTINGS[:libvirt]}
|
||
audited :except => [:password, :attrs]
|
||
serialize :attrs, Hash
|
||
... | ... | |
has_many :images, :dependent => :destroy
|
||
before_validation :set_attributes_hash
|
||
|
||
default_scope :order => 'LOWER(compute_resources.name)'
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order("LOWER(compute_resources.name)")
|
||
end
|
||
}
|
||
|
||
scope :my_compute_resources, lambda {
|
||
user = User.current
|
app/models/domain.rb | ||
---|---|---|
# This models a DNS domain and so represents a site.
|
||
class Domain < ActiveRecord::Base
|
||
include Authorization
|
||
include Taxonomix
|
||
|
||
has_many :hosts
|
||
has_many :hostgroups
|
||
#order matters! see https://github.com/rails/rails/issues/670
|
||
... | ... | |
belongs_to :dns, :class_name => "SmartProxy"
|
||
has_many :domain_parameters, :dependent => :destroy, :foreign_key => :reference_id
|
||
has_and_belongs_to_many :users, :join_table => "user_domains"
|
||
|
||
accepts_nested_attributes_for :domain_parameters, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
|
||
validates_uniqueness_of :name
|
||
validates_uniqueness_of :fullname, :allow_blank => true, :allow_nil => true
|
||
... | ... | |
scoped_search :on => [:name, :fullname], :complete_value => true
|
||
scoped_search :in => :domain_parameters, :on => :value, :on_key=> :name, :complete_value => true, :only_explicit => true, :rename => :params
|
||
|
||
default_scope :order => 'LOWER(domains.name)'
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order("LOWER(domains.name)")
|
||
end
|
||
}
|
||
|
||
class Jail < Safemode::Jail
|
||
allow :name, :fullname
|
app/models/environment.rb | ||
---|---|---|
class Environment < ActiveRecord::Base
|
||
include Taxonomix
|
||
has_many :environment_classes, :dependent => :destroy
|
||
has_many :puppetclasses, :through => :environment_classes, :uniq => true
|
||
has_many :hosts
|
||
... | ... | |
has_many :template_combinations
|
||
|
||
before_destroy EnsureNotUsedBy.new(:hosts)
|
||
default_scope :order => 'environments.name'
|
||
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order("LOWER(environments.name)")
|
||
end
|
||
}
|
||
|
||
scoped_search :on => :name, :complete_value => :true
|
||
|
app/models/host.rb | ||
---|---|---|
belongs_to :sp_subnet, :class_name => "Subnet"
|
||
belongs_to :compute_resource
|
||
belongs_to :image
|
||
|
||
belongs_to :location
|
||
belongs_to :organization
|
||
|
||
has_one :token, :dependent => :destroy, :conditions => Proc.new {"expires >= '#{Time.now.utc.to_s(:db)}'"}
|
||
|
||
has_many :lookup_values, :finder_sql => Proc.new { normalize_hostname; %Q{ SELECT lookup_values.* FROM lookup_values WHERE (lookup_values.match = 'fqdn=#{fqdn}') } }, :dependent => :destroy
|
||
... | ... | |
include HostCommon
|
||
|
||
class Jail < ::Safemode::Jail
|
||
allow :name, :diskLayout, :puppetmaster, :puppet_ca_server, :operatingsystem, :os, :environment, :ptable, :hostgroup, :url_for_boot,
|
||
:params, :info, :hostgroup, :compute_resource, :domain, :ip, :mac, :shortname, :architecture, :model, :certname, :capabilities,
|
||
:provider, :subnet, :token
|
||
allow :name, :diskLayout, :puppetmaster, :puppet_ca_server, :operatingsystem, :os, :environment, :ptable, :hostgroup, :location,
|
||
:organization, :url_for_boot, :params, :info, :hostgroup, :compute_resource, :domain, :ip, :mac, :shortname, :architecture,
|
||
:model, :certname, :capabilities, :provider, :subnet, :token
|
||
end
|
||
|
||
attr_reader :cached_host_params
|
||
|
||
default_scope lambda {
|
||
org = Organization.current
|
||
loc = Location.current
|
||
conditions = {}
|
||
conditions[:organization_id] = org.id if org
|
||
conditions[:location_id] = loc.id if loc
|
||
where(conditions)
|
||
}
|
||
|
||
scope :recent, lambda { |*args| {:conditions => ["last_report > ?", (args.first || (Setting[:puppet_interval] + 5).minutes.ago)]} }
|
||
scope :out_of_sync, lambda { |*args| {:conditions => ["last_report < ? and enabled != ?", (args.first || (Setting[:puppet_interval] + 5).minutes.ago), false]} }
|
||
|
||
... | ... | |
domain_conditions = sanitize_sql_for_conditions([" (hosts.domain_id in (?))",dms = (user.domains).map(&:id)])
|
||
compute_resource_conditions = sanitize_sql_for_conditions([" (hosts.compute_resource_id in (?))",(crs = user.compute_resources).map(&:id)])
|
||
hostgroup_conditions = sanitize_sql_for_conditions([" (hosts.hostgroup_id in (?))",(hgs = user.hostgroups).map(&:id)])
|
||
organization_conditions = sanitize_sql_for_conditions([" (hosts.organization_id in (?))",orgs = (user.organizations).map(&:id)])
|
||
location_conditions = sanitize_sql_for_conditions([" (hosts.location_id in (?))",locs = (user.locations).map(&:id)])
|
||
|
||
fact_conditions = ""
|
||
for user_fact in (ufs = user.user_facts)
|
||
... | ... | |
(conditions = (user.compute_resources_andor == "and") ? "(#{conditions}) and #{compute_resource_conditions} " : "#{conditions} or #{compute_resource_conditions} ") unless crs.empty?
|
||
(conditions = (user.hostgroups_andor == "and") ? "(#{conditions}) and #{hostgroup_conditions} " : "#{conditions} or #{hostgroup_conditions} ") unless hgs.empty?
|
||
(conditions = (user.facts_andor == "and") ? "(#{conditions}) and #{fact_conditions} " : "#{conditions} or #{fact_conditions} ") unless ufs.empty?
|
||
(conditions = (user.organizations_andor == "and") ? "(#{conditions}) and #{organization_conditions} " : "#{conditions} or #{organization_conditions} ") unless orgs.empty?
|
||
(conditions = (user.locations_andor == "and") ? "(#{conditions}) and #{location_conditions} " : "#{conditions} or #{location_conditions} ") unless locs.empty?
|
||
conditions.sub!(/\s*\(\)\s*/, "")
|
||
conditions.sub!(/^(?:\(\))?\s?(?:and|or)\s*/, "")
|
||
conditions.sub!(/\(\s*(?:or|and)\s*\(/, "((")
|
app/models/hostext/search.rb | ||
---|---|---|
scoped_search :in => :fact_values, :on => :value, :in_key=> :fact_names, :on_key=> :name, :rename => :facts, :complete_value => true, :only_explicit => true
|
||
scoped_search :in => :search_parameters, :on => :value, :on_key=> :name, :complete_value => true, :rename => :params, :ext_method => :search_by_params, :only_explicit => true
|
||
|
||
scoped_search :in => :location, :on => :name, :rename => :location, :complete_value => true if SETTINGS[:locations_enabled]
|
||
scoped_search :in => :organization, :on => :name, :rename => :organization, :complete_value => true if SETTINGS[:organizations_enabled]
|
||
|
||
if SETTINGS[:unattended]
|
||
scoped_search :in => :subnet, :on => :network, :complete_value => true, :rename => :subnet
|
||
scoped_search :on => :mac, :complete_value => true
|
app/models/hostgroup.rb | ||
---|---|---|
class Hostgroup < ActiveRecord::Base
|
||
has_ancestry :orphan_strategy => :rootify
|
||
include Authorization
|
||
include Taxonomix
|
||
include HostCommon
|
||
has_many :hostgroup_classes, :dependent => :destroy
|
||
has_many :puppetclasses, :through => :hostgroup_classes
|
||
... | ... | |
audited
|
||
has_many :trends, :as => :trendable, :class_name => "ForemanTrend"
|
||
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda { with_taxonomy_scope }
|
||
|
||
scoped_search :on => :name, :complete_value => :true
|
||
scoped_search :in => :group_parameters, :on => :value, :on_key=> :name, :complete_value => true, :only_explicit => true, :rename => :params
|
||
scoped_search :in => :hosts, :on => :name, :complete_value => :true, :rename => "host"
|
app/models/location.rb | ||
---|---|---|
class Location < Taxonomy
|
||
include Foreman::ThreadSession::LocationModel
|
||
|
||
has_and_belongs_to_many :organizations
|
||
has_many :hosts
|
||
before_destroy EnsureNotUsedBy.new(:hosts)
|
||
|
||
scope :completer_scope, lambda { my_locations }
|
||
|
||
scope :my_locations, lambda {
|
||
user = User.current
|
||
if user.admin?
|
||
conditions = { }
|
||
else
|
||
conditions = sanitize_sql_for_conditions([" (taxonomies.id in (?))", user.locations.map(&:id)])
|
||
end
|
||
where(conditions).reorder('type, name')
|
||
}
|
||
end
|
app/models/medium.rb | ||
---|---|---|
class Medium < ActiveRecord::Base
|
||
include Authorization
|
||
include Taxonomix
|
||
has_and_belongs_to_many :operatingsystems
|
||
has_many :hosts
|
||
|
||
... | ... | |
:if => Proc.new { |m| m.respond_to? :media_path }
|
||
|
||
before_destroy EnsureNotUsedBy.new(:hosts)
|
||
default_scope :order => 'LOWER(media.name)'
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order("LOWER(media.name)")
|
||
end
|
||
}
|
||
scoped_search :on => :name, :complete_value => :true, :default_order => true
|
||
scoped_search :on => :path, :complete_value => :true
|
||
scoped_search :on => :os_family, :rename => "family", :complete_value => :true
|
app/models/organization.rb | ||
---|---|---|
class Organization < Taxonomy
|
||
include Foreman::ThreadSession::OrganizationModel
|
||
|
||
has_and_belongs_to_many :locations
|
||
has_many :hosts
|
||
before_destroy EnsureNotUsedBy.new(:hosts)
|
||
|
||
scope :completer_scope, lambda { my_organizations }
|
||
|
||
scope :my_organizations, lambda {
|
||
user = User.current
|
||
if user.admin?
|
||
conditions = { }
|
||
else
|
||
conditions = sanitize_sql_for_conditions([" (taxonomies.id in (?))", user.organizations.map(&:id)])
|
||
end
|
||
where(conditions).reorder('type, name')
|
||
}
|
||
end
|
app/models/smart_proxy.rb | ||
---|---|---|
class SmartProxy < ActiveRecord::Base
|
||
include Taxonomix
|
||
ProxyFeatures = %w[ TFTP BMC DNS DHCP Puppetca Puppet]
|
||
attr_accessible :name, :url
|
||
#TODO check if there is a way to look into the tftp_id too
|
||
... | ... | |
before_save :sanitize_url, :associate_features
|
||
before_destroy EnsureNotUsedBy.new(:subnets, :domains, :hosts, :hostgroups)
|
||
|
||
default_scope :order => 'LOWER(smart_proxies.name)'
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order("LOWER(smart_proxies.name)")
|
||
end
|
||
}
|
||
ProxyFeatures.each {|f| scope "#{f.downcase}_proxies".to_sym, where(:features => {:name => f}).joins(:features) }
|
||
|
||
def hostname
|
app/models/subnet.rb | ||
---|---|---|
require 'ipaddr'
|
||
class Subnet < ActiveRecord::Base
|
||
include Authorization
|
||
include Taxonomix
|
||
has_many :hosts
|
||
# sps = Service processors / ilom boards etc
|
||
has_many :sps, :class_name => "Host", :foreign_key => 'sp_subnet_id'
|
||
... | ... | |
validates_format_of :network, :mask, :with => Net::Validations::IP_REGEXP
|
||
validates_format_of :gateway, :dns_primary, :dns_secondary, :with => Net::Validations::IP_REGEXP, :allow_blank => true, :allow_nil => true
|
||
validate :name_should_be_uniq_across_domains
|
||
default_scope :order => 'priority'
|
||
|
||
validate :validate_ranges
|
||
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order('vlanid')
|
||
end
|
||
}
|
||
|
||
before_destroy EnsureNotUsedBy.new(:hosts, :sps)
|
||
|
||
scoped_search :on => [:name, :network, :mask, :gateway, :dns_primary, :dns_secondary, :vlanid], :complete_value => true
|
||
... | ... | |
# [+other+] : Subnet object with which to compare ourself
|
||
# +returns+ : Subnet object with higher precedence
|
||
def <=> (other)
|
||
self.priority <=> other.priority
|
||
self.vlanid <=> other.vlanid
|
||
end
|
||
|
||
# Given an IP returns the subnet that contains that IP
|
app/models/taxable_taxonomy.rb | ||
---|---|---|
class TaxableTaxonomy < ActiveRecord::Base
|
||
belongs_to :taxonomy
|
||
belongs_to :taxable, :polymorphic => true
|
||
|
||
validates_uniqueness_of :taxonomy_id, :scope => [:taxable_id, :taxable_type]
|
||
end
|
app/models/taxonomix.rb | ||
---|---|---|
module Taxonomix
|
||
def self.included(base)
|
||
base.send :include, InstanceMethods
|
||
|
||
base.class_eval do
|
||
@taxonomy_join_table = "taxable_taxonomies"
|
||
@primary_key = "taxable_id"
|
||
has_many @taxonomy_join_table, :dependent => :destroy, :as => :taxable
|
||
has_many :locations, :through => @taxonomy_join_table, :source => :taxonomy, :class_name => 'Location'
|
||
has_many :organizations, :through => @taxonomy_join_table, :source => :taxonomy, :class_name => 'Organization'
|
||
after_initialize :set_current_taxonomy
|
||
|
||
scoped_search :in => :locations, :on => :name, :rename => :location, :complete_value => true
|
||
scoped_search :in => :organizations, :on => :name, :rename => :organization, :complete_value => true
|
||
|
||
def self.with_taxonomy_scope
|
||
scope = block_given? ? yield : where(1)
|
||
|
||
scope = scope.joins(taxonomy_join_condition 'loc1').where("loc1.taxonomy_id in (?)", Location.current.id) if SETTINGS[:locations_enabled] and Location.current
|
||
scope = scope.joins(taxonomy_join_condition 'org1').where("org1.taxonomy_id in (?)", Organization.current.id) if SETTINGS[:organizations_enabled] and Organization.current
|
||
|
||
scope
|
||
end
|
||
|
||
def self.taxonomy_join_condition name
|
||
" INNER JOIN #{@taxonomy_join_table} #{name} ON #{name}.#{@primary_key} = #{self.table_name}.id and #{name}.taxable_type = '#{self.to_s}'"
|
||
end
|
||
|
||
end
|
||
end
|
||
|
||
module InstanceMethods
|
||
def set_current_taxonomy
|
||
if self.new_record? && self.errors.empty?
|
||
self.locations << Location.current if Taxonomy.locations_enabled and Location.current
|
||
self.organizations << Organization.current if Taxonomy.organizations_enabled and Organization.current
|
||
end
|
||
end
|
||
|
||
end
|
||
|
||
end
|
app/models/taxonomy.rb | ||
---|---|---|
class Taxonomy < ActiveRecord::Base
|
||
audited
|
||
has_associated_audits
|
||
|
||
validates_presence_of :name
|
||
validates_uniqueness_of :name, :scope => :type
|
||
|
||
belongs_to :user
|
||
|
||
has_many :taxable_taxonomies, :dependent => :destroy
|
||
has_many :users, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'User'
|
||
has_many :smart_proxies, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'SmartProxy'
|
||
has_many :compute_resources, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'ComputeResource'
|
||
has_many :media, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'Medium'
|
||
has_many :domains, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'Domain'
|
||
has_many :hostgroups, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'Hostgroup'
|
||
has_many :environments, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'Environment'
|
||
has_many :subnets, :through => :taxable_taxonomies, :source => :taxable, :source_type => 'Subnet'
|
||
|
||
scoped_search :on => :name, :complete_value => true
|
||
|
||
def to_param
|
||
"#{id.to_s.parameterize}"
|
||
end
|
||
|
||
def to_label
|
||
name =~ /[A-Z]/ ? name : name.capitalize
|
||
end
|
||
|
||
def self.locations_enabled
|
||
SETTINGS[:locations_enabled]
|
||
end
|
||
|
||
def self.organizations_enabled
|
||
SETTINGS[:organizations_enabled]
|
||
end
|
||
|
||
def self.no_taxonomy_scope
|
||
as_taxonomy nil, nil do
|
||
yield if block_given?
|
||
end
|
||
end
|
||
|
||
def self.as_taxonomy org, location
|
||
Organization.as_org org do
|
||
Location.as_location location do
|
||
yield if block_given?
|
||
end
|
||
end
|
||
end
|
||
|
||
end
|
app/models/user.rb | ||
---|---|---|
class User < ActiveRecord::Base
|
||
include Authorization
|
||
include Foreman::ThreadSession::UserModel
|
||
include Taxonomix
|
||
audited :except => [:last_login_on, :password, :password_hash, :password_salt, :password_confirmation]
|
||
self.auditing_enabled = !defined?(Rake)
|
||
|
||
... | ... | |
has_many :user_facts, :dependent => :destroy
|
||
has_many :facts, :through => :user_facts, :source => :fact_name
|
||
|
||
scope :except_admin, where(:admin => false)
|
||
|
||
accepts_nested_attributes_for :user_facts, :reject_if => lambda { |a| a[:criteria].blank? }, :allow_destroy => true
|
||
|
||
validates :mail, :format => { :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)*[a-z]{2,})$/i },
|
||
... | ... | |
scoped_search :on => :last_login_on, :complete_value => :true
|
||
scoped_search :in => :roles, :on => :name, :rename => :role, :complete_value => true
|
||
|
||
default_scope lambda {
|
||
with_taxonomy_scope do
|
||
order('firstname')
|
||
end
|
||
}
|
||
|
||
def to_label
|
||
"#{firstname} #{lastname}"
|
||
end
|
||
... | ... | |
compute_resources.any? or
|
||
domains.any? or
|
||
hostgroups.any? or
|
||
facts.any?
|
||
facts.any? or
|
||
locations.any? or
|
||
organizations.any?
|
||
end
|
||
|
||
private
|
app/views/common/_edit_habtm.erb | ||
---|---|---|
<% if associations.empty? -%>
|
||
<strong>None Found</strong>
|
||
<% else -%>
|
||
<%= link_to_function(icon_text("check", ""), "toggleCheckboxesBySelector(\"[id$='#{ActiveModel::Naming.singular(associations.first)}_ids_']\")",
|
||
:title => "Select all") %>
|
||
<% associations.sort{|a,b| a.to_s <=> b.to_s}.each do |association| -%>
|
||
<li>
|
||
<%= content_tag_for :label, association do %>
|
||
<%= check_box_tag(
|
||
"#{prefix || klass.class.table_name.singularize}[#{ActiveModel::Naming.singular(association)}_ids][]",
|
||
association.id, klass.send(association.class.table_name).map(&:id).include?(association.id))
|
||
"#{prefix || klass.class.model_name.downcase}[#{ActiveModel::Naming.singular(association)}_ids][]",
|
||
association.id, klass.send(ActiveModel::Naming.plural(association)).map(&:id).include?(association.id))
|
||
%>
|
||
<%= contract association %>
|
||
<%= hidden_field_tag "#{prefix || klass.class.table_name.singularize}[#{ActiveModel::Naming.singular(association)}_ids][]" %>
|
||
<%= hidden_field_tag "#{prefix || klass.class.model_name.downcase}[#{ActiveModel::Naming.singular(association)}_ids][]" %>
|
||
<% end -%>
|
||
</li>
|
||
<% end -%>
|
app/views/compute_resources/_form.html.erb | ||
---|---|---|
<%= javascript "compute_resource" %>
|
||
<%= form_for(@compute_resource) do |f| %>
|
||
<%= form_for @compute_resource do |f| %>
|
||
<%= base_errors_for @compute_resource %>
|
||
<%= text_f f, :name %>
|
||
<%= selectable_f f, :provider, ComputeResource::PROVIDERS, { :include_blank => "Choose a provider"},
|
||
{:disabled=> f.object.uuid.present?, :'data-url'=> provider_selected_compute_resources_path, :onchange => 'providerSelected(this);'} %>
|
||
<%= textarea_f f, :description, :rows => 3 %>
|
||
<div id='compute_connection'>
|
||
<%= render "compute_resources/form/#{@compute_resource.provider.downcase}", :f => f unless @compute_resource.provider.empty? %>
|
||
</div>
|
||
|
||
<% if show_taxonomy_tabs? %>
|
||
<ul class="nav nav-tabs" data-tabs="tabs">
|
||
<li class="active"><a href="#primary" data-toggle="tab">Compute Resource</a></li>
|
||
<% if show_location_tab? %>
|
||
<li><a href="#locations" data-toggle="tab">Locations</a></li>
|
||
<% end %>
|
||
<% if show_organization_tab? %>
|
||
<li><a href="#organizations" data-toggle="tab">Organizations</a></li>
|
||
<% end %>
|
||
</ul>
|
||
|
||
<div class="tab-content">
|
||
<div class="tab-pane active" id="primary">
|
||
<% end %>
|
||
<%= text_f f, :name %>
|
||
<%= selectable_f f, :provider, ComputeResource::PROVIDERS, { :include_blank => "Choose a provider"},
|
||
{:disabled=> f.object.uuid.present?, :'data-url'=> provider_selected_compute_resources_path, :onchange => 'providerSelected(this);'} %>
|
||
<%= textarea_f f, :description, :rows => 3 %>
|
||
<div id='compute_connection'>
|
||
<%= render "compute_resources/form/#{@compute_resource.provider.downcase}", :f => f unless @compute_resource.provider.empty? %>
|
||
</div>
|
||
<% if show_taxonomy_tabs? %>
|
||
</div>
|
||
<% if show_location_tab? %>
|
||
<div class="tab-pane" id="locations">
|
||
<%= multiple_checkboxes f, :locations, @compute_resource, Location %>
|
||
</div>
|
||
<% end %>
|
||
|
||
<% if show_organization_tab? %>
|
||
<div class="tab-pane" id="organizations">
|
||
<%= multiple_checkboxes f, :organizations, @compute_resource, Organization %>
|
||
</div>
|
||
<% end %>
|
||
</div>
|
||
<% end %>
|
||
|
||
<%= submit_or_cancel f %>
|
||
<% end %>
|
app/views/domains/_form.html.erb | ||
---|---|---|
<ul class="nav nav-tabs" data-tabs="tabs">
|
||
<li class="active"><a href="#primary" data-toggle="tab">Domain</a></li>
|
||
<li><a href="#params" data-toggle="tab">Parameters</a></li>
|
||
<% if show_location_tab? %>
|
||
<li><a href="#locations" data-toggle="tab">Locations</a></li>
|
||
<% end %>
|
||
<% if show_organization_tab? %>
|
||
<li><a href="#organizations" data-toggle="tab">Organizations</a></li>
|
||
<% end %>
|
||
</ul>
|
||
|
||
<div class="tab-content">
|
||
... | ... | |
<%= render "common_parameters/parameters", { :f => f, :type => :domain_parameters } %>
|
||
</div>
|
||
|
||
<% if show_location_tab? %>
|
||
<div class="tab-pane" id="locations">
|
||
<%= multiple_checkboxes f, :locations, @domain, Location %>
|
||
</div>
|
||
<% end %>
|
||
|
||
<% if show_organization_tab? %>
|
||
<div class="tab-pane" id="organizations">
|
||
<%= multiple_checkboxes f, :organizations, @domain, Organization %>
|
||
</div>
|
||
<% end %>
|
||
|
||
</div>
|
||
|
||
<%= submit_or_cancel f %>
|
app/views/environments/_form.html.erb | ||
---|---|---|
<%= form_for @environment do |f| %>
|
||
<%= base_errors_for @environment %>
|
||
<%= text_f f, :name %>
|
||
<% if show_taxonomy_tabs? %>
|
||
<ul class="nav nav-tabs" data-tabs="tabs">
|
||
<li class="active"><a href="#primary" data-toggle="tab">Primary</a></li>
|
||
<% if show_location_tab? %>
|
||
<li><a href="#locations" data-toggle="tab">Locations</a></li>
|
||
<% end %>
|
||
<% if show_organization_tab? %>
|
||
<li><a href="#organizations" data-toggle="tab">Organizations</a></li>
|
||
<% end %>
|
||
</ul>
|
||
|
||
<div class="tab-content">
|
||
|
||
<div class="tab-pane active" id="primary">
|
||
<%= text_f f, :name %>
|
||
</div>
|
||
|
||
<% if show_location_tab? %>
|
||
<div class="tab-pane" id="locations">
|
||
<%= multiple_checkboxes f, :locations, @environment, Location, { :prefix => "environment" } %>
|
||
</div>
|
||
<% end %>
|
||
|
||
<% if show_organization_tab? %>
|
||
<div class="tab-pane" id="organizations">
|
||
<%= multiple_checkboxes f, :organizations, @environment, Organization, { :prefix => "environment" } %>
|
||
</div>
|
||
<% end %>
|
||
</div>
|
||
|
||
<% else %>
|
||
<%= text_f f, :name %>
|
||
<% end %>
|
||
|
||
<%= submit_or_cancel f %>
|
||
<% end %>
|
app/views/home/_location_dropdown.rhtml | ||
---|---|---|
<li class="dropdown">
|
||
<% location_count = Location.my_locations.count %>
|
||
<%= location_dropdown location_count %>
|
||
<ul class="dropdown-menu">
|
||
<% if show_add_location_button? location_count%>
|
||
<div class="no-taxonomies">
|
||
<div class="alert">
|
||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||
There aren't any locations yet.
|
||
</div>
|
||
<button class="btn btn-primary" type="button"><%= link_to "New Location", :controller => "locations", :action => "new" %></button>
|
||
</div>
|
||
<% elsif location_count > 1 %>
|
||
<li><%= link_to('Any Location', clear_locations_path) %></li>
|
||
<% Location.my_locations.each do |location| %>
|
||
<li><%= link_to(location.name, select_location_path(location)) %></li>
|
||
<% end -%>
|
||
<% end %>
|
||
</ul>
|
||
</li>
|
app/views/home/_organization_dropdown.rhtml | ||
---|---|---|
<li class="dropdown">
|
||
<% orgs_count = Organization.my_organizations.count %>
|
||
<%= organization_dropdown orgs_count %>
|
||
<ul class="dropdown-menu">
|
||
<% if show_add_organization_button? orgs_count %>
|
||
<div class="no-taxonomies">
|
||
<div class="alert">
|
||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||
There aren't any organizations yet.
|
||
</div>
|
||
<button class="btn btn-primary" type="button"><%= link_to "New Organization", :controller => "organizations", :action => "new" %></button>
|
||
</div>
|
||
<% elsif orgs_count > 1 %>
|
||
<li><%= link_to('All', clear_organizations_path) %></li>
|
||
<% Organization.my_organizations.each do |organization| %>
|
||
<li><%= link_to(organization.name, select_organization_path(organization)) %></li>
|
||
<% end %>
|
||
<% end %>
|
||
</ul>
|
||
</li>
|
app/views/home/_topbar.rhtml | ||
---|---|---|
<ul class="nav" id="menu">
|
||
<% my_bookmarks = Bookmark.my_bookmarks %>
|
||
|
||
<%= menu 'dashboard', my_bookmarks %>
|
||
<%= menu 'hosts', my_bookmarks %>
|
||
<%= menu 'reports', my_bookmarks, hash_for_reports_path.merge(:search => 'eventful = true') %>
|
||
<%= menu 'facts' , my_bookmarks, hash_for_fact_values_path %>
|
||
<%= menu 'audits', my_bookmarks, hash_for_audits_path %>
|
||
<%= menu 'statistics', my_bookmarks %>
|
||
<%= menu 'trends', my_bookmarks, hash_for_trends_path %>
|
||
</ul>
|
||
</div>
|
||
<div class="nav-collapse nav2">
|
||
<ul class="nav pull-right" id="menu2">
|
||
<%= render "home/settings" -%>
|
||
<% if SETTINGS[:login]%>
|
||
<%= render 'home/user_dropdown' %>
|
||
<%= menu 'dashboard', my_bookmarks %>
|
||
<%= menu 'hosts', my_bookmarks %>
|
||
<%= menu 'reports', my_bookmarks, hash_for_reports_path.merge(:search => 'eventful = true') %>
|
||
<%= menu 'facts' , my_bookmarks, hash_for_fact_values_path %>
|
||
<%= menu 'audits', my_bookmarks, hash_for_audits_path %>
|
||
<%= menu 'statistics', my_bookmarks %>
|
||
<%= menu 'trends', my_bookmarks, hash_for_trends_path %>
|
||
</ul>
|
||
</div>
|
||
<div class="nav-collapse nav2">
|
||
<ul class="nav pull-right" id="menu2">
|
||
<% if SETTINGS[:login] %>
|
||
<% if SETTINGS[:locations_enabled] %>
|
||
<%= render 'home/location_dropdown' %>
|
||
<% end -%>
|
||
</ul>
|
||
<% if SETTINGS[:organizations_enabled] %>
|
||
<%= render 'home/organization_dropdown' %>
|
||
<% end %>
|
||
<% end %>
|
||
<%= render "home/settings" -%>
|
||
<% if SETTINGS[:login]%>
|
||
<%= render 'home/user_dropdown' %>
|
||
<% end -%>
|
||
</ul>
|
||
</div>
|
||
<% end -%>
|
||
<% end -%>
|
app/views/hostgroups/_form.html.erb | ||
---|---|---|
<li><a href="#os" data-toggle="tab">Operating System</a></li>
|
||
<% end -%>
|
||
<li><a href="#params" data-toggle="tab">Parameters</a></li>
|
||
<% if show_location_tab? %>
|
||
<li><a href="#locations" data-toggle="tab">Locations</a></li>
|
||
<% end %>
|
||
<% if show_organization_tab? %>
|
||
<li><a href="#organizations" data-toggle="tab">Organizations</a></li>
|
||
<% end %>
|
||
</ul>
|
||
|
||
<div class="tab-content">
|
||
... | ... | |
<div class="tab-pane" id="params">
|
||
<%= render "common_parameters/parameters", { :f => f, :type => :group_parameters } %>
|
||
</div>
|
||
|
||
<% if show_location_tab? %>
|
||
<div class="tab-pane" id="locations">
|
||
<%= multiple_checkboxes f, :locations, @hostgroup, Location %>
|
||
</div>
|
||
<% end %>
|
||
|
||
<% if show_organization_tab? %>
|
||
<div class="tab-pane" id="organizations">
|
||
<%= multiple_checkboxes f, :organizations, @hostgroup, Organization %>
|
||
</div>
|
||
<% end %>
|
||
</div>
|
||
|
||
<%= submit_or_cancel f %>
|
app/views/hosts/_form.html.erb | ||
---|---|---|
|
||
<div class="tab-pane active" id="primary">
|
||
<%= text_f f, :name, :class => "input-xlarge", :value => name_field(@host) %>
|
||
|
||
<% if show_organization_tab? %>
|
||
<%= select_f f, :organization_id, Organization.my_organizations, :id, :to_label,
|
||
{ :include_blank => true },
|
||
{ :onchange => 'organization_changed(this);', :label => "Organization", :'data-host-id' => @host.id,
|
||
:'data-url' => process_taxonomy_hosts_path, :selected => Organization.my_organizations,
|
||
:help_inline => image_tag('spinner.gif', :id => 'organization_indicator', :class => 'hide').html_safe } %>
|
||
<% end %>
|
||
|
||
<% if show_location_tab? %>
|
||
<%= select_f f, :location_id, Location.my_locations, :id, :to_label,
|
||
{ :include_blank => true},
|
||
{ :onchange => 'location_changed(this);', :label => "Location", :"data-host-id" => @host.id,
|
||
:'data-url' => process_taxonomy_hosts_path, :selected => Location.my_locations,
|
||
:help_inline => image_tag('spinner.gif', :id => 'location_indicator', :class => 'hide').html_safe } %>
|
||
<% end %>
|
||
|
||
<%= select_f f, :compute_resource_id, ComputeResource.my_compute_resources, :id, :to_label,
|
||
{ :include_blank => 'Bare Metal' },
|
||
{:label => "Deploy on", :disabled => !@host.new_record?, :'data-url' => compute_resource_selected_hosts_path ,
|
||
:onchange => 'computeResourceSelected(this);'} if SETTINGS[:unattended] && @host.new_record? || @host.compute_resource_id %>
|
||
|
||
<%= select_f f, :hostgroup_id, accessible_hostgroups, :id, :to_label,
|
||
{ :include_blank => true},
|
||
{ :onchange => 'hostgroup_changed(this);' , :'data-host-id' => @host.id,
|
||
... | ... | |
</div>
|
||
<%= textarea_f f, :comment, :help_block => "Additional information about this host", :class => "input-xxlarge", :rows => "3" %>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<%= f.hidden_field :overwrite? %>
|
||
<%= submit_or_cancel f, @host.overwrite? %>
|
||
<% end %>
|
Also available in: Unified diff
Add organization and location to foreman.
This feature allows foreman to provide multi location, multi tenant and
multi organizations capablities.
the idea is that resources within foreman (e.g. hosts, subnets, users,
environments etc) can belong to one or more locations and organization,
effectivily hidding resources from users.
Organization may contain multiple locations, and Locations can belong
to multiple Organization, this is an extermily flexiable design,
however, it is up to the user to allocate the resources across the
organizations and locations.
When creating new hosts, the resources that can be consumed are only
resources in which exists in both the currently used organization and location.
fixes #1578
fixes #1593