Skip to content

Commit

Permalink
Fixes #15347 - Filter hosts for activation key associations (#6113)
Browse files Browse the repository at this point in the history
All systems are being returned in the activation key associations page.
This changes that page to use hosts endpoint instead of activation keys,
which makes it possible to use scoped search to filter them.
  • Loading branch information
John Mitsch committed Jun 17, 2016
1 parent 57ab21e commit 515a48b
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 30 deletions.
25 changes: 25 additions & 0 deletions app/models/katello/concerns/subscription_facet_host_extensions.rb
Expand Up @@ -14,6 +14,7 @@ module SubscriptionFacetHostExtensions

has_one :subscription_facet, :class_name => '::Katello::Host::SubscriptionFacet', :foreign_key => :host_id, :inverse_of => :host, :dependent => :destroy

has_many :activation_keys, :through => :subscription_facet
has_one :subscription_status_object, :class_name => 'Katello::SubscriptionStatus', :foreign_key => 'host_id'
scoped_search :on => :status, :in => :subscription_status_object, :rename => :subscription_status,
:complete_value => SUBSCRIPTION_STATUS_MAP
Expand All @@ -26,13 +27,37 @@ module SubscriptionFacetHostExtensions
scoped_search :on => :last_checkin, :in => :subscription_facet, :complete_value => true
scoped_search :on => :registered_at, :in => :subscription_facet, :rename => :registered_at
scoped_search :on => :uuid, :in => :subscription_facet, :rename => :subscription_uuid
scoped_search :in => :activation_keys, :on => :name, :rename => :activation_key, :complete_value => true, :ext_method => :find_by_activation_key
scoped_search :in => :activation_keys, :on => :id, :rename => :activation_key_id, :complete_value => true, :ext_method => :find_by_activation_key_id
end

def update_action
if subscription_facet.try(:backend_update_needed?)
::Actions::Katello::Host::Update
end
end

module ClassMethods
def find_by_activation_key(_key, operator, value)
conditions = sanitize_sql_for_conditions(["#{Katello::ActivationKey.table_name}.name #{operator} ?", value_to_sql(operator, value)])
hosts = ::Host::Managed.joins(:activation_keys).where(conditions)
if hosts.empty?
{ :conditions => "1=0" }
else
{ :conditions => "#{::Host::Managed.table_name}.id IN (#{hosts.pluck(:id).join(',')})" }
end
end

def find_by_activation_key_id(_key, operator, value)
conditions = sanitize_sql_for_conditions(["#{Katello::ActivationKey.table_name}.id #{operator} ?", value_to_sql(operator, value)])
hosts = ::Host::Managed.joins(:activation_keys).where(conditions)
if hosts.empty?
{ :conditions => "1=0" }
else
{ :conditions => "#{::Host::Managed.table_name}.id IN (#{hosts.pluck(:id).join(',')})" }
end
end
end
end
end
end
6 changes: 6 additions & 0 deletions app/models/katello/glue/candlepin/pool.rb
Expand Up @@ -135,6 +135,12 @@ def create_activation_key_associations
def host
System.find_by(:uuid => host_id) if host_id
end

def hosts
entitlements = Resources::Candlepin::Entitlement.get
uuids = entitlements.delete_if { |ent| ent["pool"]["id"] != cp_id }.map { |ent| ent["consumer"]["uuid"] }
::Host.where(:id => Katello::Host::ContentFacet.where(:uuid => uuids).pluck(:host_id))
end
end
end
end
36 changes: 19 additions & 17 deletions app/views/katello/api/v2/subscriptions/show.json.rabl
Expand Up @@ -13,34 +13,36 @@ node :provided_products, :if => lambda { |sub| sub && !sub.products.blank? } do
end

