foreman_content 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -1
  3. data/app/controllers/content/api/repositories_controller.rb +3 -5
  4. data/app/controllers/content/content_views_controller.rb +48 -0
  5. data/app/controllers/content/products_controller.rb +1 -1
  6. data/app/controllers/content/repositories_controller.rb +9 -6
  7. data/app/helpers/content/content_views_helper.rb +21 -0
  8. data/app/helpers/content/products_helper.rb +9 -0
  9. data/app/helpers/content/repositories_helper.rb +3 -49
  10. data/app/models/concerns/content/environment_extensions.rb +2 -2
  11. data/app/models/concerns/content/home_helper.rb +1 -0
  12. data/app/models/concerns/content/host_extensions.rb +17 -1
  13. data/app/models/concerns/content/hostgroup_extensions.rb +14 -0
  14. data/app/models/concerns/content/operatingsystem_extensions.rb +6 -5
  15. data/app/models/concerns/content/orchestration/pulp/clone.rb +77 -0
  16. data/app/models/concerns/content/orchestration/pulp/sync.rb +70 -0
  17. data/app/models/concerns/content/orchestration/pulp.rb +25 -0
  18. data/app/models/content/available_content_view.rb +12 -0
  19. data/app/models/content/content_view.rb +66 -0
  20. data/app/models/content/content_view_host.rb +9 -0
  21. data/app/models/content/content_view_repository_clone.rb +5 -0
  22. data/app/models/content/host_product.rb +0 -11
  23. data/app/models/content/hostgroup_product.rb +0 -11
  24. data/app/models/content/operatingsystem_repository.rb +0 -11
  25. data/app/models/content/product.rb +6 -5
  26. data/app/models/content/repository/operating_system.rb +14 -0
  27. data/app/models/content/repository/product.rb +21 -0
  28. data/app/models/content/repository.rb +28 -39
  29. data/app/models/content/repository_clone.rb +29 -0
  30. data/app/models/content/validators/content_validator.rb +0 -12
  31. data/app/models/content/validators/description_format.rb +0 -12
  32. data/app/models/content/validators/no_trailing_space.rb +0 -12
  33. data/app/models/setting/content.rb +0 -18
  34. data/app/overrides/{add_host_conent_tab.rb → add_host_content_tab.rb} +2 -2
  35. data/app/overrides/{add_hostgroup_conent_tab.rb → add_hostgroup_content_tab.rb} +1 -1
  36. data/app/services/content/content_view_factory.rb +41 -0
  37. data/app/services/content/{pulp_configuration.rb → pulp/configuration.rb} +1 -1
  38. data/app/services/content/pulp/event_handler.rb +61 -0
  39. data/app/services/content/pulp/repository.rb +200 -0
  40. data/app/services/content/pulp/repository_clone.rb +24 -0
  41. data/app/services/content/pulp/repository_sync_history.rb +35 -0
  42. data/app/services/content/pulp/repository_sync_status.rb +30 -0
  43. data/app/views/content/content_views/_form.html.erb +49 -0
  44. data/app/views/content/content_views/_form_tab.html.erb +3 -0
  45. data/app/views/content/content_views/_host_tab_pane.html.erb +5 -0
  46. data/app/views/content/content_views/_step1.html.erb +18 -0
  47. data/app/views/content/content_views/_step2.html.erb +16 -0
  48. data/app/views/content/content_views/edit.html.erb +5 -0
  49. data/app/views/content/content_views/index.html.erb +27 -0
  50. data/app/views/content/content_views/new.html.erb +11 -0
  51. data/app/views/content/products/_form.html.erb +2 -13
  52. data/app/views/content/products/_form_tab.html.erb +3 -3
  53. data/app/views/content/products/_hostgroup_tab_pane.html.erb +2 -2
  54. data/app/views/content/products/index.html.erb +6 -1
  55. data/app/views/content/repositories/_os_form.html.erb +22 -0
  56. data/app/views/content/repositories/{_form.html.erb → _product_form.html.erb} +4 -6
  57. data/app/views/content/repositories/edit.html.erb +5 -2
  58. data/app/views/content/repositories/index.html.erb +12 -9
  59. data/app/views/content/repositories/new.html.erb +5 -2
  60. data/app/views/content/repositories/show.html.erb +9 -16
  61. data/config/environment.rb +0 -0
  62. data/config/routes.rb +6 -0
  63. data/db/migrate/20130702140034_create_content_repositories.rb +6 -2
  64. data/db/migrate/20130722084911_create_content_operatingsystem_repositories.rb +1 -1
  65. data/db/migrate/20130807121629_create_content_content_views.rb +15 -0
  66. data/db/migrate/20130807123220_create_content_available_content_views.rb +11 -0
  67. data/db/migrate/20130812154754_create_content_content_view_hosts.rb +9 -0
  68. data/db/migrate/20130813110455_create_content_repository_clones.rb +17 -0
  69. data/db/migrate/20130825145431_create_content_content_view_repository_clones.rb +12 -0
  70. data/lib/content/engine.rb +2 -0
  71. data/lib/content/version.rb +1 -1
  72. data/test/fixtures/content/repository_clones.yml +21 -0
  73. data/test/unit/content/repository_clone_test.rb +7 -0
  74. metadata +44 -17
  75. data/app/models/concerns/content/custom_repository_paths.rb +0 -29
  76. data/app/models/content/environment_product.rb +0 -19
  77. data/app/models/content/orchestration/pulp.rb +0 -93
  78. data/app/models/content/product_operatingsystem.rb +0 -19
  79. data/app/models/content/remote/pulp/repository.rb +0 -48
  80. data/app/overrides/add_os_conent_tab.rb +0 -9
  81. data/app/services/content/pulp_event_handler.rb +0 -25
  82. data/app/views/content/products/_host_tab_pane.html.erb +0 -5
  83. data/app/views/content/products/_operatingsystem_tab_pane.html.erb +0 -5
  84. data/db/migrate/20130717032320_create_content_environments_products.rb +0 -9
  85. 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 :environment_products, :dependent => :destroy, :uniq=>true
7
- has_many :environments, :through => :environment_products
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,14 @@
1
+ module Content
2
+ class Repository::OperatingSystem < Repository
3
+
4
+ validates_presence_of :operatingsystem
5
+
6
+ def self.model_name
7
+ Repository.model_name
8
+ end
9
+
10
+ def entity_name
11
+ operatingsystem.to_label
12
+ end
13
+ end
14
+ end
@@ -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 CustomRepositoryPaths
7
- include Content::Remote::Pulp::Repository
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
- REPO_PREFIX = '/pulp/repos/'
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 :operatingsystem_repositories, :dependent => :destroy, :uniq => true
22
- has_many :operatingsystems, :through => :operatingsystem_repositories
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 => :operatingsystems, :on => :name, :rename => :os, :complete_value => :true
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 update_cache
55
- nil
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
- "#{product.name}-#{name}".parameterize
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/products/form_tab')
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/products/host_tab_pane')
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
@@ -1,7 +1,7 @@
1
1
  require 'runcible'
2
2
  require 'uri'
3
3
 
4
- class Content::PulpConfiguration
4
+ class Content::Pulp::Configuration
5
5
  def initialize options = {}
6
6
  Runcible::Base.config = runcible_config.merge(options)
7
7
  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