Skip to content

Commit

Permalink
fixes #6519 - updating associations UI
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasmckay committed Jul 29, 2014
1 parent 3433537 commit 7e86b53
Show file tree
Hide file tree
Showing 28 changed files with 665 additions and 133 deletions.
6 changes: 5 additions & 1 deletion app/controllers/katello/api/v2/systems_controller.rb
Expand Up @@ -73,9 +73,13 @@ def index
environment_ids = environment_ids.empty? ? params[:environment_id] : environment_ids & [params[:environment_id].to_i] if params[:environment_id]
if !environment_ids.empty?
filters << {:terms => {:environment_id => environment_ids}}
elsif params[:host_collection_id]
end
if params[:host_collection_id]
filters << {:terms => {:host_collection_ids => [params[:host_collection_id]] }}
end
if params[:activation_key_id]
filters << {:terms => {:activation_key_ids => [params[:activation_key_id]] }}
end

filters << {:terms => {:uuid => System.all_by_pool_uuid(params['pool_id']) }} if params['pool_id']
filters << {:terms => {:uuid => [params['uuid']] }} if params['uuid']
Expand Down
8 changes: 4 additions & 4 deletions app/lib/katello/resources/candlepin.rb
Expand Up @@ -742,8 +742,8 @@ def regenerate_entitlement_certificates_for_product(product_id)
self.put("/candlepin/entitlements/product/#{product_id}", nil, self.default_headers).code.to_i
end

def get(id = nil)
json = Candlepin::CandlepinResource.get(path(id), self.default_headers).body
def get(id = nil, params = '')
json = Candlepin::CandlepinResource.get(path(id) + params, self.default_headers).body
JSON.parse(json)
end

Expand All @@ -756,8 +756,8 @@ def path(id = nil)
class ActivationKey < CandlepinResource
class << self

def get(id = nil)
akeys_json = super(path(id), self.default_headers).body
def get(id = nil, params = '')
akeys_json = super(path(id) + params, self.default_headers).body
akeys = JSON.parse(akeys_json)
akeys = [akeys] unless id.nil?
Util::Data.array_with_indifferent_access akeys
Expand Down
10 changes: 7 additions & 3 deletions app/models/katello/glue/candlepin/pool.rb
Expand Up @@ -168,16 +168,20 @@ def load_remote_data(attrs)
end

def products
Product.where(:cp_id => provided_products.map { |prod| prod[:productId] })
Katello::Product.where(:cp_id => provided_products.map { |prod| prod[:productId] })
end

def systems
System.all_by_pool(cp_id)
end

def activation_keys
# TODO: no longer valid - error thrown here now
ActivationKey.joins(:pools).where("#{self.class.table_name}.cp_id" => cp_id)
keys = Resources::Candlepin::ActivationKey.get(nil, "?include=id&include=pools.pool.id")
activation_key_ids = keys.collect do |key|
key['id'] if key['pools'].any? { |pool| pool['pool']['id'] == cp_id }
end

return Katello::ActivationKey.where(:cp_id => activation_key_ids.compact)
end

def distributors
Expand Down
14 changes: 14 additions & 0 deletions app/models/katello/glue/elastic_search/system.rb
Expand Up @@ -24,6 +24,8 @@ def self.included(base)

add_host_collection_hook lambda { |host_collection| reindex_on_association_change(host_collection) }
remove_host_collection_hook lambda { |host_collection| reindex_on_association_change(host_collection) }
add_activation_key_hook lambda { |activation_key| reindex_on_association_change(activation_key) }
remove_activation_key_hook lambda { |activation_key| reindex_on_association_change(activation_key) }

# 'index_options' controls what attributes are indexed and stored in ES. From indexed_model.rb
# :json - normal to_json options, :only or :except allowed
Expand All @@ -48,6 +50,7 @@ def self.included(base)
:created_at,
:lastCheckin,
:host_collection,
:activation_key,
:installed_products,
"custom_info.KEYNAME",
:content_view,
Expand Down Expand Up @@ -129,6 +132,8 @@ def extended_index_attrs
:organization_id => self.organization.id,
:host_collection => self.host_collections.collect{|g| g.name},
:host_collection_ids => self.host_collection_ids,
:activation_key => self.activation_keys.collect{|g| g.name},
:activation_key_ids => self.activation_key_ids,
:installed_products => collect_installed_product_names,
:sockets => self.sockets,
:custom_info => collect_custom_info,
Expand Down Expand Up @@ -159,7 +164,16 @@ def update_host_collections
Tire.index System.index.name do
update System.document_type, system_id, {:script => id_update + name_update }
end
end