node :systems do |subscription|
subscription.systems.readable.map do |sys|
facts = sys.facts
subscription.hosts.map do |host|
facts = host.facts
{
uuid: sys.uuid,
host_id: sys.host_id,
name: sys.name,
environment: { id: sys.environment.id, name: sys.environment.name },
content_view: { id: sys.content_view.id, name: sys.content_view.name },
created: sys.created,
checkin_time: sys.checkin_time,
entitlement_status: sys.entitlementStatus,
service_level: sys.serviceLevel,
autoheal: sys.autoheal,
uuid: host.subscription_facet.try(:uuid),
host_id: host.id,
name: host.name,
environment: { id: host.content_facet.try(:lifecycle_environment).try(:id),
name: host.content_facet.try(:lifecycle_environment).try(:name) },
content_view: { id: host.content_facet.try(:content_view).try(:id),
name: host.content_facet.try(:content_view).try(:name) },
created: host.subscription_facet.try(:registered_at),
checkin_time: host.subscription_facet.try(:last_checkin),
entitlement_status: host.subscription_status,
service_level: host.subscription_facet.try(:service_level),
autoheal: host.subscription_facet.try(:autoheal),
facts: {
dmi: {
memory: {
size: facts['dmi.memory.size']
size: facts['dmi::memory::size']
}
},
memory: {
memtotal: facts['memory.memtotal']
memtotal: facts['memory::memtotal']
},
cpu: {
'cpu_socket(s)' => facts['cpu.cpu_socket(s)'],
'core(s)_per_socket' => facts['cpu.core(s)_per_socket']
'cpu_socket(s)' => facts['cpu::cpu_socket(s)'],
'core(s)_per_socket' => facts['cpu::core(s)_per_socket']
},
virt: {
is_guest: facts['virt.is_guest']
is_guest: facts['virt::is_guest']
}
}
}
Expand Down
Expand Up @@ -14,8 +14,8 @@
* Provides the functionality for activation key associations.
*/
angular.module('Bastion.activation-keys').controller('ActivationKeyAssociationsController',
['$scope', '$location', 'translate', 'Nutupane', 'ActivationKey', 'ContentHostsHelper', 'CurrentOrganization',
function ($scope, $location, translate, Nutupane, ActivationKey, ContentHostsHelper, CurrentOrganization) {
['$scope', '$location', 'translate', 'Nutupane', 'ActivationKey', 'ContentHostsHelper', 'CurrentOrganization', 'Host',
function ($scope, $location, translate, Nutupane, ActivationKey, ContentHostsHelper, CurrentOrganization, Host) {
var contentHostsNutupane, params = {
'organization_id': CurrentOrganization,
'search': $location.search().search || "",
Expand All @@ -31,12 +31,21 @@ angular.module('Bastion.activation-keys').controller('ActivationKeyAssociationsC
$scope.table.working = false;
}

contentHostsNutupane = new Nutupane(ActivationKey, params, 'contentHosts');
contentHostsNutupane = new Nutupane(Host, params);
contentHostsNutupane.searchTransform = function (term) {
var searchQuery, addition = "activation_key_id=" + $scope.$stateParams.activationKeyId;
if (term === "" || angular.isUndefined(term)) {
searchQuery = addition;
} else {
searchQuery = term + " and " + addition;
}
return searchQuery;
};

contentHostsNutupane.masterOnly = true;
$scope.detailsTable = contentHostsNutupane.table;

$scope.activationKey.$promise.then(function () {
params.id = $scope.activationKey.id;
contentHostsNutupane.setParams(params);
contentHostsNutupane.load();
});
Expand Down
Expand Up @@ -26,21 +26,21 @@
</thead>

<tbody>
<tr bst-table-row ng-repeat="contentHost in detailsTable.rows"
<tr bst-table-row ng-repeat="host in detailsTable.rows"
ng-controller="ContentHostStatusController">
<td bst-table-cell>
<a ui-sref="content-hosts.details.info({hostId: contentHost.host_id})">
{{ contentHost.name }}
<a ui-sref="content-hosts.details.info({hostId: host.host_id})">
{{ host.name }}
</a>
</td>
<td bst-table-cell>
<span ng-class="getHostStatusIcon(contentHost.entitlementStatus)">
<span ng-class="getHostStatusIcon(host.subscription_global_status)">
</span>
</td>
<td bst-table-cell>{{ contentHost.environment.name }}</td>
<td bst-table-cell>{{ contentHost.content_view.name || "" }}</td>
<td bst-table-cell>{{ contentHost.service_level }}</td>
<td bst-table-cell>{{ contentHost.release_ver }}</td>
<td bst-table-cell>{{ host.environment.name }}</td>
<td bst-table-cell>{{ host.content_view.name || "" }}</td>
<td bst-table-cell>{{ host.service_level }}</td>
<td bst-table-cell>{{ host.release_ver }}</td>
</tr>
</tbody>
</table>
Expand Down
Expand Up @@ -2,6 +2,7 @@ describe('Controller: ActivationKeyAssociationsController', function() {
var $scope,
ActivationKey,
CurrentOrganization,
Host,
translate;

beforeEach(module(
Expand All @@ -11,7 +12,8 @@ describe('Controller: ActivationKeyAssociationsController', function() {

beforeEach(inject(function($injector) {
var $controller = $injector.get('$controller'),
ActivationKey = $injector.get('MockResource').$new();
ActivationKey = $injector.get('MockResource').$new(),
Host = $injector.get('MockResource').$new();

translate = function (message) {
return message;
Expand All @@ -36,6 +38,7 @@ describe('Controller: ActivationKeyAssociationsController', function() {
$scope: $scope,
translate: translate,
ActivationKey: ActivationKey,
Host: Host,
ContentHostsHelper: {},
CurrentOrganization: "ACME"
});
Expand Down
11 changes: 11 additions & 0 deletions test/models/host/subscription_facet_test.rb
Expand Up @@ -6,6 +6,7 @@ class SubscriptionFacetBase < ActiveSupport::TestCase
let(:library) { katello_environments(:library) }
let(:dev) { katello_environments(:dev) }
let(:view) { katello_content_views(:library_dev_view) }
let(:activation_key) { katello_activation_keys(:simple_key) }
let(:empty_host) { ::Host::Managed.create!(:name => 'foobar', :managed => false) }
let(:host) do
FactoryGirl.create(:host, :with_content, :with_subscription, :content_view => view,
Expand Down Expand Up @@ -140,5 +141,15 @@ def test_backend_update_needed?
subscription_facet.host.content_facet.lifecycle_environment_id = dev.id
assert subscription_facet.backend_update_needed?
end

def test_search_by_activation_key_id
host.subscription_facet.activation_keys << activation_key
assert_includes ::Host.search_for("activation_key_id = #{activation_key.id}"), host
end

def test_search_by_activation_key
host.subscription_facet.activation_keys << activation_key
assert_includes ::Host.search_for("activation_key = \"#{activation_key.name}\""), host
end
end
end
13 changes: 13 additions & 0 deletions test/models/pool_test.rb
Expand Up @@ -3,6 +3,8 @@
module Katello
class PoolTest < ActiveSupport::TestCase
def setup
@library = katello_environments(:library)
@view = katello_content_views(:library_dev_view)
@pool_one = katello_pools(:pool_one)
@pool_two = katello_pools(:pool_two)
end
Expand Down Expand Up @@ -56,6 +58,17 @@ def test_with_identifiers
assert_equal Pool.with_identifier("#{@pool_one.id}"), @pool_one
end

def test_hosts
active_pool = FactoryGirl.build(:katello_pool, :active)
host_one = FactoryGirl.create(:host, :with_content, :with_subscription, :content_view => @view,
:lifecycle_environment => @library)
cp_id = "foo"
active_pool.cp_id = cp_id
pool_data = [{"pool" => {"id" => cp_id}, "consumer" => {"uuid" => host_one.content_facet.uuid}}]
Resources::Candlepin::Entitlement.expects(:get).returns(pool_data)
assert_equal active_pool.hosts, [host_one]
end

def test_search_consumed
subscriptions = Pool.search_for("consumed = \"#{@pool_one.consumed}\"")
assert_includes subscriptions, @pool_one
Expand Down

0 comments on commit 515a48b

Please sign in to comment.