1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
module HammerCLICsv
|
13
|
class CsvCommand
|
14
|
class ProductsCommand < BaseCommand
|
15
|
command_name 'products'
|
16
|
desc 'import or export products'
|
17
|
|
18
|
LABEL = 'Label'
|
19
|
ORGANIZATION = 'Organization'
|
20
|
REPOSITORY = 'Repository'
|
21
|
REPOSITORY_TYPE = 'Repository Type'
|
22
|
REPOSITORY_URL = 'Repository Url'
|
23
|
DESCRIPTION = 'Description'
|
24
|
|
25
|
def export
|
26
|
CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => false}) do |csv|
|
27
|
csv << [NAME, COUNT, LABEL, ORGANIZATION, REPOSITORY, REPOSITORY_TYPE, REPOSITORY_URL]
|
28
|
@api.resource(:organizations)\
|
29
|
.call(:index, {
|
30
|
:per_page => 999999
|
31
|
})['results'].each do |organization|
|
32
|
@api.resource(:products)\
|
33
|
.call(:index, {
|
34
|
'per_page' => 999999,
|
35
|
'enabled' => true,
|
36
|
'organization_id' => foreman_organization(:name => organization['name'])
|
37
|
})['results'].each do |product|
|
38
|
product['repositories'].each do |repository|
|
39
|
repository_type = repository['product_type'] == 'custom' ? 'Custom' : 'Red Hat'
|
40
|
repository_type += " #{repository['content_type'].capitalize}"
|
41
|
csv << [product['name'], 1, product['label'], organization['name'],
|
42
|
repository['name'], repository_type, repository['url']]
|
43
|
end
|
44
|
end
|
45
|
end
|
46
|
end
|
47
|
end
|
48
|
|
49
|
def import
|
50
|
@existing_products = {}
|
51
|
@existing_repositories = {}
|
52
|
|
53
|
thread_import do |line|
|
54
|
create_products_from_csv(line)
|
55
|
end
|
56
|
end
|
57
|
|
58
|
def create_products_from_csv(line)
|
59
|
if !@existing_products[line[ORGANIZATION]]
|
60
|
@existing_products[line[ORGANIZATION]] = {}
|
61
|
@api.resource(:products)\
|
62
|
.call(:index, {
|
63
|
'per_page' => 999999,
|
64
|
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
65
|
'enabled' => true
|
66
|
})['results'].each do |product|
|
67
|
@existing_products[line[ORGANIZATION]][product['name']] = product['id']
|
68
|
|
69
|
@api.resource(:repositories)\
|
70
|
.call(:index, {
|
71
|
'page_size' => 999999, 'paged' => true,
|
72
|
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
73
|
'product_id' => product['id'],
|
74
|
'enabled' => true,
|
75
|
'library' => true
|
76
|
})['results'].each do |repository|
|
77
|
@existing_repositories[line[ORGANIZATION] + product['name']] ||= {}
|
78
|
@existing_repositories[line[ORGANIZATION] + product['name']][repository['label']] = repository['id']
|
79
|
end
|
80
|
end
|
81
|
end
|
82
|
|
83
|
line[COUNT].to_i.times do |number|
|
84
|
name = namify(line[NAME], number)
|
85
|
product_id = @existing_products[line[ORGANIZATION]][name]
|
86
|
if product_id.nil?
|
87
|
print "Creating product '#{name}'..." if option_verbose?
|
88
|
if line[REPOSITORY_TYPE] =~ /Red Hat/
|
89
|
raise "Red Hat product '#{name}' does not exist in '#{line[ORGANIZATION]}'"
|
90
|
end
|
91
|
|
92
|
product_id = @api.resource(:products)\
|
93
|
.call(:create, {
|
94
|
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
95
|
'name' => name
|
96
|
})['id']
|
97
|
@existing_products[line[ORGANIZATION]][name] = product_id
|
98
|
else
|
99
|
|
100
|
print "Updating product '#{name}'..." if option_verbose?
|
101
|
end
|
102
|
@existing_repositories[line[ORGANIZATION] + name] = {}
|
103
|
print "done\n" if option_verbose?
|
104
|
|
105
|
repository_name = namify(line[REPOSITORY], number)
|
106
|
|
107
|
if !@existing_repositories[line[ORGANIZATION] + name][repository_name]
|
108
|
@api.resource(:repositories)\
|
109
|
.call(:index, {
|
110
|
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
111
|
'library' => true,
|
112
|
'all' => false,
|
113
|
'product_id' => product_id
|
114
|
})['results'].each do |repository|
|
115
|
@existing_repositories[line[ORGANIZATION] + name][repository['name']] = repository
|
116
|
end
|
117
|
end
|
118
|
|
119
|
repository = @existing_repositories[line[ORGANIZATION] + name][repository_name]
|
120
|
if !repository
|
121
|
raise "Red Hat product '#{name}' does not have repository '#{repository_name}'" if line[REPOSITORY_TYPE] =~ /Red Hat/
|
122
|
|
123
|
print "Creating repository '#{repository_name}' in product '#{name}'..." if option_verbose?
|
124
|
repository = @api.resource(:repositories)\
|
125
|
.call(:create, {
|
126
|
'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
|
127
|
'name' => repository_name,
|
128
|
'label' => labelize(repository_name),
|
129
|
'product_id' => product_id,
|
130
|
'url' => line[REPOSITORY_URL],
|
131
|
'content_type' => content_type(line[REPOSITORY_TYPE])
|
132
|
})
|
133
|
@existing_repositories[line[ORGANIZATION] + name][line[LABEL]] = repository
|
134
|
puts 'done' if option_verbose?
|
135
|
end
|
136
|
|
137
|
print "Sync'ing repository '#{repository_name}' in product '#{name}'..." if option_verbose?
|
138
|
if repository['sync_state'] == 'finished'
|
139
|
puts 'already done' if option_verbose?
|
140
|
else
|
141
|
if line[REPOSITORY_TYPE] =~ /Red Hat/
|
142
|
print 'skipping Red Hat repo sync... so slow!... '
|
143
|
else
|
144
|
sync_repository(line, repository)
|
145
|
end
|
146
|
print "done\n" if option_verbose?
|
147
|
end
|
148
|
end
|
149
|
|
150
|
rescue RuntimeError => e
|
151
|
raise "#{e}\n #{line}"
|
152
|
end
|
153
|
|
154
|
private
|
155
|
|
156
|
def content_type(repository_type)
|
157
|
case repository_type
|
158
|
when /yum/i
|
159
|
'yum'
|
160
|
when /puppet/i
|
161
|
'puppet'
|
162
|
else
|
163
|
raise "Unrecognized repository type '#{repository_type}'"
|
164
|
end
|
165
|
end
|
166
|
|
167
|
def sync_repository(line, repository)
|
168
|
|
169
|
args = %W{ repository synchronize
|
170
|
--id #{ repository['id'] }
|
171
|
--organization-id #{ foreman_organization(:name => line[ORGANIZATION]) } }
|
172
|
hammer.run(args)
|
173
|
|
174
|
rescue RuntimeError => e
|
175
|
raise "#{e}\n #{line}"
|
176
|
end
|
177
|
end
|
178
|
end
|
179
|
end
|