Revision 7cdaddab
Added by Shlomi Zadok over 8 years ago
app/assets/javascripts/about.js | ||
---|---|---|
$(function() {
|
||
$(".proxy-version").each(function(index, item) {
|
||
var item = $(item);
|
||
var url = item.data('url');
|
||
$.ajax({
|
||
type: 'get',
|
||
url: url,
|
||
success: function(response) {
|
||
item.attr('title',response.message);
|
||
if(response.success == true) {
|
||
item.addClass('label label-success')
|
||
item.text(__(response.message));
|
||
} else {
|
||
item.addClass('label label-danger')
|
||
item.text(__('Error'));
|
||
}
|
||
item.tooltip({html: true});
|
||
}
|
||
})
|
||
});
|
||
$(".proxy-status, .compute-status").each(function(index, item) {
|
||
"use strict";
|
||
$(".compute-status").each(function(index, item) {
|
||
var item = $(item);
|
||
var url = item.data('url');
|
||
$.ajax({
|
||
... | ... | |
success: function(response) {
|
||
item.text(__(response.status));
|
||
item.attr('title',response.message);
|
||
if(response.status == "OK"){
|
||
if(response.status === "OK"){
|
||
item.addClass('label label-success')
|
||
}else{
|
||
item.addClass('label label-danger')
|
||
}
|
||
item.tooltip({html: true});
|
||
}
|
||
})
|
||
});
|
||
});
|
||
});
|
app/assets/javascripts/application.js | ||
---|---|---|
//= require two-pane
|
||
//= require vendor
|
||
//= require about
|
||
//= require proxy_status
|
||
//= require jquery.extentions
|
||
//= require jquery.multi-select
|
||
//= require settings
|
||
... | ... | |
|
||
$(item).blur();
|
||
}
|
||
|
||
function icon(name) {
|
||
"use strict";
|
||
return '<span class="glyphicon glyphicon-' + name + '" />';
|
||
}
|
app/assets/javascripts/proxy_status.js | ||
---|---|---|
function setItemStatus(item, response) {
|
||
if(response.success) {
|
||
item.attr('title', __('Active'));
|
||
item.addClass('text-success');
|
||
item.html(icon('ok-sign'));
|
||
} else {
|
||
item.attr('title', response.message);
|
||
item.addClass('text-danger');
|
||
item.html(icon('exclamation-sign'));
|
||
}
|
||
item.tooltip({html: true});
|
||
}
|
||
|
||
function setProxyVersion(item, response) {
|
||
var text = response.message.version ? response.message.version : response.message;
|
||
generateItem(item, response.success, text);
|
||
}
|
||
|
||
function setPluginVersion(item, response) {
|
||
var pluginName = item.data('plugin');
|
||
var pluginVersion = response.message.modules ? response.message.modules[pluginName] : response.message;
|
||
generateItem(item, response.success, pluginVersion);
|
||
}
|
||
|
||
function generateItem(item, status, text) {
|
||
"use strict";
|
||
if (status === true) {
|
||
item.text(text);
|
||
} else {
|
||
item.attr('title', text);
|
||
item.addClass('text-danger');
|
||
item.html(icon('exclamation-sign'));
|
||
}
|
||
item.tooltip({html: true});
|
||
}
|
||
|
||
$(function() {
|
||
$('.proxy-show').each(function(index, item) {
|
||
var proxy = new ProxyStatus($(item));
|
||
proxy.getVersions();
|
||
});
|
||
|
||
$('.proxy-tftp').each(function(index, item) {
|
||
var item = $(item);
|
||
var url = item.data('url');
|
||
$.ajax({
|
||
type: 'get',
|
||
url: url,
|
||
success: function (response) {
|
||
generateItem(item, response.success, response.message);
|
||
},
|
||
error: function (response) {
|
||
generateItem(item, false, response.message);
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
function ProxyStatus(item) {
|
||
this.url = item.data('url');
|
||
this.item = item;
|
||
var self = this;
|
||
|
||
this.getVersions = function() {
|
||
$.ajax({
|
||
type: 'get',
|
||
url: this.url,
|
||
success: function (response) {
|
||
populateData(response, self.item);
|
||
}.bind(this),
|
||
error: function (response) {
|
||
populateData(response, self.item);
|
||
}.bind(this)
|
||
});
|
||
};
|
||
}
|
||
|
||
function populateData(response, item) {
|
||
$(item.children().find(".proxy-version")).each(function(index, i) {
|
||
var item = $(i);
|
||
setProxyVersion(item, response);
|
||
});
|
||
|
||
$(".plugin-version").each(function(index, i) {
|
||
var item = $(i);
|
||
setPluginVersion(item, response);
|
||
});
|
||
|
||
$(item.children().find(".proxy-show-status")).each(function(index, i) {
|
||
var item = $(i);
|
||
setItemStatus(item, response);
|
||
});
|
||
}
|
app/assets/javascripts/two-pane.js | ||
---|---|---|
}
|
||
});
|
||
|
||
$(document).on('click', "a[href$='edit'].edit_two_pane", function(e) {
|
||
if ($('.table-two-pane').length) {
|
||
e.preventDefault();
|
||
two_pane_open(this);
|
||
}
|
||
});
|
||
|
||
$(document).on('submit','.two-pane-right', function() {
|
||
two_pane_submit();
|
||
return false;
|
app/assets/stylesheets/application.scss | ||
---|---|---|
.spinner-placeholder {
|
||
width: 16px;
|
||
height: 16px;
|
||
background: image-url('spinner.gif');
|
||
background: image-url('spinner.gif') no-repeat top left;
|
||
text-indent: 20px;
|
||
white-space: nowrap;
|
||
margin: 20% 30% 0 40%;
|
||
display: block;
|
||
}
|
||
|
||
.exit-fullscreen {
|
||
... | ... | |
.ms-container {
|
||
background: transparent image-url('switch.png') no-repeat 270px 80px;
|
||
}
|
||
|
||
.big {
|
||
font-size: 3rem;
|
||
color: #797979;
|
||
}
|
app/assets/stylesheets/bootstrap_and_overrides.scss | ||
---|---|---|
.btn-strike {
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
#proxy-tab {
|
||
margin-bottom: 0px;
|
||
}
|
||
.proxy-content.tab-content {
|
||
padding: 19px;
|
||
min-height: 0px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 2px;
|
||
border-top: 0px;
|
||
float: left;
|
||
width: 100%;
|
||
}
|
app/assets/stylesheets/two_pane.scss | ||
---|---|---|
}
|
||
|
||
.two-pane-right{
|
||
.spinner-placeholder {
|
||
margin: 20% 30% 0 40%;
|
||
}
|
||
.well{
|
||
padding: 19px;
|
||
min-height: 460px;
|
app/controllers/smart_proxies_controller.rb | ||
---|---|---|
class SmartProxiesController < ApplicationController
|
||
include Foreman::Controller::AutoCompleteSearch
|
||
before_filter :find_resource, :only => [:edit, :update, :refresh, :ping, :version, :destroy]
|
||
|
||
before_filter :find_resource, :only => [:show, :edit, :update, :refresh, :ping, :tftp_server, :destroy]
|
||
|
||
def index
|
||
@smart_proxies = resource_base.includes(:features).search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
||
end
|
||
|
||
def show
|
||
end
|
||
|
||
def new
|
||
@smart_proxy = SmartProxy.new
|
||
end
|
||
... | ... | |
@proxy = @smart_proxy
|
||
end
|
||
|
||
def ping
|
||
@proxy = @smart_proxy
|
||
respond_to do |format|
|
||
format.json {render :json => errors_hash(@smart_proxy.refresh)}
|
||
end
|
||
end
|
||
|
||
def refresh
|
||
old_features = @smart_proxy.features
|
||
old_features = @smart_proxy.features.to_a
|
||
if @smart_proxy.refresh.blank? && @smart_proxy.save
|
||
msg = @smart_proxy.features == old_features ? _("No changes found when refreshing features from %s.") : _("Successfully refreshed features from %s.")
|
||
msg = @smart_proxy.features.to_a == old_features ? _("No changes found when refreshing features from %s.") : _("Successfully refreshed features from %s.")
|
||
process_success :object => @smart_proxy, :success_msg => msg % @smart_proxy.name
|
||
else
|
||
process_error :object => @smart_proxy
|
||
end
|
||
end
|
||
|
||
def version
|
||
begin
|
||
version = @smart_proxy.version
|
||
rescue Foreman::Exception => exception
|
||
render :json => {:success => false, :message => exception.message} and return
|
||
end
|
||
render :json => {:success => true, :message => version[:message]}
|
||
def ping
|
||
requested_data(:version)
|
||
end
|
||
|
||
def tftp_server
|
||
requested_data(:tftp_server)
|
||
end
|
||
|
||
def update
|
||
... | ... | |
|
||
private
|
||
|
||
def requested_data(data_name)
|
||
data = @smart_proxy.public_send(data_name)
|
||
render :json => {:success => true, :message => data}
|
||
rescue Foreman::Exception => exception
|
||
render :json => {:success => false, :message => exception.message} and return
|
||
end
|
||
|
||
def action_permission
|
||
case params[:action]
|
||
when 'refresh'
|
||
:edit
|
||
when 'ping', 'version'
|
||
when 'ping', 'tftp_server'
|
||
:view
|
||
else
|
||
super
|
app/helpers/application_helper.rb | ||
---|---|---|
url, :rel => 'external', :class => 'btn btn-info', :target => '_blank')
|
||
end
|
||
|
||
def generate_links_for(sub_model)
|
||
return _("None found") if sub_model.empty?
|
||
sub_model.map {|model| link_to(model.to_label, { :controller => model.class.model_name.plural.downcase, :action => :index, :search => "name = #{model.name}" })}.to_sentence
|
||
end
|
||
|
||
private
|
||
|
||
def edit_inline(object, property, options = {})
|
app/helpers/layout_helper.rb | ||
---|---|---|
end
|
||
end
|
||
|
||
def spinner
|
||
'<span class="spinner-placeholder" />'.html_safe
|
||
end
|
||
|
||
private
|
||
|
||
def table_css_classes(classes = '')
|
app/helpers/smart_proxies_helper.rb | ||
---|---|---|
module SmartProxiesHelper
|
||
def proxy_actions(proxy, authorizer)
|
||
[ display_link_if_authorized(_("Edit"), hash_for_edit_smart_proxy_path(:id => proxy), :class => 'edit_two_pane') ] +
|
||
[if proxy.has_feature?('Puppet CA')
|
||
[display_link_if_authorized(_("Certificates"), hash_for_smart_proxy_puppetca_index_path(:smart_proxy_id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'view_smart_proxies_puppetca', :authorizer => authorizer)),
|
||
merge(:auth_object => proxy, :permission => 'view_smart_proxies_puppetca', :authorizer => authorizer)),
|
||
display_link_if_authorized(_("Autosign"), hash_for_smart_proxy_autosign_index_path(:smart_proxy_id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'view_smart_proxies_autosign', :authorizer => authorizer))]
|
||
end,
|
||
merge(:auth_object => proxy, :permission => 'view_smart_proxies_autosign', :authorizer => authorizer))]
|
||
end] +
|
||
[ display_delete_if_authorized(hash_for_smart_proxy_path(:id => proxy).merge(:auth_object => proxy, :authorizer => authorizer),
|
||
:data => {:confirm => _("Delete %s?") % proxy.name}, :class => 'delete') ]
|
||
end
|
||
|
||
def smart_proxy_title_actions(proxy, authorizer)
|
||
actions = [display_link_if_authorized(_("Refresh features"), hash_for_refresh_smart_proxy_path(:id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'edit_smart_proxies', :authorizer => authorizer), :method => :put)]
|
||
if proxy.has_feature?('Puppet CA')
|
||
actions << [display_link_if_authorized(_("Certificates"), hash_for_smart_proxy_puppetca_index_path(:smart_proxy_id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'view_smart_proxies_puppetca', :authorizer => authorizer))]
|
||
actions << [display_link_if_authorized(_("Autosign"), hash_for_smart_proxy_autosign_index_path(:smart_proxy_id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'view_smart_proxies_autosign', :authorizer => authorizer))]
|
||
end
|
||
if SETTINGS[:unattended] and proxy.has_feature?('DHCP')
|
||
actions << display_link_if_authorized(_("Import subnets"), hash_for_import_subnets_path(:smart_proxy_id => proxy))
|
||
end
|
||
|
||
if SETTINGS[:unattended] and proxy.has_feature?('DHCP')
|
||
display_link_if_authorized(_("Import subnets"), hash_for_import_subnets_path(:smart_proxy_id => proxy))
|
||
end,
|
||
title_actions(
|
||
button_group(
|
||
link_to(_("Back"), smart_proxies_path)
|
||
),
|
||
select_action_button(_("Select Action"), {}, actions),
|
||
button_group(
|
||
display_link_if_authorized(_("Edit"), hash_for_edit_smart_proxy_path(:id => proxy))
|
||
),
|
||
button_group(
|
||
display_delete_if_authorized(hash_for_smart_proxy_path(:id => proxy).merge(:auth_object => proxy, :authorizer => authorizer),
|
||
:data => {:confirm => _("Delete %s?") % proxy.name}, :class => 'btn-danger')
|
||
)
|
||
)
|
||
end
|
||
|
||
display_link_if_authorized(_("Refresh features"), hash_for_refresh_smart_proxy_path(:id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'edit_smart_proxies', :authorizer => authorizer), :method => :put),
|
||
def refresh_proxy_icon(proxy, authorizer)
|
||
display_link_if_authorized(icon_text("refresh"), hash_for_refresh_smart_proxy_path(:id => proxy).
|
||
merge(:auth_object => proxy, :permission => 'edit_smart_proxies', :authorizer => authorizer), :method => :put)
|
||
end
|
||
|
||
display_delete_if_authorized(hash_for_smart_proxy_path(:id => proxy).merge(:auth_object => proxy, :authorizer => authorizer), :data => { :confirm => _("Delete %s?") % proxy.name })]
|
||
def proxy_features_besides_puppet(proxy)
|
||
proxy_features_lowercase = proxy.features.pluck("LOWER(REPLACE(name, ' ', '_'))").uniq
|
||
puppet_features_lowercase = %w(puppet puppet_ca)
|
||
proxy_features_lowercase - puppet_features_lowercase
|
||
end
|
||
end
|
app/models/smart_proxy.rb | ||
---|---|---|
scoped_search :on => :url, :complete_value => :true
|
||
scoped_search :in => :features, :on => :name, :rename => :feature, :complete_value => :true
|
||
|
||
delegate :version, :tftp_server, :to => :proxy_status
|
||
|
||
# with proc support, default_scope can no longer be chained
|
||
# include all default scoping here
|
||
default_scope lambda {
|
||
... | ... | |
|
||
scope :with_features, ->(*feature_names) { where(:features => { :name => feature_names }).joins(:features) if feature_names.any? }
|
||
|
||
HTTP_ERRORS = [Errno::EINVAL, Errno::ECONNRESET, EOFError, Timeout::Error,
|
||
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError]
|
||
|
||
def hostname
|
||
URI(url).host
|
||
end
|
||
... | ... | |
end
|
||
|
||
def refresh
|
||
proxy_status.revoke_cache!
|
||
associate_features
|
||
errors
|
||
end
|
||
... | ... | |
self.features.any? { |proxy_feature| proxy_feature.name == feature }
|
||
end
|
||
|
||
def version
|
||
result = {}
|
||
begin
|
||
Timeout::timeout(20) do
|
||
version = ProxyAPI::Version.new(:url => url).version
|
||
result[:success] = true
|
||
result[:message] = version
|
||
end
|
||
rescue *HTTP_ERRORS => exception
|
||
raise ::Foreman::WrappedException.new exception, N_("Unable to connect to smart proxy")
|
||
end
|
||
result
|
||
end
|
||
|
||
private
|
||
|
||
def proxy_status
|
||
@proxy_status ||= ProxyStatus.new(self)
|
||
end
|
||
|
||
def sanitize_url
|
||
self.url.chomp!('/') unless url.empty?
|
||
end
|
app/services/foreman/access_permissions.rb | ||
---|---|---|
end
|
||
|
||
permission_set.security_block :smart_proxies do |map|
|
||
map.permission :view_smart_proxies, {:smart_proxies => [:index, :ping, :auto_complete_search, :version],
|
||
map.permission :view_smart_proxies, {:smart_proxies => [:index, :ping, :auto_complete_search, :version,
|
||
:show, :plugin_version, :tftp_server],
|
||
:"api/v1/smart_proxies" => [:index, :show],
|
||
:"api/v2/smart_proxies" => [:index, :show, :version]
|
||
}
|
app/services/proxy_status.rb | ||
---|---|---|
class ProxyStatus
|
||
CONNECTION_ERRORS = [Errno::EINVAL, Errno::ECONNRESET, EOFError, Timeout::Error, Errno::ENOENT,
|
||
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError]
|
||
|
||
def initialize(proxy, opts = {})
|
||
@proxy = proxy
|
||
@cache_duration = opts[:cache_duration] || 3.minutes
|
||
@api ||= ProxyAPI::Version.new(:url => proxy.url)
|
||
end
|
||
|
||
def api_versions
|
||
Rails.cache.fetch(versions_cache_key, :expires_in => cache_duration) do
|
||
fetch_proxy_data do
|
||
api.proxy_versions
|
||
end
|
||
end
|
||
end
|
||
|
||
# TODO: extract to another status implementation
|
||
def tftp_server
|
||
raise ::Foreman::Exception.new(N_('No TFTP feature for %s') % proxy.to_label) unless proxy.has_feature?('TFTP')
|
||
Rails.cache.fetch("proxy_#{proxy.id}/tftp_server", :expires_in => cache_duration) do
|
||
fetch_proxy_data do
|
||
ProxyAPI::TFTP.new(:url => proxy.url).bootServer
|
||
end
|
||
end
|
||
end
|
||
|
||
def revoke_cache!
|
||
# As memcached does not support delete_matched, we need to delete each
|
||
Rails.cache.delete(versions_cache_key)
|
||
Rails.cache.delete("proxy_#{proxy.id}/tftp_server")
|
||
end
|
||
|
||
def versions_cache_key
|
||
"proxy_#{proxy.id}/versions"
|
||
end
|
||
|
||
private
|
||
|
||
attr_reader :proxy, :cache_duration, :api
|
||
alias_method :version, :api_versions
|
||
|
||
def fetch_proxy_data
|
||
begin
|
||
yield
|
||
rescue *CONNECTION_ERRORS => exception
|
||
raise ::Foreman::WrappedException.new exception, N_("Unable to connect to smart proxy")
|
||
end
|
||
end
|
||
end
|
app/views/about/index.html.erb | ||
---|---|---|
</thead>
|
||
<tbody>
|
||
<% @smart_proxies.each do |proxy| %>
|
||
<tr>
|
||
<td><%= link_to_if_authorized proxy.name, hash_for_edit_smart_proxy_path(proxy) %></td>
|
||
<tr class="proxy-show" data-url="<%= ping_smart_proxy_path(proxy) %>">
|
||
<td><%= link_to_if_authorized proxy.name, hash_for_smart_proxy_path(proxy) %></td>
|
||
<td><%=h proxy.features.to_sentence %></td>
|
||
<td><div class="proxy-status" data-url=<%= ping_smart_proxy_path(proxy) %>><%= _("Connecting..") %></div></td>
|
||
<td><div class="proxy-version" data-url=<%= version_smart_proxy_path(proxy) %>><%= _("Connecting..") %></div></td>
|
||
<td><div class="proxy-show-status"><%= spinner %></div></td>
|
||
<td><div class="proxy-version"><%= spinner %></div></td>
|
||
</tr>
|
||
<% end %>
|
||
</tbody>
|
||
... | ... | |
<tr>
|
||
<td><%= link_to compute.name, compute %></td>
|
||
<td><%= compute.provider_friendly_name %></td>
|
||
<td><div class="compute-status" data-url=<%= ping_compute_resource_path(compute) %>><%= _("Connecting..") %></div></td>
|
||
<td><div class="compute-status" data-url=<%= ping_compute_resource_path(compute) %>><%= spinner %></div></td>
|
||
</tr>
|
||
<% end %>
|
||
</tbody>
|
app/views/smart_proxies/index.html.erb | ||
---|---|---|
<thead>
|
||
<tr>
|
||
<th class="col-md-2"><%= s_("SmartProxy|Name") %></th>
|
||
<th class="col-md-5"><%= s_("SmartProxy|Url") %></th>
|
||
<th class="col-md-3"><%= _("Features") %></th>
|
||
<th class="col-md-4"><%= s_("SmartProxy|Url") %></th>
|
||
<th class="col-md-4"><%= _("Features") %></th>
|
||
<th class="col-md-1"><%= _('Status') %></th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<% for proxy in @smart_proxies %>
|
||
<tr>
|
||
<td class="display-two-pane ellipsis"><%= link_to_if_authorized proxy.name, hash_for_edit_smart_proxy_path(:id => proxy).merge(:auth_object => proxy, :authorizer => authorizer) %></td>
|
||
<td class="ellipsis"><%= proxy.url %></td>
|
||
<td class="ellipsis"><%= proxy.features.to_sentence %></td>
|
||
<tr class="proxy-show" data-url="<%= ping_smart_proxy_path(proxy) %>">
|
||
<td><%= link_to_if_authorized proxy.name, hash_for_smart_proxy_path(:id => proxy).merge(:auth_object => proxy, :authorizer => authorizer) %></td>
|
||
<td><%= proxy.url %></td>
|
||
<td><%= proxy.features.to_sentence %></td>
|
||
<td>
|
||
<span class="proxy-show-status"><%= spinner %></span>
|
||
</td>
|
||
<td><%= action_buttons(*proxy_actions(proxy, authorizer)) %></td>
|
||
</tr>
|
||
<% end %>
|
app/views/smart_proxies/plugins/_dhcp.html.erb | ||
---|---|---|
<div class="row">
|
||
<h3><%= _('DHCP') %></h3>
|
||
<%= render :partial => 'smart_proxies/plugins/plugin_version', :locals => {:feature => feature, :proxy => @smart_proxy} %>
|
||
<div class="col-md-4">
|
||
<%= _('Subnets') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<%= generate_links_for(@smart_proxy.subnets).html_safe %>
|
||
</div>
|
||
</div>
|
app/views/smart_proxies/plugins/_dns.html.erb | ||
---|---|---|
<div class="row">
|
||
<h3><%= _('DNS') %></h3>
|
||
<%= render :partial => 'smart_proxies/plugins/plugin_version', :locals => {:feature => feature, :proxy => @smart_proxy} %>
|
||
<div class="col-md-4">
|
||
<%= _('Domains') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<%= generate_links_for(@smart_proxy.domains).html_safe %>
|
||
</div>
|
||
</div>
|
app/views/smart_proxies/plugins/_no_template.html.erb | ||
---|---|---|
<div class="row">
|
||
<h3><%= _("#{feature.capitalize}") %></h3>
|
||
<%= render :partial => 'smart_proxies/plugins/plugin_version', :locals => {:feature => feature, :proxy => @smart_proxy} %>
|
||
<div class="col-md-12"><%= _('Data not available for %s') % feature %></div>
|
||
</div>
|
app/views/smart_proxies/plugins/_plugin_version.html.erb | ||
---|---|---|
<div class="col-md-4"><%= _('Version') %></div>
|
||
<div class="col-md-8">
|
||
<span class="plugin-version" data-plugin="<%= feature %>">
|
||
<%= spinner %>
|
||
</span>
|
||
</div>
|
app/views/smart_proxies/plugins/_realm.html.erb | ||
---|---|---|
<div class="row">
|
||
<h3><%= _('Realm') %></h3>
|
||
<%= render :partial => 'smart_proxies/plugins/plugin_version', :locals => {:feature => feature, :proxy => @smart_proxy} %>
|
||
<div class="col-md-4">
|
||
<%= _('Realms') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<%= generate_links_for(@smart_proxy.realms).html_safe %>
|
||
</div>
|
||
</div>
|
app/views/smart_proxies/plugins/_tftp.html.erb | ||
---|---|---|
<div class="row">
|
||
<h3><%= _('TFTP') %></h3>
|
||
<%= render :partial => 'smart_proxies/plugins/plugin_version', :locals => {:feature => feature, :proxy => @smart_proxy} %>
|
||
<div class="col-md-4">
|
||
<%= _('TFTP server') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<span class="proxy-tftp" data-url="<%= tftp_server_smart_proxy_path(@smart_proxy) %>">
|
||
<%= spinner %>
|
||
</span>
|
||
</div>
|
||
</div>
|
app/views/smart_proxies/show.html.erb | ||
---|---|---|
<% javascript('proxy_status') %>
|
||
<% title(_('Smart Proxy: %s') % @smart_proxy.to_label) %>
|
||
<%= smart_proxy_title_actions(@smart_proxy, authorizer) %>
|
||
<% service_features = proxy_features_besides_puppet(@smart_proxy) %>
|
||
<div class="row proxy-show" data-url="<%= ping_smart_proxy_path(@smart_proxy) %>">
|
||
<ul id="proxy-tab" class="nav nav-tabs">
|
||
<li class="active"><a href="#properties" data-toggle="tab"><%= _('Overview') %></a></li>
|
||
<% if service_features.any? %>
|
||
<li><a href="#services" data-toggle="tab"><%= _('Services') %></a></li>
|
||
<% end %>
|
||
</ul>
|
||
<div id="proxy-tab-content" class="proxy-content tab-content">
|
||
<div class="tab-pane active in" id="properties">
|
||
<div class="col-md-6">
|
||
<div class="row">
|
||
<h3><%= _('Details') %></h3>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<%= _('Communication status') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<span class="proxy-show-status">
|
||
<%= spinner %>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<%= _('URL') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<%= @smart_proxy.url %>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<%= _('Version') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<span class="proxy-version" data-url="<%= ping_smart_proxy_path(@smart_proxy) %>">
|
||
<%= spinner %>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<%= _('Features') %>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<%= @smart_proxy.features.to_sentence %> <%= refresh_proxy_icon(@smart_proxy, authorizer) %>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<!--place holder for Capsule sync-->
|
||
</div>
|
||
</div>
|
||
<% if service_features.any? %>
|
||
<div class="tab-pane" id="services">
|
||
<div class="col-md-6">
|
||
<% service_features.each do |feature| %>
|
||
<% feature_erb = "smart_proxies/plugins/#{feature}" %>
|
||
<% if lookup_context.template_exists?(feature_erb, [], true) %>
|
||
<%= render :partial => feature_erb, :locals => {:feature => feature} %>
|
||
<% else %>
|
||
<%= render :partial => "smart_proxies/plugins/no_template", :locals => {:feature => feature} %>
|
||
<% end %>
|
||
<% end %>
|
||
</div>
|
||
</div>
|
||
<% end %>
|
||
</div>
|
||
</div>
|
config/environments/production.rb | ||
---|---|---|
auth_source_ldap
|
||
subnets
|
||
hidden_values
|
||
password_strength)
|
||
password_strength
|
||
proxy-status)
|
||
|
||
stylesheets = %w( )
|
||
|
config/routes.rb | ||
---|---|---|
end
|
||
end
|
||
|
||
resources :smart_proxies, :except => [:show] do
|
||
resources :smart_proxies do
|
||
member do
|
||
post 'ping'
|
||
get 'ping'
|
||
put 'refresh'
|
||
get 'version'
|
||
get 'plugin_version'
|
||
get 'tftp_server'
|
||
end
|
||
constraints(:id => /[^\/]+/) do
|
||
resources :puppetca, :only => [:index, :update, :destroy]
|
lib/proxy_api/tftp.rb | ||
---|---|---|
|
||
# returns the TFTP boot server for this proxy
|
||
def bootServer
|
||
if (response = parse(get("serverName"))) and response["serverName"].present?
|
||
if (response = parse(get("serverName"))) && response["serverName"].present?
|
||
return response["serverName"]
|
||
end
|
||
false
|
lib/proxy_api/version.rb | ||
---|---|---|
end
|
||
|
||
def proxy_versions
|
||
parse get
|
||
@proxy_versions ||= parse(get)
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to detect version"))
|
||
end
|
||
|
||
def version
|
||
proxy_versions["version"]
|
||
end
|
||
end
|
||
end
|
test/functional/smart_proxies_controller_test.rb | ||
---|---|---|
end
|
||
|
||
test "smart proxy version succeeded" do
|
||
SmartProxy.any_instance.stubs(:version).returns({:success => true, :message => '1.11'})
|
||
get :version, { :id => smart_proxies(:one).to_param }, set_session_user
|
||
expected_response = {'version' => '1.11', 'modules' => {'dns' => '1.11'}}
|
||
SmartProxy.any_instance.stubs(:version).returns(expected_response)
|
||
get :ping, { :id => smart_proxies(:one).to_param }, set_session_user
|
||
assert_response :success
|
||
show_response = ActiveSupport::JSON.decode(@response.body)
|
||
assert_equal('1.11', show_response['message'])
|
||
assert_equal('1.11', show_response['message']['version'])
|
||
end
|
||
|
||
test "smart proxy version failed" do
|
||
SmartProxy.any_instance.stubs(:version).raises(Foreman::Exception, 'Exception message')
|
||
get :version, { :id => smart_proxies(:one).to_param }, set_session_user
|
||
get :ping, { :id => smart_proxies(:one).to_param }, set_session_user
|
||
assert_response :success
|
||
show_response = ActiveSupport::JSON.decode(@response.body)
|
||
assert_match(/Exception message/, show_response['message'])
|
||
end
|
||
|
||
test '#show' do
|
||
proxy = smart_proxies(:one)
|
||
get :show, { :id => proxy.id }, set_session_user
|
||
assert_response :success
|
||
assert_template 'show'
|
||
end
|
||
|
||
test 'tftp_server should return tftp address' do
|
||
SmartProxy.any_instance.stubs(:tftp_server).returns('127.13.0.1')
|
||
get :tftp_server, { :id => smart_proxies(:one).to_param }, set_session_user
|
||
assert_response :success
|
||
show_response = ActiveSupport::JSON.decode(@response.body)
|
||
assert_equal('127.13.0.1', show_response['message'])
|
||
end
|
||
|
||
test 'tftp server should return false if not found' do
|
||
get :tftp_server, { :id => smart_proxies(:one).to_param }, set_session_user
|
||
assert_response :success
|
||
show_response = ActiveSupport::JSON.decode(@response.body)
|
||
assert_match(/No TFTP feature/, show_response['message'])
|
||
end
|
||
end
|
test/integration/smart_proxy_test.rb | ||
---|---|---|
test "edit page" do
|
||
visit smart_proxies_path
|
||
click_link "DHCP Proxy"
|
||
click_link "Edit"
|
||
fill_in "smart_proxy_name", :with => "DHCP Secure"
|
||
fill_in "smart_proxy_url", :with => "https://secure.net:8443"
|
||
assert_submit_button(smart_proxies_path)
|
||
assert page.has_link? 'DHCP Secure'
|
||
assert_submit_button(smart_proxy_path(smart_proxies(:one)))
|
||
assert page.has_title? 'DHCP Secure'
|
||
assert page.has_content? "https://secure.net:8443"
|
||
end
|
||
|
||
test "show page" do
|
||
proxy = smart_proxies(:one)
|
||
visit smart_proxy_path(proxy)
|
||
assert page.has_selector?('h1', :text => proxy.to_label), "#{proxy.to_label} <h1> tag, but was not found"
|
||
assert page.has_content? proxy.url
|
||
assert page.has_link? "Delete"
|
||
assert page.has_link? "Edit"
|
||
assert page.has_link? "Refresh features"
|
||
assert page.has_link? "Services"
|
||
click_link "Services"
|
||
# smart_proxies(:one) has DHCP feature
|
||
assert page.has_selector?('h3', :text => "DHCP")
|
||
assert page.has_content? "Version"
|
||
end
|
||
end
|
test/unit/proxy_status_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class ProxyStatusTest < ActiveSupport::TestCase
|
||
setup do
|
||
@proxy = FactoryGirl.
|
||
build_stubbed(:template_smart_proxy, :url => 'https://secure.proxy:4568')
|
||
end
|
||
|
||
test '#versions_cache_key' do
|
||
proxy_status = ProxyStatus.new(@proxy)
|
||
assert_equal("proxy_#{@proxy.id}/versions", proxy_status.versions_cache_key)
|
||
end
|
||
|
||
context '#tftp_server' do
|
||
test 'it returns tftp server ip' do
|
||
ProxyAPI::TFTP.any_instance.stubs(:bootServer).returns('127.13.0.1')
|
||
proxy_status = ProxyStatus.new(@proxy)
|
||
assert_equal('127.13.0.1', proxy_status.tftp_server)
|
||
end
|
||
|
||
test 'it caches tftp_server' do
|
||
ProxyAPI::TFTP.any_instance.stubs(:bootServer).returns('127.13.0.1')
|
||
ProxyStatus.new(@proxy).tftp_server
|
||
assert_equal('127.13.0.1', Rails.cache.fetch("proxy_#{@proxy.id}/tftp_server"))
|
||
end
|
||
|
||
test 'it raises an error if proxy has no tftp feature' do
|
||
proxy = FactoryGirl.build_stubbed(:smart_proxy)
|
||
assert_raise Foreman::Exception do
|
||
ProxyStatus.new(proxy).tftp_server
|
||
end
|
||
end
|
||
end
|
||
|
||
context '#api_versions' do
|
||
setup do
|
||
@expected_versions = {'version' => '1.11', 'modules' => {'dns' => '1.11'}}
|
||
ProxyAPI::Version.any_instance.stubs(:proxy_versions).returns(@expected_versions)
|
||
end
|
||
|
||
test 'it returns version from the proxy' do
|
||
proxy_status = ProxyStatus.new(@proxy)
|
||
assert_equal(@expected_versions, proxy_status.api_versions)
|
||
end
|
||
|
||
test 'it caches api_versions' do
|
||
ProxyStatus.new(@proxy).api_versions
|
||
assert_equal(@expected_versions, Rails.cache.fetch("proxy_#{@proxy.id}/versions"))
|
||
end
|
||
|
||
test 'it raises error if no connection to proxy' do
|
||
ProxyAPI::Version.any_instance.stubs(:proxy_versions).raises(Net::HTTPBadResponse)
|
||
assert_raise(Foreman::WrappedException, "Unable to connect to smart proxy") do
|
||
ProxyStatus.new(@proxy).api_versions
|
||
end
|
||
end
|
||
end
|
||
end
|
test/unit/smart_proxy_test.rb | ||
---|---|---|
end
|
||
|
||
context "#version" do
|
||
def setup
|
||
Rails.cache.clear
|
||
end
|
||
|
||
test "should succeed" do
|
||
proxy = smart_proxies(:one)
|
||
fake_version = {:version => '1.11'}
|
||
fake_version = {'version' => '1.11'}
|
||
ProxyAPI::Version.any_instance.expects(:get).returns(fake_response(fake_version))
|
||
assert_equal(fake_version[:version], proxy.version[:message])
|
||
assert_equal(fake_version, proxy.version)
|
||
end
|
||
|
||
test "should raise error" do
|
Also available in: Unified diff
fixes #12714 - Show proxy status in index, and create a show page for proxy