Skip to content

Commit

Permalink
fixes #16725 - add plugin extension point for smart proxies
Browse files Browse the repository at this point in the history
  • Loading branch information
timogoebel authored and domcleal committed Oct 7, 2016
1 parent a4d7a03 commit c676093
Show file tree
Hide file tree
Showing 44 changed files with 396 additions and 192 deletions.
4 changes: 3 additions & 1 deletion app/controllers/api/v2/domains_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ def show
param :domain, Hash, :required => true, :action_aware => true do
param :name, String, :required => true, :desc => N_("The full DNS domain name")
param :fullname, String, :required => false, :allow_nil => true, :desc => N_("Description of the domain")
param :dns_id, :number, :required => false, :allow_nil => true, :desc => N_("DNS proxy to use within this domain")
Domain.registered_smart_proxies.each do |name, options|
param :"#{name}_id", :number, :required => false, :allow_nil => true, :desc => options[:api_description]
end
param :domain_parameters_attributes, Array, :required => false, :desc => N_("Array of parameters (name, value)")
param_group :taxonomies, ::Api::V2::BaseController
end
Expand Down
5 changes: 3 additions & 2 deletions app/controllers/api/v2/hostgroups_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ def show
param :pxe_loader, Operatingsystem.all_loaders, :desc => N_("DHCP filename option (Grub2/PXELinux by default)")
param :medium_id, :number, :desc => N_('Media ID')
param :ptable_id, :number, :desc => N_('Partition table ID')
param :puppet_ca_proxy_id, :number, :desc => N_('Puppet CA proxy ID')
param :subnet_id, :number, :desc => N_('Subnet ID')
param :domain_id, :number, :desc => N_('Domain ID')
param :realm_id, :number, :desc => N_('Realm ID')
param :puppet_proxy_id, :number, :desc => N_('Puppet proxy ID')
Hostgroup.registered_smart_proxies.each do |name, options|
param :"#{name}_id", :number, :desc => options[:api_description]
end
param :root_pass, String, :desc => N_('Root password on provisioned hosts')
param_group :taxonomies, ::Api::V2::BaseController
end
Expand Down
5 changes: 3 additions & 2 deletions app/controllers/api/v2/hosts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ def show
param :architecture_id, :number, :desc => N_("required if host is managed and value is not inherited from host group")
param :domain_id, :number, :desc => N_("required if host is managed and value is not inherited from host group")
param :realm_id, :number
param :puppet_proxy_id, :number
Host.registered_smart_proxies.each do |name, options|
param :"#{name}_id", :number, :desc => options[:api_description]
end
param :puppetclass_ids, Array
param :operatingsystem_id, String, :desc => N_("required if host is managed and value is not inherited from host group")
param :medium_id, String, :desc => N_("required if not imaged based provisioning and host is managed and value is not inherited from host group")
Expand All @@ -73,7 +75,6 @@ def show
param :hostgroup_id, :number
param :owner_id, :number
param :owner_type, Host::Base::OWNER_TYPES, :desc => N_("Host's owner type")
param :puppet_ca_proxy_id, :number
param :image_id, :number
param :host_parameters_attributes, Array, :desc => N_("Host's parameters (array or indexed hash)") do
param :name, String, :desc => N_("Name of the parameter"), :required => true
Expand Down
4 changes: 3 additions & 1 deletion app/controllers/api/v2/realms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ def show
def_param_group :realm do
param :realm, Hash, :required => true, :action_aware => true do
param :name, String, :required => true, :desc => N_("The realm name, e.g. EXAMPLE.COM")
param :realm_proxy_id, :number, :required => true, :allow_nil => true, :desc => N_("Proxy to use for this realm")
Realm.registered_smart_proxies.each do |name, options|
param :"#{name}_id", :number, :required => true, :allow_nil => true, :desc => options[:api_description]
end
param :realm_type, String, :required => true, :desc => N_("Realm type, e.g. FreeIPA or Active Directory")
param_group :taxonomies, ::Api::V2::BaseController
end
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/api/v2/subnets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ def show
param :to, String, :desc => N_("Ending IP Address for IP auto suggestion")
param :vlanid, String, :desc => N_("VLAN ID for this subnet")
param :domain_ids, Array, :desc => N_("Domains in which this subnet is part")
param :dhcp_id, :number, :desc => N_("DHCP Proxy to use within this subnet")
param :tftp_id, :number, :desc => N_("TFTP Proxy to use within this subnet")
param :dns_id, :number, :desc => N_("DNS Proxy to use within this subnet")
Subnet.registered_smart_proxies.each do |name, options|
param :"#{name}_id", :number, :desc => options[:api_description]
end
param :boot_mode, String, :desc => N_('Default boot mode for interfaces assigned to this subnet, valid values are "Static", "DHCP"')
param :subnet_parameters_attributes, Array, :required => false, :desc => N_("Array of parameters (name, value)")
param_group :taxonomies, ::Api::V2::BaseController
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ module Foreman::Controller::Parameters::Domain
extend ActiveSupport::Concern
include Foreman::Controller::Parameters::Parameter
include Foreman::Controller::Parameters::Taxonomix
include Foreman::Controller::Parameters::SmartProxiesCommon