def update_activation_keys
system_id = self.id #save the system id for the block
id_update = "ctx._source.activation_key_ids = [#{self.activation_key_ids.join(",")}]; "
names = self.activation_keys.pluck(:name).map{|name| "\"#{name}\""}
name_update = "ctx._source.activation_key = [#{names.join(",")}];"
Tire.index System.index.name do
update System.document_type, system_id, {:script => id_update + name_update }
end
end

end
Expand Down
18 changes: 16 additions & 2 deletions app/models/katello/system.rb
Expand Up @@ -19,6 +19,7 @@ class System < Katello::Model

include Hooks
define_hooks :add_host_collection_hook, :remove_host_collection_hook,
:add_activation_key_hook, :remove_activation_key_hook,
:as_json_hook

include ForemanTasks::Concerns::ActionSubject
Expand All @@ -30,7 +31,8 @@ class System < Katello::Model
include AsyncOrchestration

attr_accessible :name, :uuid, :description, :location, :environment, :content_view,
:environment_id, :content_view_id, :host_collection_ids, :host_id
:environment_id, :content_view_id, :host_collection_ids, :host_id,
:activation_key_ids

after_rollback :rollback_on_create, :on => :create

Expand All @@ -39,7 +41,11 @@ class System < Katello::Model

has_many :task_statuses, :class_name => "Katello::TaskStatus", :as => :task_owner, :dependent => :destroy
has_many :system_activation_keys, :class_name => "Katello::SystemActivationKey", :dependent => :destroy
has_many :activation_keys, :through => :system_activation_keys
has_many :activation_keys, {
:through => :system_activation_keys,
:after_add => :add_activation_key,
:after_remove => :remove_activation_key
}
has_many :system_host_collections, :class_name => "Katello::SystemHostCollection", :dependent => :destroy
has_many :host_collections, {:through => :system_host_collections,
:after_add => :add_host_collection,
Expand Down Expand Up @@ -93,6 +99,14 @@ def remove_host_collection(host_collection)
run_hook(:remove_host_collection_hook, host_collection)
end

def add_activation_key(activation_key)
run_hook(:add_activation_key_hook, activation_key)
end

def remove_activation_key(activation_key)
run_hook(:remove_activation_key_hook, activation_key)
end

class << self
def architectures
{ 'i386' => 'x86', 'ia64' => 'Itanium', 'x86_64' => 'x86_64', 'ppc' => 'PowerPC',
Expand Down
52 changes: 45 additions & 7 deletions app/views/katello/api/v2/subscriptions/show.json.rabl
Expand Up @@ -30,15 +30,53 @@ end

node :systems, :if => (params[:action] == "show") do |subscription|
current_organization = subscription.organization
subscription.systems.readable.map { |sys| {id: sys.id, name: sys.name} }
subscription.systems.readable.map do |sys|
facts = sys.facts
{
uuid: sys.uuid,
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,
facts: {
memory: {
memtotal: facts['memory.memtotal']
},
cpu: {
'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']
}
}
}
end
end

# TODO: what should replace this since activerecord relation is gone?
# http://projects.theforeman.org/issues/4255
# node :activation_keys, :if => (params[:action] == "show") do |subscription|
# current_organization = subscription.organization
# subscription.activation_keys.readable(current_organization).map { |key| {id: key.id, name: key.name} }
# end
node :activation_keys, :if => (params[:action] == "show") do |subscription|
current_organization = subscription.organization
subscription.activation_keys.readable.map do |key|
{
id: key.id,
name: key.name,
release_version: key.release_version,
service_level: key.service_level,
environment: {
id: key.environment.try(:id),
name: key.environment.try(:name)
},
content_view: {
id: key.content_view.try(:id),
name: key.content_view.try(:name)
}
}
end
end

node :host, :if => lambda { |sub| sub && sub.host } do |subscription|
{id: subscription.host.id, name: subscription.host.name}
Expand Down
1 change: 1 addition & 0 deletions config/routes/api/v2.rb
Expand Up @@ -52,6 +52,7 @@ class ActionDispatch::Routing::Mapper
match '/available' => 'subscriptions#available', :via => :get
end
end
api_resources :systems, :only => [:index]
end

api_resources :content_views do
Expand Down
Expand Up @@ -29,6 +29,7 @@ angular.module('Bastion.activation-keys').factory('ActivationKey',
releaseVersions: {method: 'GET', params: {action: 'releases'}},
subscriptions: {method: 'GET', params: {action: 'subscriptions'}},
products: {method: 'GET', params: {action: 'products'}},
contentHosts: {method: 'GET', params: {action: 'systems'}},
availableSubscriptions: {method: 'GET', params: {action: 'subscriptions', action2: 'available'}},
removeSubscriptions: {method: 'PUT', isArray: false, params: {action: 'subscriptions'}},
addSubscriptions: {method: 'POST', isArray: false, params: {action: 'subscriptions'}},
Expand Down
Expand Up @@ -124,6 +124,13 @@ angular.module('Bastion.activation-keys').config(['$stateProvider', function ($s
collapsed: true,
controller: 'ActivationKeyAddHostCollectionsController',
templateUrl: 'activation-keys/details/views/activation-key-host-collections-table.html'
})
.state('activation-keys.details.associations-content-hosts', {
url: '/associations/content-hosts',
permission: 'view_activation_keys',
collapsed: true,
controller: 'ActivationKeyAssociationsController',
templateUrl: 'activation-keys/details/views/activation-key-associations-content-hosts.html'
});

}]);
@@ -0,0 +1,49 @@
/**
* Copyright 2013-2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public
* License as published by the Free Software Foundation; either version
* 2 of the License (GPLv2) or (at your option) any later version.
* There is NO WARRANTY for this software, express or implied,
* including the implied warranties of MERCHANTABILITY,
* NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
* have received a copy of GPLv2 along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*/

