foreman_content 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +40 -1
- data/app/controllers/content/api/repositories_controller.rb +3 -5
- data/app/controllers/content/content_views_controller.rb +48 -0
- data/app/controllers/content/products_controller.rb +1 -1
- data/app/controllers/content/repositories_controller.rb +9 -6
- data/app/helpers/content/content_views_helper.rb +21 -0
- data/app/helpers/content/products_helper.rb +9 -0
- data/app/helpers/content/repositories_helper.rb +3 -49
- data/app/models/concerns/content/environment_extensions.rb +2 -2
- data/app/models/concerns/content/home_helper.rb +1 -0
- data/app/models/concerns/content/host_extensions.rb +17 -1
- data/app/models/concerns/content/hostgroup_extensions.rb +14 -0
- data/app/models/concerns/content/operatingsystem_extensions.rb +6 -5
- data/app/models/concerns/content/orchestration/pulp/clone.rb +77 -0
- data/app/models/concerns/content/orchestration/pulp/sync.rb +70 -0
- data/app/models/concerns/content/orchestration/pulp.rb +25 -0
- data/app/models/content/available_content_view.rb +12 -0
- data/app/models/content/content_view.rb +66 -0
- data/app/models/content/content_view_host.rb +9 -0
- data/app/models/content/content_view_repository_clone.rb +5 -0
- data/app/models/content/host_product.rb +0 -11
- data/app/models/content/hostgroup_product.rb +0 -11
- data/app/models/content/operatingsystem_repository.rb +0 -11
- data/app/models/content/product.rb +6 -5
- data/app/models/content/repository/operating_system.rb +14 -0
- data/app/models/content/repository/product.rb +21 -0
- data/app/models/content/repository.rb +28 -39
- data/app/models/content/repository_clone.rb +29 -0
- data/app/models/content/validators/content_validator.rb +0 -12
- data/app/models/content/validators/description_format.rb +0 -12
- data/app/models/content/validators/no_trailing_space.rb +0 -12
- data/app/models/setting/content.rb +0 -18
- data/app/overrides/{add_host_conent_tab.rb → add_host_content_tab.rb} +2 -2
- data/app/overrides/{add_hostgroup_conent_tab.rb → add_hostgroup_content_tab.rb} +1 -1
- data/app/services/content/content_view_factory.rb +41 -0
- data/app/services/content/{pulp_configuration.rb → pulp/configuration.rb} +1 -1
- data/app/services/content/pulp/event_handler.rb +61 -0
- data/app/services/content/pulp/repository.rb +200 -0
- data/app/services/content/pulp/repository_clone.rb +24 -0
- data/app/services/content/pulp/repository_sync_history.rb +35 -0
- data/app/services/content/pulp/repository_sync_status.rb +30 -0
- data/app/views/content/content_views/_form.html.erb +49 -0
- data/app/views/content/content_views/_form_tab.html.erb +3 -0
- data/app/views/content/content_views/_host_tab_pane.html.erb +5 -0
- data/app/views/content/content_views/_step1.html.erb +18 -0
- data/app/views/content/content_views/_step2.html.erb +16 -0
- data/app/views/content/content_views/edit.html.erb +5 -0
- data/app/views/content/content_views/index.html.erb +27 -0
- data/app/views/content/content_views/new.html.erb +11 -0
- data/app/views/content/products/_form.html.erb +2 -13
- data/app/views/content/products/_form_tab.html.erb +3 -3
- data/app/views/content/products/_hostgroup_tab_pane.html.erb +2 -2
- data/app/views/content/products/index.html.erb +6 -1
- data/app/views/content/repositories/_os_form.html.erb +22 -0
- data/app/views/content/repositories/{_form.html.erb → _product_form.html.erb} +4 -6
- data/app/views/content/repositories/edit.html.erb +5 -2
- data/app/views/content/repositories/index.html.erb +12 -9
- data/app/views/content/repositories/new.html.erb +5 -2
- data/app/views/content/repositories/show.html.erb +9 -16
- data/config/environment.rb +0 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20130702140034_create_content_repositories.rb +6 -2
- data/db/migrate/20130722084911_create_content_operatingsystem_repositories.rb +1 -1
- data/db/migrate/20130807121629_create_content_content_views.rb +15 -0
- data/db/migrate/20130807123220_create_content_available_content_views.rb +11 -0
- data/db/migrate/20130812154754_create_content_content_view_hosts.rb +9 -0
- data/db/migrate/20130813110455_create_content_repository_clones.rb +17 -0
- data/db/migrate/20130825145431_create_content_content_view_repository_clones.rb +12 -0
- data/lib/content/engine.rb +2 -0
- data/lib/content/version.rb +1 -1
- data/test/fixtures/content/repository_clones.yml +21 -0
- data/test/unit/content/repository_clone_test.rb +7 -0
- metadata +44 -17
- data/app/models/concerns/content/custom_repository_paths.rb +0 -29
- data/app/models/content/environment_product.rb +0 -19
- data/app/models/content/orchestration/pulp.rb +0 -93
- data/app/models/content/product_operatingsystem.rb +0 -19
- data/app/models/content/remote/pulp/repository.rb +0 -48
- data/app/overrides/add_os_conent_tab.rb +0 -9
- data/app/services/content/pulp_event_handler.rb +0 -25
- data/app/views/content/products/_host_tab_pane.html.erb +0 -5
- data/app/views/content/products/_operatingsystem_tab_pane.html.erb +0 -5
- data/db/migrate/20130717032320_create_content_environments_products.rb +0 -9
- data/db/migrate/20130729032320_create_content_product_operatingsystems.rb +0 -9
@@ -1,14 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# Copyright 2013 Red Hat, Inc.
|
3
|
-
#
|
4
|
-
# This software is licensed to you under the GNU General Public
|
5
|
-
# License as published by the Free Software Foundation; either version
|
6
|
-
# 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
-
# There is NO WARRANTY for this software, express or implied,
|
8
|
-
# including the implied warranties of MERCHANTABILITY,
|
9
|
-
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
-
# have received a copy of GPLv2 along with this software; if not, see
|
11
|
-
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
1
|
module Content
|
13
2
|
class OperatingsystemRepository < ActiveRecord::Base
|
14
3
|
belongs_to :operatingsystem
|
@@ -3,11 +3,8 @@ module Content
|
|
3
3
|
include ::Taxonomix
|
4
4
|
|
5
5
|
has_many :repositories
|
6
|
-
has_many :
|
7
|
-
has_many :
|
8
|
-
|
9
|
-
has_many :product_operatingsystems, :dependent => :destroy, :uniq=>true
|
10
|
-
has_many :operatingsystems, :through => :product_operatingsystems
|
6
|
+
has_many :repository_clones, :through => :repositories
|
7
|
+
has_many :content_views, :as => :originator
|
11
8
|
|
12
9
|
has_many :hostgroup_products, :dependent => :destroy, :uniq=>true
|
13
10
|
has_many :hostgroups, :through => :hostgroup_products
|
@@ -15,6 +12,10 @@ module Content
|
|
15
12
|
has_many :host_products, :dependent => :destroy, :uniq=>true
|
16
13
|
has_many :hosts, :through => :host_products
|
17
14
|
|
15
|
+
before_destroy EnsureNotUsedBy.new(:hostgroups, :hosts, :repositories)
|
16
|
+
|
17
|
+
scope :has_repos, joins(:repositories).uniq
|
18
|
+
|
18
19
|
validates_with Validators::DescriptionFormat, :attributes => :description
|
19
20
|
validates :name, :presence => true
|
20
21
|
validates_with Validators::NameFormat, :attributes => :name
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Content
|
2
|
+
class Repository::Product < Repository
|
3
|
+
|
4
|
+
has_many :operatingsystem_repositories, :foreign_key => :repository_id, :dependent => :destroy, :uniq => true
|
5
|
+
has_many :operatingsystems, :through => :operatingsystem_repositories
|
6
|
+
|
7
|
+
validates_presence_of :product
|
8
|
+
|
9
|
+
def self.model_name
|
10
|
+
Repository.model_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def content_types
|
14
|
+
TYPES - [KICKSTART_TYPE]
|
15
|
+
end
|
16
|
+
|
17
|
+
def entity_name
|
18
|
+
product.name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,29 +1,25 @@
|
|
1
|
-
require 'content/orchestration/pulp'
|
2
|
-
# TODO: split into a custom and red hat repositories:
|
3
|
-
# as handling of repo creation/updates is different between them
|
4
1
|
module Content
|
5
2
|
class Repository < ActiveRecord::Base
|
6
|
-
include
|
7
|
-
include
|
8
|
-
include ::Orchestration
|
9
|
-
include Content::Orchestration::Pulp
|
3
|
+
include Content::Orchestration::Pulp::Sync
|
4
|
+
include Foreman::STI
|
10
5
|
|
11
6
|
YUM_TYPE = 'yum'
|
12
7
|
KICKSTART_TYPE = 'kickstart'
|
13
8
|
FILE_TYPE = 'iso'
|
14
9
|
TYPES = [YUM_TYPE, KICKSTART_TYPE, FILE_TYPE]
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
belongs_to :product
|
11
|
+
belongs_to :product, :class_name => 'Content::Product'
|
12
|
+
belongs_to :operatingsystem
|
19
13
|
belongs_to :gpg_key
|
20
14
|
belongs_to :architecture
|
21
|
-
has_many :
|
22
|
-
|
15
|
+
has_many :repository_clones
|
16
|
+
|
17
|
+
before_destroy EnsureNotUsedBy.new(:repository_clones)
|
18
|
+
|
19
|
+
validates_presence_of :type # can't create this object, only child
|
23
20
|
|
24
|
-
validates :product, :presence => true
|
25
21
|
validates :name, :presence => true
|
26
|
-
validates_uniqueness_of :name, :scope => :product_id
|
22
|
+
validates_uniqueness_of :name, :scope => [:operatingsystem_id, :product_id]
|
27
23
|
validates_inclusion_of :content_type,
|
28
24
|
:in => TYPES,
|
29
25
|
:allow_blank => false,
|
@@ -31,40 +27,33 @@ module Content
|
|
31
27
|
|
32
28
|
scoped_search :on => [:name, :enabled], :complete_value => :true
|
33
29
|
scoped_search :in => :architecture, :on => :name, :rename => :architecture, :complete_value => :true
|
34
|
-
scoped_search :in => :
|
30
|
+
scoped_search :in => :operatingsystem, :on => :name, :rename => :os, :complete_value => :true
|
35
31
|
scoped_search :in => :product, :on => :name, :rename => :product, :complete_value => :true
|
36
32
|
|
37
|
-
# Repositories filtered by operating system architecture and environment.
|
38
|
-
# architecture_id is nil for noarch repositories.
|
39
|
-
scope :available_for_host, lambda { |host|
|
40
|
-
joins(:operatingsystems => :operatingsystem_repositories , :product => :environments).
|
41
|
-
where(:architecture_id => [nil, host.architecture_id],
|
42
|
-
:content_operatingsystem_repositories => { :operatingsystem_id => host.operatingsystem_id},
|
43
|
-
:content_environment_products => { :environment_id => host.environment_id }).
|
44
|
-
uniq}
|
45
|
-
|
46
|
-
#
|
47
|
-
scope :attached_to_host, lambda { |host|
|
48
|
-
where(:product_id => host.all_product_ids).available_for_host(host)
|
49
|
-
}
|
50
|
-
|
51
33
|
scope :kickstart, where(:content_type => KICKSTART_TYPE)
|
52
34
|
scope :yum, where(:content_type => YUM_TYPE)
|
53
35
|
|
54
|
-
def
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
def full_path
|
59
|
-
pulp_url = URI.parse(Setting.pulp_url)
|
60
|
-
scheme = (unprotected ? 'http' : 'https')
|
61
|
-
port = (pulp_url.port == 443 || pulp_url.port == 80 ? "" : ":#{pulp_url.port}")
|
62
|
-
"#{scheme}://#{pulp_url.host}#{port}#{REPO_PREFIX}#{relative_path}"
|
36
|
+
def content_types
|
37
|
+
TYPES
|
63
38
|
end
|
64
39
|
|
65
40
|
# The label is used as a repository label in a yum repo file.
|
66
41
|
def to_label
|
67
|
-
"#{
|
42
|
+
"#{entity_name}-#{name}".parameterize
|
43
|
+
end
|
44
|
+
|
45
|
+
#inhariters are expected to override this method
|
46
|
+
def entity_name
|
47
|
+
''
|
68
48
|
end
|
49
|
+
|
50
|
+
def publish content_view
|
51
|
+
repository_clones.create!(
|
52
|
+
:content_views => [content_view],
|
53
|
+
:name => self.name + "_clone",
|
54
|
+
:relative_path => "content_views/#{to_label}/#{Foreman.uuid}"
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
69
58
|
end
|
70
59
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Content
|
2
|
+
class RepositoryClone < ActiveRecord::Base
|
3
|
+
include Content::Orchestration::Pulp::Clone
|
4
|
+
|
5
|
+
REPO_PREFIX = '/pulp/repos/'
|
6
|
+
|
7
|
+
belongs_to :repository
|
8
|
+
has_many :content_view_repository_clones, :dependent => :destroy
|
9
|
+
has_many :content_views, :through => :content_view_repository_clones
|
10
|
+
before_destroy EnsureNotUsedBy.new(:content_views)
|
11
|
+
|
12
|
+
attr_accessible :description, :last_published, :name, :pulp_id, :relative_path, :status, :content_views
|
13
|
+
validate :relative_path, :repository_id, :presence => true
|
14
|
+
|
15
|
+
delegate :content_type, :architecture, :unprotected, :gpg_key, :product, :to => :repository
|
16
|
+
|
17
|
+
scope :for_content_views, lambda { |ids|
|
18
|
+
joins(:content_view_repository_clones).
|
19
|
+
where('content_content_view_repository_clones' => {:content_view_id => ids})
|
20
|
+
}
|
21
|
+
|
22
|
+
def full_path
|
23
|
+
pulp_url = URI.parse(Setting.pulp_url)
|
24
|
+
scheme = (unprotected ? 'http' : 'https')
|
25
|
+
port = (pulp_url.port == 443 || pulp_url.port == 80 ? "" : ":#{pulp_url.port}")
|
26
|
+
"#{scheme}://#{pulp_url.host}#{port}#{REPO_PREFIX}#{relative_path}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,15 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# Copyright 2013 Red Hat, Inc.
|
3
|
-
#
|
4
|
-
# This software is licensed to you under the GNU General Public
|
5
|
-
# License as published by the Free Software Foundation; either version
|
6
|
-
# 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
-
# There is NO WARRANTY for this software, express or implied,
|
8
|
-
# including the implied warranties of MERCHANTABILITY,
|
9
|
-
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
-
# have received a copy of GPLv2 along with this software; if not, see
|
11
|
-
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
-
|
13
1
|
module Content
|
14
2
|
module Validators
|
15
3
|
class ContentValidator < ActiveModel::EachValidator
|
@@ -1,15 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# Copyright 2013 Red Hat, Inc.
|
3
|
-
#
|
4
|
-
# This software is licensed to you under the GNU General Public
|
5
|
-
# License as published by the Free Software Foundation; either version
|
6
|
-
# 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
-
# There is NO WARRANTY for this software, express or implied,
|
8
|
-
# including the implied warranties of MERCHANTABILITY,
|
9
|
-
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
-
# have received a copy of GPLv2 along with this software; if not, see
|
11
|
-
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
-
|
13
1
|
module Content
|
14
2
|
module Validators
|
15
3
|
class DescriptionFormat < ActiveModel::EachValidator
|
@@ -1,15 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# Copyright 2013 Red Hat, Inc.
|
3
|
-
#
|
4
|
-
# This software is licensed to you under the GNU General Public
|
5
|
-
# License as published by the Free Software Foundation; either version
|
6
|
-
# 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
-
# There is NO WARRANTY for this software, express or implied,
|
8
|
-
# including the implied warranties of MERCHANTABILITY,
|
9
|
-
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
-
# have received a copy of GPLv2 along with this software; if not, see
|
11
|
-
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
-
|
13
1
|
module Content
|
14
2
|
module Validators
|
15
3
|
class NoTrailingSpace < ActiveModel::EachValidator
|
@@ -21,22 +21,4 @@ class Setting::Content< ::Setting
|
|
21
21
|
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.ensure_sync_notification
|
25
|
-
include Rails.application.routes.url_helpers
|
26
|
-
|
27
|
-
resource = Runcible::Resources::EventNotifier
|
28
|
-
url = events_repositories_url(:only_path => false, :host => Setting[:foreman_url])
|
29
|
-
type = '*' #resource::EventTypes::REPO_SYNC_COMPLETE
|
30
|
-
notifs = resource.list
|
31
|
-
|
32
|
-
#delete any similar tasks with the wrong url (in case it changed)
|
33
|
-
notifs.select { |n| n['event_types'] == [type] && n['notifier_config']['url'] != url }.each do |e|
|
34
|
-
resource.delete(e['id'])
|
35
|
-
end
|
36
|
-
|
37
|
-
#only create a notifier if one doesn't exist with the correct url
|
38
|
-
exists = notifs.select { |n| n['event_types'] == [type] && n['notifier_config']['url'] == url }
|
39
|
-
resource.create(resource::NotifierTypes::REST_API, { :url => url }, [type]) if exists.empty?
|
40
|
-
end
|
41
|
-
|
42
24
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Deface::Override.new(:virtual_path => "hosts/_form",
|
2
2
|
:name => "add_content_tab",
|
3
3
|
:insert_after => 'ul.nav > li a#params-tab',
|
4
|
-
:partial => 'content/
|
4
|
+
:partial => 'content/content_views/form_tab')
|
5
5
|
|
6
6
|
Deface::Override.new(:virtual_path => "hosts/_form",
|
7
7
|
:name => "add_content_tab_pane",
|
8
8
|
:insert_after => 'div.tab-pane#params',
|
9
|
-
:partial => 'content/
|
9
|
+
:partial => 'content/content_views/host_tab_pane')
|
@@ -6,4 +6,4 @@ Deface::Override.new(:virtual_path => "hostgroups/_form",
|
|
6
6
|
Deface::Override.new(:virtual_path => "hostgroups/_form",
|
7
7
|
:name => "add_content_tab_pane",
|
8
8
|
:insert_after => 'div.tab-pane#params',
|
9
|
-
:partial => 'content/products/hostgroup_tab_pane')
|
9
|
+
:partial => 'content/products/hostgroup_tab_pane')
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Content
|
2
|
+
class ContentViewFactory
|
3
|
+
include ActiveModel::Conversion
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
|
6
|
+
attr_accessor :type, :originator_id, :parent_cv, :product_cv, :os_cv
|
7
|
+
# create a content view of a single product
|
8
|
+
def self.create_product_content_view(product_id)
|
9
|
+
product = Product.find_by_id(product_id)
|
10
|
+
ContentView.new(:source_repositories => product.repositories, :originator => product)
|
11
|
+
end
|
12
|
+
|
13
|
+
# create a content view of an operating system
|
14
|
+
def self.create_os_content_view(operatingsystem_id)
|
15
|
+
os = Operatingsystem.find_by_id(operatingsystem_id)
|
16
|
+
ContentView.new(:source_repositories => os.repositories, :originator => os)
|
17
|
+
end
|
18
|
+
|
19
|
+
# create a composite content view of a hostgroup (the hostgroup may have a list of products) and a parent
|
20
|
+
# content view. The parent content view is one of the hostgroup parent content views.
|
21
|
+
# A hostgroup may have number of content views representing different versions of that hostgroup content.
|
22
|
+
def self.create_composite_content_view(options = {})
|
23
|
+
factory = new(options)
|
24
|
+
hostgroup = Hostgroup.find_by_id(factory.originator_id)
|
25
|
+
clone_ids = Content::RepositoryClone.for_content_views([factory.product_cv, factory.os_cv]).
|
26
|
+
pluck(:id)
|
27
|
+
ContentView.new(:source_repositories=> [], :originator => hostgroup,
|
28
|
+
:repository_clone_ids => clone_ids, :parent_id => factory.parent_cv)
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(attributes = {})
|
32
|
+
attributes.each do |name, value|
|
33
|
+
instance_variable_set("@#{name}", value) if respond_to?("#{name}".to_sym)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def persisted?
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Content::Pulp::EventHandler
|
2
|
+
attr_reader :type, :status
|
3
|
+
delegate :name, :to => :repo
|
4
|
+
delegate :logger, :to => :Rails
|
5
|
+
|
6
|
+
def initialize(pulp_id, params)
|
7
|
+
@pulp_id = pulp_id
|
8
|
+
@params = params
|
9
|
+
@type, @status = parse_type
|
10
|
+
return nil unless repo
|
11
|
+
log
|
12
|
+
update_state
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
attr_reader :pulp_id, :params
|
17
|
+
|
18
|
+
def repo
|
19
|
+
@repo ||= case type
|
20
|
+
when 'sync'
|
21
|
+
Content::Repository.where(:pulp_id => pulp_id).first
|
22
|
+
when 'promote'
|
23
|
+
Content::RepositoryClone.where(:pulp_id => pulp_id).first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def log
|
28
|
+
logger.info "Repository #{name} #{type} #{status}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_type
|
32
|
+
# converts repo.sync.start to ['sync','start']
|
33
|
+
params['event_type'].gsub(/^repo\./, '').split('.')
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_state
|
37
|
+
#nothing to do if we didnt finish a task
|
38
|
+
return unless status == 'finish'
|
39
|
+
|
40
|
+
case type
|
41
|
+
when 'sync'
|
42
|
+
repo.update_attribute(:last_sync, finished_at) if success?
|
43
|
+
when 'promote'
|
44
|
+
repo.update_attribute(:last_published, finished_at) if success?
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def success?
|
50
|
+
result == 'success'
|
51
|
+
end
|
52
|
+
|
53
|
+
def result
|
54
|
+
params['payload']['result']
|
55
|
+
end
|
56
|
+
|
57
|
+
def finished_at
|
58
|
+
Time.parse(params['payload']['completed'])
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
class Content::Pulp::Repository
|
2
|
+
PULP_SELECT_FIELDS = ['name', 'epoch', 'version', 'release', 'arch', 'checksumtype', 'checksum']
|
3
|
+
|
4
|
+
attr_reader :pulp_id, :content_type, :relative_path, :name, :description
|
5
|
+
delegate :logger, :to => :Rails
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def create(options = {})
|
10
|
+
new(options).create
|
11
|
+
end
|
12
|
+
|
13
|
+
def delete(pulp_id)
|
14
|
+
new(:pulp_id => pulp_id).delete
|
15
|
+
end
|
16
|
+
|
17
|
+
def sync(pulp_id)
|
18
|
+
new(:pulp_id => pulp_id).sync
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize options = {}
|
24
|
+
options.each do |k, v|
|
25
|
+
instance_variable_set("@#{k}", v) if respond_to?("#{k}".to_sym)
|
26
|
+
end
|
27
|
+
|
28
|
+
raise('must define pulp id') unless pulp_id
|
29
|
+
|
30
|
+
# initiate pulp connection
|
31
|
+
Content::Pulp::Configuration.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_with_distributor
|
35
|
+
create_repository [pulp_distributor]
|
36
|
+
end
|
37
|
+
|
38
|
+
def create
|
39
|
+
create_repository
|
40
|
+
end
|
41
|
+
|
42
|
+
def display_name
|
43
|
+
details['display_name']
|
44
|
+
end
|
45
|
+
|
46
|
+
def checksum_type
|
47
|
+
details['checksum_type']
|
48
|
+
end
|
49
|
+
|
50
|
+
def description
|
51
|
+
@description || details['description']
|
52
|
+
end
|
53
|
+
|
54
|
+
def counters
|
55
|
+
details['content_unit_counts']
|
56
|
+
end
|
57
|
+
|
58
|
+
def feed
|
59
|
+
@feed || importer['config']['feed_url']
|
60
|
+
end
|
61
|
+
|
62
|
+
def last_sync
|
63
|
+
importer['last_sync']
|
64
|
+
end
|
65
|
+
|
66
|
+
def last_publish
|
67
|
+
distributor['last_publish']
|
68
|
+
end
|
69
|
+
|
70
|
+
def auto_publish
|
71
|
+
@auto_publish.nil? ? distributor['auto_publish'] : @auto_publish
|
72
|
+
end
|
73
|
+
|
74
|
+
def protected
|
75
|
+
@protected.nil? ? distributor['protected'] : @protected
|
76
|
+
end
|
77
|
+
|
78
|
+
def reload!
|
79
|
+
@details = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def sync_status
|
83
|
+
status = Runcible::Extensions::Repository.sync_status(pulp_id)
|
84
|
+
Content::Pulp::RepositorySyncStatus.new(status.first) unless status.empty?
|
85
|
+
end
|
86
|
+
|
87
|
+
def sync_history
|
88
|
+
history = Runcible::Extensions::Repository.sync_history(pulp_id)
|
89
|
+
(history || []).map do |sync|
|
90
|
+
Content::Pulp::RepositorySyncHistory.new(sync)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def delete
|
95
|
+
Runcible::Resources::Repository.delete(pulp_id)
|
96
|
+
rescue RestClient::ResourceNotFound => e
|
97
|
+
true #not found is not a failure for delete
|
98
|
+
end
|
99
|
+
|
100
|
+
def sync
|
101
|
+
Runcible::Resources::Repository.sync(pulp_id)
|
102
|
+
end
|
103
|
+
|
104
|
+
def publish
|
105
|
+
Runcible::Extensions::Repository.publish_all(pulp_id)
|
106
|
+
end
|
107
|
+
|
108
|
+
def cancel_running_sync!
|
109
|
+
return if sync_status.blank? || sync_status.not_synced?
|
110
|
+
Runcible::Resources::Task.cancel(sync_status.task_id)
|
111
|
+
rescue RestClient::ResourceNotFound
|
112
|
+
# task already done, nothing to do here
|
113
|
+
end
|
114
|
+
|
115
|
+
# once we keep a list pulp servers, this should be done in create/destroy
|
116
|
+
def create_event_notifier
|
117
|
+
url = Rails.application.routes.url_helpers.
|
118
|
+
events_api_repositories_url(:only_path => false, :host => Setting[:foreman_url])
|
119
|
+
type = '*'
|
120
|
+
resource = Runcible::Resources::EventNotifier
|
121
|
+
notifs = resource.list
|
122
|
+
|
123
|
+
#only create a notifier if one doesn't exist with the correct url
|
124
|
+
exists = notifs.select { |n| n['event_types'] == [type] && n['notifier_config']['url'] == url }
|
125
|
+
resource.create(resource::NotifierTypes::REST_API, { :url => url }, [type]) if exists.empty?
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def create_repository pulp_distributors = []
|
132
|
+
defaults
|
133
|
+
Runcible::Extensions::Repository.create_with_importer_and_distributors(pulp_id,
|
134
|
+
pulp_importer,
|
135
|
+
pulp_distributors,
|
136
|
+
{ :display_name => relative_path || name,
|
137
|
+
:description => description })
|
138
|
+
rescue RestClient::BadRequest => e
|
139
|
+
raise parse_error(e)
|
140
|
+
end
|
141
|
+
|
142
|
+
def pulp_importer
|
143
|
+
options = {
|
144
|
+
:feed_url => feed
|
145
|
+
}
|
146
|
+
|
147
|
+
case content_type
|
148
|
+
when Content::Repository::YUM_TYPE, Content::Repository::KICKSTART_TYPE
|
149
|
+
Runcible::Extensions::YumImporter.new(options)
|
150
|
+
when Content::Repository::FILE_TYPE
|
151
|
+
Runcible::Extensions::IsoImporter.new(options)
|
152
|
+
else
|
153
|
+
raise "Unexpected repo type %s" % content_type
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def pulp_distributor
|
158
|
+
case content_type
|
159
|
+
when Content::Repository::YUM_TYPE, Content::Repository::KICKSTART_TYPE
|
160
|
+
Runcible::Extensions::YumDistributor.new(relative_path, protected, true,
|
161
|
+
{ :protected => protected, :id => pulp_id,
|
162
|
+
:auto_publish => auto_publish })
|
163
|
+
when Content::Repository::FILE_TYPE
|
164
|
+
dist = Runcible::Extensions::IsoDistributor.new(true, true)
|
165
|
+
dist.auto_publish = true
|
166
|
+
dist
|
167
|
+
else
|
168
|
+
raise "Unexpected repo type %s" % content_type
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def defaults
|
173
|
+
@protected = true if @protected.nil?
|
174
|
+
end
|
175
|
+
|
176
|
+
def importer
|
177
|
+
details['importers'].empty? ? {} : details['importers'].first
|
178
|
+
end
|
179
|
+
|
180
|
+
def distributor
|
181
|
+
details['distributors'].empty? ? {} : details['distributors'].first
|
182
|
+
end
|
183
|
+
|
184
|
+
def details
|
185
|
+
@details ||= Runcible::Resources::Repository.retrieve(pulp_id, { :details => true })
|
186
|
+
rescue RestClient::ResourceNotFound => e
|
187
|
+
logger.warn "Repo not found: #{parse_error(e)}"
|
188
|
+
{:state => 'not found'}
|
189
|
+
end
|
190
|
+
|
191
|
+
def state
|
192
|
+
return 'published' if last_publish.present?
|
193
|
+
return sync_status.state if sync_status.present?
|
194
|
+
return details[:state] if details[:state]
|
195
|
+
end
|
196
|
+
|
197
|
+
def parse_error exception
|
198
|
+
JSON.parse(exception.response)['error_message']
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Content::Pulp::RepositoryClone < Content::Pulp::Repository
|
2
|
+
PULP_SELECT_FIELDS = %w(name epoch version release arch checksumtype checksum)
|
3
|
+
|
4
|
+
def copy_from(src_repo_id)
|
5
|
+
# In order to reduce the memory usage of pulp during the copy process,
|
6
|
+
# include the fields that will uniquely identify the rpm. If no fields
|
7
|
+
# are listed, pulp will retrieve every field it knows about for the rpm
|
8
|
+
# (e.g. changelog, filelist...etc).
|
9
|
+
Runcible::Extensions::Rpm.copy(src_repo_id, pulp_id, { :fields => PULP_SELECT_FIELDS })
|
10
|
+
Runcible::Extensions::Distribution.copy(src_repo_id, pulp_id)
|
11
|
+
|
12
|
+
# Since the rpms will be copied above, during the copy of errata and package groups,
|
13
|
+
# include the copy_children flag to request that pulp skip copying them again.
|
14
|
+
Runcible::Extensions::Errata.copy(src_repo_id, pulp_id, { :copy_children => false })
|
15
|
+
Runcible::Extensions::PackageGroup.copy(src_repo_id, pulp_id, { :copy_children => false })
|
16
|
+
Runcible::Extensions::YumRepoMetadataFile.copy(src_repo_id, pulp_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def defaults; end
|
20
|
+
|
21
|
+
def pulp_importer
|
22
|
+
Runcible::Extensions::YumImporter.new
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Content::Pulp::RepositorySyncHistory
|
2
|
+
attr_reader :exception, :removed_count, :started, :completed, :summary,
|
3
|
+
:error_message, :added_count, :updated_count, :details, :result
|
4
|
+
|
5
|
+
def initialize(attrs)
|
6
|
+
attrs.each do |k, v|
|
7
|
+
instance_variable_set("@#{k}", v) if respond_to?("#{k}".to_sym)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def times
|
12
|
+
{
|
13
|
+
:comps => summary[:time_total_sec],
|
14
|
+
:errata => summary[:errata_time_total_sec],
|
15
|
+
:packages => summary[:packages][:time_total_sec]
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def metrics
|
20
|
+
{
|
21
|
+
:updated => updated_count,
|
22
|
+
:removed => removed_count,
|
23
|
+
:added => added_count,
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def status
|
28
|
+
{
|
29
|
+
:result => result,
|
30
|
+
:message => error_message || summary['error'],
|
31
|
+
:completed => completed
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|