class_methods do
def domain_params_filter
Foreman::ParameterFilter.new(::Domain).tap do |filter|
filter.permit :dns_id, :dns_name,
:fullname,
filter.permit :fullname,
:name,
:domain_parameters_attributes => [parameter_params_filter(DomainParameter)]
add_taxonomix_params_filter(filter)
add_smart_proxies_common_params_filter(filter)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ def add_host_base_params_filter(filter)
:operatingsystem, :operatingsystem_id, :operatingsystem_name,
:organization, :organization_id, :organization_name,
:ptable, :ptable_id, :ptable_name,
:puppet_ca_proxy, :puppet_ca_proxy_id, :puppet_ca_proxy_name,
:puppet_proxy, :puppet_proxy_id, :puppet_proxy_name,
:progress_report, :progress_report_id, :progress_report_name,
:realm, :realm_id, :realm_name,
:subnet, :subnet_id, :subnet_name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Foreman::Controller::Parameters::HostCommon
extend ActiveSupport::Concern
include Foreman::Controller::Parameters::LookupValue
include Foreman::Controller::Parameters::Parameter
include Foreman::Controller::Parameters::SmartProxiesCommon

class_methods do
def add_host_common_params_filter(filter)
Expand All @@ -12,6 +13,7 @@ def add_host_common_params_filter(filter)
:lookup_value_matcher,
:use_image,
:lookup_values_attributes => [lookup_value_params_filter]
add_smart_proxies_common_params_filter(filter)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ def hostgroup_params_filter
:operatingsystem_id, :operatingsystem_name,
:os, :os_id, :os_name,
:ptable_id, :ptable_name,
:puppet_ca_proxy_id, :puppet_ca_proxy_name,
:puppet_proxy_id, :puppet_proxy_name,
:config_group_names => [], :config_group_ids => [],
:puppetclass_ids => [], :puppetclass_names => [],
:group_parameters_attributes => [parameter_params_filter(::GroupParameter)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Foreman::Controller::Parameters::Realm
extend ActiveSupport::Concern
include Foreman::Controller::Parameters::Taxonomix
include Foreman::Controller::Parameters::SmartProxiesCommon

class_methods do
def realm_params_filter
Expand All @@ -9,6 +10,7 @@ def realm_params_filter
:realm_type,
:realm_proxy, :realm_proxy_id, :realm_proxy_name
add_taxonomix_params_filter(filter)
add_smart_proxies_common_params_filter(filter)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Foreman::Controller::Parameters::SmartProxiesCommon
extend ActiveSupport::Concern

class_methods do
def add_smart_proxies_common_params_filter(filter)
filter.resource_class.registered_smart_proxies.keys.each do |proxy|
filter.permit proxy, :"#{proxy}_id", :"#{proxy}_name"
end
filter
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ module Foreman::Controller::Parameters::Subnet
extend ActiveSupport::Concern
include Foreman::Controller::Parameters::Parameter
include Foreman::Controller::Parameters::Taxonomix
include Foreman::Controller::Parameters::SmartProxiesCommon

class_methods do
def subnet_params_filter
Foreman::ParameterFilter.new(::Subnet).tap do |filter|
filter.permit :boot_mode,
:cidr,
:dhcp, :dhcp_id,
:dns, :dns_id,
:dns_primary,
:dns_secondary,
:from,
Expand All @@ -19,13 +18,13 @@ def subnet_params_filter
:name,
:network,
:network_type,
:tftp, :tftp_id,
:to,
:type,
:vlanid,
:domain_ids => [], :domain_names => [],
:subnet_parameters_attributes => [parameter_params_filter(::SubnetParameter)]
add_taxonomix_params_filter(filter)
add_smart_proxies_common_params_filter(filter)
end
end
end
Expand Down
39 changes: 39 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -440,4 +440,43 @@ def webpack_dev_server
return unless Rails.configuration.webpack.dev_server.enabled
javascript_include_tag "#{@dev_server}/webpack-dev-server.js"
end

def accessible_resource_records(resource, order = :name)
klass = resource.to_s.classify.constantize
klass = klass.with_taxonomy_scope_override(@location, @organization) if klass.include? Taxonomix
klass.authorized.reorder(order)
end

def accessible_resource(obj, resource, order = :name)
list = accessible_resource_records(resource, order).to_a
# we need to allow the current value even if it was filtered
current = obj.public_send(resource) if obj.respond_to?(resource)
list |= [current] if current.present?
list
end

def accessible_related_resource(obj, relation, opts = {})
return [] if obj.blank?
order = opts.fetch(:order, :name)
where = opts.fetch(:where, nil)
related = obj.public_send(relation)
related = related.with_taxonomy_scope_override(@location, @organization) if obj.class.reflect_on_association(relation).klass.include?(Taxonomix)
related.authorized.where(where).reorder(order)
end

def explicit_value?(field)
return true if params[:action] == 'clone'
return false unless params[:host]
!!params[:host][field]
end

def user_set?(field)
# if the host has no hostgroup
return true unless @host && @host.hostgroup
# when editing a host, the values are specified explicitly
return true if params[:action] == 'edit'
return true if params[:action] == 'clone'
# check if the user set the field explicitly despite setting a hostgroup.
params[:host] && params[:host][:hostgroup_id] && params[:host][field]
end
end
74 changes: 0 additions & 74 deletions app/helpers/hosts_and_hostgroups_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,6 @@ def model_name(host)
name
end

def accessible_resource_records(resource, order = :name)
klass = resource.to_s.classify.constantize
klass = klass.with_taxonomy_scope_override(@location, @organization) if klass.include? Taxonomix
klass.authorized.reorder(order)
end

def accessible_resource(obj, resource, order = :name)
list = accessible_resource_records(resource, order).to_a
# we need to allow the current value even if it was filtered
current = obj.public_send(resource) if obj.respond_to?(resource)
list |= [current] if current.present?
list
end

def accessible_related_resource(obj, relation, opts = {})
return [] if obj.blank?
order = opts.fetch(:order, :name)
where = opts.fetch(:where, nil)
related = obj.public_send(relation)
related = related.with_taxonomy_scope_override(@location, @organization) if obj.class.reflect_on_association(relation).klass.include?(Taxonomix)
related.authorized.where(where).reorder(order)
end

def parent_classes(obj)
return obj.hostgroup.classes if obj.is_a?(Host::Base) && obj.hostgroup
return obj.is_root? ? [] : obj.parent.classes if obj.is_a?(Hostgroup)
Expand Down Expand Up @@ -66,43 +43,8 @@ def os_ptable
accessible_related_resource(@operatingsystem, :ptables)
end

def puppet_master_fields(f, can_override = false, override = false)
"#{puppet_ca(f, can_override, override)} #{puppet_master(f, can_override, override)}".html_safe
end

INHERIT_TEXT = N_("inherit")

def puppet_ca(f, can_override, override)
# Don't show this if we have no CA proxies, otherwise always include blank
# so the user can choose not to sign the puppet cert on this host
proxies = accessible_puppet_ca_proxies(f.object)
return unless proxies.present?
select_f f, :puppet_ca_proxy_id, proxies, :id, :name,
{ :include_blank => blank_or_inherit_f(f, :puppet_ca_proxy),
:disable_button => can_override ? _(INHERIT_TEXT) : nil,
:disable_button_enabled => override && !explicit_value?(:puppet_ca_proxy_id),
:user_set => user_set?(:puppet_ca_proxy_id)
},
{ :label => _("Puppet CA"),
:help_inline => _("Use this puppet server as a CA server") }
end

def puppet_master(f, can_override, override)
# Don't show this if we have no Puppet proxies, otherwise always include blank
# so the user can choose not to use puppet on this host
proxies = accessible_puppet_proxies(f.object)
return unless proxies.present?
select_f f, :puppet_proxy_id, proxies, :id, :name,
{ :include_blank => blank_or_inherit_f(f, :puppet_proxy),
:disable_button => can_override ? _(INHERIT_TEXT) : nil,
:disable_button_enabled => override && !explicit_value?(:puppet_proxy_id),
:user_set => user_set?(:puppet_proxy_id)

},
{ :label => _("Puppet Master"),
:help_inline => _("Use this puppet server as an initial Puppet Server or to execute puppet runs") }
end

def realm_field(f, can_override = false, override = false)
# Don't show this if we have no Realms, otherwise always include blank
# so the user can choose not to use a Realm on this host
Expand Down Expand Up @@ -185,22 +127,6 @@ def interesting_puppetclasses(obj)
classes.where(:id => klasses)
end

def explicit_value?(field)
return true if params[:action] == 'clone'
return false unless params[:host]
!!params[:host][field]
end

def user_set?(field)
# if the host has no hostgroup
return true unless @host && @host.hostgroup
# when editing a host, the values are specified explicitly
return true if params[:action] == 'edit'
return true if params[:action] == 'clone'
# check if the user set the field explicitly despite setting a hostgroup.
params[:host] && params[:host][:hostgroup_id] && params[:host][field]
end

def puppetclasses_tab(puppetclasses_receiver)
return unless accessible_puppet_proxies(puppetclasses_receiver).present?
content_tag(:div, :class => 'tab-pane', :id => 'puppet_klasses') do
Expand Down
42 changes: 42 additions & 0 deletions app/helpers/shared_smart_proxies_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module SharedSmartProxiesHelper
def smart_proxy_fields(f, options = {})
object = options.fetch(:object, f.object)

safe_join(object.registered_smart_proxies.map do |proxy_name, proxy_options|
smart_proxy_select_f(f, proxy_name, options.merge(proxy_options))
end)
end

INHERIT_TEXT = N_("inherit")

def smart_proxy_select_f(f, resource, options)
required = options.fetch(:required, false)
hidden = options[:if].present? && !options[:if].call(f.object)
can_override = options.fetch(:can_override, false)
override = options.fetch(:override, false)
blank = options.fetch(:blank, blank_or_inherit_f(f, resource))

proxies = accessible_smart_proxies(f.object, resource, options[:feature])
return if !required && !proxies.present?

select_options = {
:disable_button => can_override ? _(INHERIT_TEXT) : nil,
:disable_button_enabled => override && !explicit_value?(:"#{resource}_id"),
:user_set => user_set?(:"#{resource}_id")
}
select_options[:include_blank] = blank unless required

select_f f, :"#{resource}_id", proxies, :id, :name,
select_options,
:label => _(options[:label]),
:help_inline => _(options[:description]),
:wrapper_class => "form-group #{'hide' if hidden}"
end

def accessible_smart_proxies(obj, resource, feature)
list = accessible_resource_records(:smart_proxy).with_features(feature).to_a
current = obj.public_send(resource) if obj.respond_to?(resource)
list |= [current] if current.present?
list
end
end
Loading

0 comments on commit c676093

Please sign in to comment.