/**
* @ngdoc object
* @name Bastion.activation-keys.controller:ActivationKeyAssociationsController
*
* @requires $scope
* @requires translate
* @requires ActivationKey
* @requires ContentHostsHelper
* @requires CurrentOrganization
*
* @description
* Provides the functionality for activation key associations.
*/
angular.module('Bastion.activation-keys').controller('ActivationKeyAssociationsController',
['$scope', 'translate', 'ActivationKey', 'ContentHostsHelper', 'CurrentOrganization',
function ($scope, translate, ActivationKey, ContentHostsHelper, CurrentOrganization) {

if ($scope.contentHosts) {
$scope.table.working = false;
} else {
$scope.table.working = true;
}

$scope.activationKey.$promise.then(function () {
ActivationKey.contentHosts({id: $scope.activationKey.id, 'organization_id': CurrentOrganization },
function (response) {
$scope.contentHosts = response.results;
$scope.table.working = false;
});
});

$scope.getStatusColor = ContentHostsHelper.getStatusColor;

$scope.memory = ContentHostsHelper.memory;
}]
);
@@ -0,0 +1,47 @@
<span page-title ng-model="activationKey">{{ 'Content Hosts for Activation Key:' | translate }} {{ activationKey.name }}</span>

<div class="details details-full">

<h3 translate>
Attached to Content Hosts
</h3>

<table class="table table-striped" alch-table="table" ng-class="{'table-mask': table.working}">
<thead>
<tr alch-table-head>
<th alch-table-column="name" sortable>{{ "Name" | translate }}</th>
<th alch-table-column="status">
{{ "Subscription Status" | translate }}
</th>
<th alch-table-column="environment" sortable>{{ "Environment" | translate }}</th>
<th alch-table-column="contentView">{{ "Content View" | translate }}</th>
<th alch-table-column="serviceLevel">{{ "Service Level" | translate }}</th>
<th alch-table-column="releaseVersion">{{ "Release Version" | translate }}</th>
</tr>
</thead>

<tbody>
<tr ng-show="!table.working && contentHosts.length === 0">
<td colspan="6" translate>This activation key is not associated with any content hosts.</td>
</tr>

<tr alch-table-row ng-repeat="contentHost in contentHosts"
ng-controller="ContentHostStatusController">
<td alch-table-cell>
<a ui-sref="content-hosts.details.info({contentHostId: contentHost.uuid})">
{{ contentHost.name }}
</a>
</td>
<td alch-table-cell>
<span class="icon-circle" ng-class="getStatusColor(contentHost.entitlementStatus)">
</span>
</td>
<td alch-table-cell>{{ contentHost.environment.name }}</td>
<td alch-table-cell>{{ contentHost.content_view.name || "" }}</td>
<td alch-table-cell>{{ contentHost.service_level }}</td>
<td alch-table-cell>{{ contentHost.release_ver }}</td>
</tr>
</tbody>
</table>

</div>
Expand Up @@ -60,8 +60,8 @@ <h5 translate>Copy</h5>
</form>
</div>

<nav class="details-navigation">
<ul>
<nav>
<ul class="nav nav-tabs">
<li ng-class="{active: isState('activation-keys.details.info')}">
<a ui-sref="activation-keys.details.info">
<span translate>
Expand Down Expand Up @@ -90,6 +90,20 @@ <h5 translate>Copy</h5>
</span>
</a>
</li>
<li class="dropdown"
ng-class="{active: stateIncludes('activation-keys.details.associations-content-hosts')}">
<a class="dropdown-toggle">
<span translate>Associations</span>
<i class="icon-chevron-down"></i>
</a>
<ul class="dropdown-menu">
<li>
<a ui-sref="activation-keys.details.associations-content-hosts({activationKeyId: activationKey.id})" translate>
Content Hosts
</a>
</li>
</ul>
</li>
</ul>
</nav>

Expand Down

0 comments on commit 7e86b53

Please sign in to comment.