foreman_content 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/app/assets/javascripts/content/content.js +23 -12
- data/app/assets/javascripts/content/repository.js +19 -0
- data/app/controllers/content/content_views_controller.rb +19 -6
- data/app/controllers/content/products_controller.rb +1 -1
- data/app/controllers/content/repositories_controller.rb +9 -3
- data/app/helpers/content/content_views_helper.rb +24 -4
- data/app/helpers/content/repositories_helper.rb +28 -0
- data/app/models/concerns/content/host_extensions.rb +1 -1
- data/app/models/concerns/content/operatingsystem_extensions.rb +1 -1
- data/app/models/concerns/content/orchestration/pulp.rb +1 -1
- data/app/models/concerns/content/orchestration/pulp/sync.rb +37 -2
- data/app/models/concerns/content/redhat_extensions.rb +19 -3
- data/app/models/concerns/content/repository_common.rb +13 -0
- data/app/models/content/content_view.rb +21 -15
- data/app/models/content/content_view_repository_clone.rb +2 -2
- data/app/models/content/product.rb +1 -1
- data/app/models/content/repository.rb +24 -8
- data/app/models/content/repository/operating_system.rb +11 -2
- data/app/models/content/repository/product.rb +8 -3
- data/app/models/content/repository_clone.rb +5 -10
- data/app/services/content/content_view_factory.rb +46 -25
- data/app/services/content/pulp/repository.rb +13 -0
- data/app/services/content/pulp/repository_sync_history.rb +8 -2
- data/app/views/content/content_views/{_step2.html.erb → _composite.html.erb} +1 -1
- data/app/views/content/content_views/_form.html.erb +17 -14
- data/app/views/content/content_views/index.html.erb +4 -3
- data/app/views/content/content_views/new.html.erb +1 -7
- data/app/views/content/content_views/show.erb +22 -0
- data/app/views/content/products/_form.html.erb +3 -9
- data/app/views/content/repositories/_fields.html.erb +9 -0
- data/app/views/content/repositories/_os_form.html.erb +6 -11
- data/app/views/content/repositories/_product_form.html.erb +7 -11
- data/app/views/content/repositories/_repository.html.erb +4 -0
- data/app/views/content/repositories/_sync_schedule.erb +10 -0
- data/app/views/content/repositories/edit.html.erb +2 -0
- data/app/views/content/repositories/index.html.erb +14 -16
- data/app/views/content/repositories/new.html.erb +2 -0
- data/app/views/content/repositories/show.html.erb +51 -37
- data/db/migrate/20130807121629_create_content_content_views.rb +1 -1
- data/db/migrate/20130828173006_change_content_view_index_name.rb +10 -0
- data/db/migrate/20130901070945_add_publish_boolean_to_content_repository.rb +6 -0
- data/db/migrate/20130902130445_change_repository_to_polymorphic.rb +42 -0
- data/db/migrate/20130902142326_add_polymorphic_repo_to_content_view_repository_clone.rb +8 -0
- data/lib/content/version.rb +1 -1
- metadata +14 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 316501d63ca9034ac6248b472b539ebd12313e41
|
4
|
+
data.tar.gz: 4771b0bdb3ec5e080a321e0e69ed28a5e13ae747
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac73329310ab942e6858b833bf4f9e112951b36f78a9bc5065506166dc3bbf79af922364939801e411ccc536775fb0edbe011e7c20cd88be4d622e100bf43d42
|
7
|
+
data.tar.gz: b49837ce5b77ed3443b7d93a56a2ab0fb140eddef907905cce0c7f75529ab89470cf6f86f76cbd293443d8c6fc9955c881a45a10d84b1d36d0a939fd241aa78b
|
data/README.md
CHANGED
@@ -29,6 +29,7 @@ touch tmp/restart.txt (if using passeger)
|
|
29
29
|
|
30
30
|
## Pulp
|
31
31
|
* enable oauth authentication
|
32
|
+
* make sure you have enough disk space! lots of GB to /var/lib/pulp and /var/lib/mongo
|
32
33
|
|
33
34
|
## UI config
|
34
35
|
|
@@ -50,6 +51,11 @@ You would see in the UI under More, a new sub menu called content, in it:
|
|
50
51
|
* Product - The actual product you are managing, for example CentOS 6
|
51
52
|
* Repository - list of repositories that belong to the above product, for
|
52
53
|
example, CentOS 6.4 + CentOS updates.
|
54
|
+
* Content View - a collection of cloned repositories
|
55
|
+
|
56
|
+
## Create a Product
|
57
|
+
|
58
|
+
If you are planning to sync non OS packages (e.g. 3rd party yum repo), you should first create a product, e.g. Foreman 1.2-stable, afterwards, you can add repositories to it.
|
53
59
|
|
54
60
|
## Syncing Repositories
|
55
61
|
|
@@ -63,8 +69,6 @@ of an Installation media.
|
|
63
69
|
* Architecture - type of files within the repo, usually X86_64 or noarch etc.
|
64
70
|
* Operating Systems - list of valid OS's that this repo applies to.
|
65
71
|
* Enabled - true / false
|
66
|
-
* Unprotected - weather pulp should expose this repo via http and https or just
|
67
|
-
over https.
|
68
72
|
* Product - the product from above.
|
69
73
|
* GPG key - not implemented
|
70
74
|
|
@@ -1,12 +1,23 @@
|
|
1
|
-
|
2
|
-
//
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
//
|
11
|
-
|
12
|
-
|
1
|
+
$(function () {
|
2
|
+
// Disable repository selection input based on checkbox
|
3
|
+
$('.repository_selection input:checkbox').click(function () {
|
4
|
+
var checked = $(this).is(':checked');
|
5
|
+
$(this).parent().find($(':input')).each (function ( index, input) {
|
6
|
+
$(input).attr('disabled', !checked);
|
7
|
+
});
|
8
|
+
|
9
|
+
});
|
10
|
+
// toggle repository ID's to send based on the repo type
|
11
|
+
$('.cv-repo-selection').change(function () {
|
12
|
+
enable_selected_repository(this);
|
13
|
+
});
|
14
|
+
$('.cv-repo-selection').change();
|
15
|
+
});
|
16
|
+
|
17
|
+
function enable_selected_repository(element) {
|
18
|
+
var select = $(element);
|
19
|
+
var id = select.attr('id').replace(/[^\d]/g, '');
|
20
|
+
var clone = select.val() == 'clone';
|
21
|
+
$('#clone-' + id).attr('disabled', !clone);
|
22
|
+
$('#latest-' + id).attr('disabled', clone);
|
23
|
+
};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
$(function () {
|
2
|
+
// Disable repository sync input based on checkbox
|
3
|
+
$('#content_repository_schedule').click(function () {
|
4
|
+
$('#sync_schedule_form select').attr('disabled', !$(this).is(':checked'));
|
5
|
+
});
|
6
|
+
// try to guess architecture based on the URL
|
7
|
+
$('#content_repository_feed').focusout(function() {
|
8
|
+
url = $(this).val();
|
9
|
+
if (url == undefined || url == '')
|
10
|
+
return;
|
11
|
+
|
12
|
+
$('#content_repository_architecture_id option').each (function ( index, option) {
|
13
|
+
if (url.match(option.text)) {
|
14
|
+
$('#content_repository_architecture_id').val(option.value);
|
15
|
+
return false;
|
16
|
+
}
|
17
|
+
})
|
18
|
+
});
|
19
|
+
});
|
@@ -5,16 +5,29 @@ module Content
|
|
5
5
|
|
6
6
|
def index
|
7
7
|
@content_views = ContentView.search_for(params[:search], :order => params[:order]).
|
8
|
-
|
9
|
-
@counter
|
8
|
+
paginate(:page => params[:page])
|
9
|
+
@counter = ContentViewRepositoryClone.where(:content_view_id => @content_views.map(&:id)).group(:content_view_id).count
|
10
10
|
|
11
11
|
end
|
12
12
|
|
13
|
+
def show
|
14
|
+
end
|
15
|
+
|
13
16
|
def new
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
options = if params[:product]
|
18
|
+
{:originator_id => params[:product], :originator_type => 'Content::Product'}
|
19
|
+
elsif params[:operatingsystem]
|
20
|
+
{:originator_id => params[:operatingsystem], :originator_type => 'Operatingsystem'}
|
21
|
+
elsif params[:hostgroup]
|
22
|
+
@hostgroup = Hostgroup.find_by_id(params[:hostgroup])
|
23
|
+
{:originator_id => params[:hostgroup], :originator_type => 'Hostgroup'}
|
24
|
+
elsif params[:content_content_view_factory]
|
25
|
+
params[:content_content_view_factory]
|
26
|
+
elsif params[:type].blank?
|
27
|
+
process_error(:error_msg => _('Must provide a type'))
|
28
|
+
end
|
29
|
+
@factory = ContentViewFactory.new(options || {})
|
30
|
+
@content_view = @factory.try(:content_view) if @factory.originator_id
|
18
31
|
end
|
19
32
|
|
20
33
|
def create
|
@@ -6,7 +6,7 @@ module Content
|
|
6
6
|
def index
|
7
7
|
@products = Product.search_for(params[:search], :order => params[:order]).
|
8
8
|
paginate(:page => params[:page])
|
9
|
-
@counter = Repository::Product.group(:
|
9
|
+
@counter = Repository::Product.group(:originator_id).where(:originator_id => @products.map(&:id)).count
|
10
10
|
end
|
11
11
|
|
12
12
|
def new
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Content
|
2
2
|
class RepositoriesController < ::ApplicationController
|
3
3
|
include Foreman::Controller::AutoCompleteSearch
|
4
|
-
before_filter :
|
4
|
+
before_filter :find_repo, :only => %w{show edit update destroy sync}
|
5
5
|
|
6
6
|
def index
|
7
7
|
@repositories = Repository.search_for(params[:search], :order => params[:order]).
|
8
|
-
paginate(:page => params[:page])
|
8
|
+
paginate(:page => params[:page])
|
9
9
|
end
|
10
10
|
|
11
11
|
def new
|
@@ -13,7 +13,7 @@ module Content
|
|
13
13
|
when "operatingsystem"
|
14
14
|
Repository::OperatingSystem.new(:unprotected => true)
|
15
15
|
when "product"
|
16
|
-
Repository::Product.new(:
|
16
|
+
Repository::Product.new(:originator_id => params[:product_id])
|
17
17
|
else
|
18
18
|
not_found
|
19
19
|
end
|
@@ -56,5 +56,11 @@ module Content
|
|
56
56
|
rescue => e
|
57
57
|
process_error(:error_msg => _("Failed to start sync for %s") % @repository.to_label)
|
58
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def find_repo
|
63
|
+
@repository = Content::Repository.find(params[:id])
|
64
|
+
end
|
59
65
|
end
|
60
66
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module Content
|
2
2
|
module ContentViewsHelper
|
3
3
|
|
4
|
-
def repositories
|
5
|
-
|
6
|
-
|
4
|
+
def repositories
|
5
|
+
cv_repos = @content_view.repository_clones + @content_view.repository_sources
|
6
|
+
|
7
|
+
if @content_view.new_record? && cv_repos.empty? # new form
|
8
|
+
@factory.repositories
|
7
9
|
else
|
8
|
-
|
10
|
+
cv_repos # edit or new after validation failure
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
@@ -17,5 +19,23 @@ module Content
|
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
22
|
+
def step?
|
23
|
+
if params[:type]
|
24
|
+
'step1'
|
25
|
+
elsif @hostgroup
|
26
|
+
'composite'
|
27
|
+
else
|
28
|
+
'form'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def options_for_type_selection repo
|
33
|
+
options = [[_('Clone (snapshot)'), 'clone']]
|
34
|
+
options << [_('Latest'),'latest'] if repo.kind_of?(Content::Repository) && repo.publish?
|
35
|
+
selected = 'clone' if @factory # default
|
36
|
+
selected ||= @content_view.repository_clone_ids.include?(repo.id) ? 'clone' : 'latest' # on validation error
|
37
|
+
options_for_select(options, selected)
|
38
|
+
end
|
39
|
+
|
20
40
|
end
|
21
41
|
end
|
@@ -6,5 +6,33 @@ module Content
|
|
6
6
|
time_ago_in_words(time) + ' ago'
|
7
7
|
end
|
8
8
|
|
9
|
+
def sync_schedule schedules
|
10
|
+
return _('None') if schedules.empty?
|
11
|
+
schedules.map{|s| s[:schedule]}.join(', ')
|
12
|
+
rescue => e
|
13
|
+
logger.warn _("Failed to fetch sync schedule: ") + e.to_s
|
14
|
+
_('unknown')
|
15
|
+
end
|
16
|
+
|
17
|
+
def time_selector f
|
18
|
+
html_options = { :class => 'span1', :disabled => f.object.schedule.blank? }
|
19
|
+
f.select(:hour, options_for_time(0..23), {}, html_options) +
|
20
|
+
f.select(:minute, options_for_time(0..59), {}, html_options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def sync_schedule_selector f
|
24
|
+
content_tag :div, :id => 'sync_schedule_form', :class => 'input-prepend input-append' do
|
25
|
+
f.select(:interval, [%w(Daily D), %w(Weekly W)], {}, { :disabled => f.object.schedule.blank? , :class => 'span1' }) +
|
26
|
+
content_tag(:span, :class => 'add-on') { '@' } +
|
27
|
+
time_selector(f)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def options_for_time(options)
|
34
|
+
options.map { |i| [sprintf("%02d", i), i] }
|
35
|
+
end
|
36
|
+
|
9
37
|
end
|
10
38
|
end
|
@@ -38,7 +38,7 @@ module Content::HostExtensions
|
|
38
38
|
|
39
39
|
Content::ContentView.joins(:available_content_views).
|
40
40
|
where(:content_available_content_views => {:environment_id => environment_id}).
|
41
|
-
where(:originator_type => 'Hostgroup', :originator_id => hostgroup_id).pluck(
|
41
|
+
where(:originator_type => 'Hostgroup', :originator_id => hostgroup_id).pluck('content_content_views.id')
|
42
42
|
end
|
43
43
|
|
44
44
|
def all_content_view_ids
|
@@ -2,7 +2,7 @@ module Content::OperatingsystemExtensions
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
included do
|
5
|
-
has_many :repositories, :class_name => 'Content::Repository'
|
5
|
+
has_many :repositories, :class_name => 'Content::Repository', :as => :originator
|
6
6
|
|
7
7
|
has_many :available_content_views, :dependent => :destroy, :class_name => 'Content::AvailableContentView'
|
8
8
|
has_many :content_views, :as => :originator, :class_name => 'Content::ContentView'
|
@@ -3,7 +3,7 @@ module Content::Orchestration::Pulp
|
|
3
3
|
include ::Orchestration
|
4
4
|
|
5
5
|
included do
|
6
|
-
delegate :sync_status, :sync, :counters, :sync_history, :state, :to => :repo
|
6
|
+
delegate :sync_status, :sync, :sync_schedule, :counters, :sync_history, :state, :to => :repo
|
7
7
|
end
|
8
8
|
|
9
9
|
def orchestration_errors?
|
@@ -5,6 +5,9 @@ module Content::Orchestration::Pulp::Sync
|
|
5
5
|
included do
|
6
6
|
after_validation :queue_pulp
|
7
7
|
before_destroy :queue_pulp_destroy unless Rails.env.test?
|
8
|
+
attr_accessor :interval, :hour, :minute, :schedule
|
9
|
+
validates :interval, :inclusion => { :in => %w(D W) }, :if => :schedule_sync?
|
10
|
+
validates :hour, :minute, :numericality => true, :if => :schedule_sync?
|
8
11
|
end
|
9
12
|
|
10
13
|
def last_sync
|
@@ -22,8 +25,14 @@ module Content::Orchestration::Pulp::Sync
|
|
22
25
|
logger.debug "Scheduling new Pulp Repository"
|
23
26
|
queue.create(:name => _("Create Pulp Repository for %s") % self, :priority => 10,
|
24
27
|
:action => [self, :set_pulp_repo])
|
28
|
+
logger.debug "Scheduling new Pulp Repository Sync"
|
25
29
|
queue.create(:name => _("Sync Pulp Repository %s") % self, :priority => 20,
|
26
30
|
:action => [self, :set_sync_pulp_repo])
|
31
|
+
if schedule_sync?
|
32
|
+
logger.debug "Scheduling Pulp Repository sync scheduler"
|
33
|
+
queue.create(:name => _("Sync Schedule Pulp Repository %s") % self, :priority => 30,
|
34
|
+
:action => [self, :set_sync_schedule_pulp_repo])
|
35
|
+
end
|
27
36
|
end
|
28
37
|
|
29
38
|
def queue_pulp_update
|
@@ -38,7 +47,7 @@ module Content::Orchestration::Pulp::Sync
|
|
38
47
|
end
|
39
48
|
|
40
49
|
def set_pulp_repo
|
41
|
-
repo.create
|
50
|
+
publish ? repo.create_with_distributor : repo.create
|
42
51
|
end
|
43
52
|
|
44
53
|
def del_pulp_repo
|
@@ -53,6 +62,14 @@ module Content::Orchestration::Pulp::Sync
|
|
53
62
|
repo.cancel_running_sync!
|
54
63
|
end
|
55
64
|
|
65
|
+
def set_sync_schedule_pulp_repo
|
66
|
+
repo.sync_schedule = sync_schedule_time
|
67
|
+
end
|
68
|
+
|
69
|
+
def del_sync_schedule_pulp_repo
|
70
|
+
repo.sync_schedule = nil
|
71
|
+
end
|
72
|
+
|
56
73
|
def repo_options
|
57
74
|
{
|
58
75
|
:pulp_id => pulp_repo_id,
|
@@ -61,10 +78,28 @@ module Content::Orchestration::Pulp::Sync
|
|
61
78
|
:feed => feed,
|
62
79
|
:content_type => content_type,
|
63
80
|
:protected => unprotected,
|
81
|
+
:relative_path => relative_path,
|
82
|
+
:auto_publish => publish
|
64
83
|
}
|
65
84
|
end
|
66
85
|
|
67
86
|
def repo
|
68
87
|
@repo ||= Content::Pulp::Repository.new(repo_options)
|
69
88
|
end
|
70
|
-
|
89
|
+
|
90
|
+
def relative_path
|
91
|
+
"#{entity_name}/#{name}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def schedule_sync?
|
95
|
+
schedule.present? && schedule != '0'
|
96
|
+
end
|
97
|
+
|
98
|
+
def sync_schedule_time
|
99
|
+
return if schedule.blank?
|
100
|
+
time = Time.parse("00:#{hour}:#{minute}").iso8601
|
101
|
+
repetition = "R1" # no limit of hour many syncs
|
102
|
+
"#{repetition}/#{time}/P1#{interval}"
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -6,7 +6,7 @@ module Content::RedhatExtensions
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def medium_uri_with_content_uri host, url = nil
|
9
|
-
if url.nil? && (full_path =
|
9
|
+
if url.nil? && (full_path = kickstart_repo(host).try(:full_path))
|
10
10
|
URI.parse(full_path)
|
11
11
|
else
|
12
12
|
medium_uri_without_content_uri(host, url)
|
@@ -16,7 +16,14 @@ module Content::RedhatExtensions
|
|
16
16
|
# return an array of repositories for kickstart script as additional repos
|
17
17
|
# to the kickstart main repo, this list will typically include updates and epel
|
18
18
|
def repos host
|
19
|
-
host.
|
19
|
+
yum_repos(host).map { |repo| format_repo(repo) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def boot_files_uri(medium, architecture)
|
23
|
+
Redhat::PXEFILES.values.collect do |img|
|
24
|
+
medium_vars_to_uri("#{medium.path}/#{pxedir}/#{img}", architecture.name, self)
|
25
|
+
URI.parse(interpolate_medium_vars(url, arch, os)).normalize
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
22
29
|
private
|
@@ -25,9 +32,18 @@ module Content::RedhatExtensions
|
|
25
32
|
{
|
26
33
|
:baseurl => repo.full_path,
|
27
34
|
:name => repo.to_label,
|
28
|
-
:description => repo.
|
35
|
+
:description => repo.description,
|
29
36
|
:enabled => repo.enabled,
|
30
37
|
:gpgcheck => !!repo.gpg_key
|
31
38
|
}
|
32
39
|
end
|
40
|
+
|
41
|
+
def kickstart_repo host
|
42
|
+
host.attached_repositories.detect{|r| r.content_type == Content::Repository::KICKSTART_TYPE}
|
43
|
+
end
|
44
|
+
|
45
|
+
def yum_repos host
|
46
|
+
host.attached_repositories.select{|r| r.content_type == Content::Repository::YUM_TYPE}
|
47
|
+
end
|
48
|
+
|
33
49
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Content::RepositoryCommon
|
2
|
+
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
REPO_PREFIX = '/pulp/repos/'
|
6
|
+
|
7
|
+
def full_path
|
8
|
+
pulp_url = URI.parse(Setting.pulp_url)
|
9
|
+
scheme = (unprotected ? 'http' : 'https')
|
10
|
+
port = (pulp_url.port == 443 || pulp_url.port == 80 ? "" : ":#{pulp_url.port}")
|
11
|
+
"#{scheme}://#{pulp_url.host}#{port}#{REPO_PREFIX}#{relative_path}"
|
12
|
+
end
|
13
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Content
|
2
2
|
class ContentView < ActiveRecord::Base
|
3
3
|
has_ancestry :orphan_strategy => :rootify
|
4
|
+
attr_accessor :repository_ids_to_clone
|
4
5
|
|
5
6
|
belongs_to :originator, :polymorphic => true
|
6
7
|
has_many :available_content_views, :dependent => :destroy
|
@@ -10,18 +11,23 @@ module Content
|
|
10
11
|
has_many :content_view_hosts, :dependent => :destroy, :uniq => true, :foreign_key => :content_view_id, :class_name => 'Content::ContentViewHost'
|
11
12
|
has_many :hosts, :through => :content_view_hosts
|
12
13
|
|
14
|
+
before_destroy :clean_unused_clone_repos
|
13
15
|
has_many :content_view_repository_clones, :dependent => :destroy
|
14
|
-
|
15
|
-
has_many :
|
16
|
+
|
17
|
+
has_many :repository_clones, :through => :content_view_repository_clones,
|
18
|
+
:source => :repository, :source_type => 'Content::RepositoryClone'
|
19
|
+
|
20
|
+
has_many :repository_sources, :through => :content_view_repository_clones,
|
21
|
+
:source => :repository, :source_type => 'Content::Repository'
|
16
22
|
|
17
23
|
scope :hostgroups, where(:originator_type => 'Hostgroup')
|
18
24
|
scope :products, where(:originator_type => 'Content::Product')
|
19
25
|
scope :operatingsystem, where(:originator_type => 'Operatingsystem')
|
20
26
|
|
21
|
-
|
22
|
-
before_destroy :clean_unused_clone_repos
|
27
|
+
after_create :clone_repos
|
23
28
|
|
24
29
|
validates_presence_of :name
|
30
|
+
validates_uniqueness_of :name, :scope => [:originator_id, :originator_type]
|
25
31
|
|
26
32
|
# special relationships needed for search with polymorphic associations
|
27
33
|
belongs_to :search_hostgroups, :class_name => 'Hostgroup', :foreign_key => :originator_id,
|
@@ -38,28 +44,28 @@ module Content
|
|
38
44
|
scoped_search :in => :search_hostgroups, :on => :label, :complete_value => true,
|
39
45
|
:rename => :hostgroup, :only_explicit => true
|
40
46
|
|
41
|
-
attr_accessor :source_repositories
|
42
|
-
|
43
47
|
def to_label
|
44
48
|
name || "#{originator.to_label} - #{DateTime.now.strftime("%m/%d/%Y")}".parameterize
|
45
49
|
end
|
46
50
|
|
51
|
+
private
|
52
|
+
|
47
53
|
def clone_repos
|
48
|
-
return unless
|
49
|
-
Repository.where(:id =>
|
50
|
-
repository.
|
54
|
+
return unless repository_ids_to_clone
|
55
|
+
Repository.where(:id => repository_ids_to_clone).each do |repository|
|
56
|
+
repository.clone self
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
54
|
-
private
|
55
|
-
|
56
60
|
def clean_unused_clone_repos
|
57
|
-
current_repos = Content::ContentViewRepositoryClone.where(:content_view_id => id).pluck(:
|
58
|
-
used_repos
|
59
|
-
where(:
|
60
|
-
where(['content_view_id IS NOT ?', id]).pluck(:
|
61
|
+
current_repos = Content::ContentViewRepositoryClone.where(:content_view_id => id, :repository_type => 'Content::RepositoryClone').pluck(:repository_id)
|
62
|
+
used_repos = Content::ContentViewRepositoryClone.
|
63
|
+
where(:repository_id => current_repos).
|
64
|
+
where(['content_view_id IS NOT ?', id]).pluck(:repository_id)
|
61
65
|
|
62
66
|
repos_to_delete = current_repos - used_repos
|
67
|
+
logger.debug('All Cloned repositories are used elsewhere, nothing to do') if repos_to_delete.empty?
|
68
|
+
logger.debug("Clone Repos IDS: #{repos_to_delete.join(', ')} are unused - deleting...") if repos_to_delete.any?
|
63
69
|
Content::RepositoryClone.destroy(repos_to_delete) if repos_to_delete.any?
|
64
70
|
end
|
65
71
|
end
|