hammer_cli_import 0.10.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +115 -0
- data/channel_data_pretty.json +10316 -0
- data/config/import/config_macros.yml +16 -0
- data/config/import/interview_answers.yml +13 -0
- data/config/import/role_map.yml +10 -0
- data/config/import.yml +2 -0
- data/lib/hammer_cli_import/activationkey.rb +156 -0
- data/lib/hammer_cli_import/all.rb +253 -0
- data/lib/hammer_cli_import/asynctasksreactor.rb +187 -0
- data/lib/hammer_cli_import/autoload.rb +27 -0
- data/lib/hammer_cli_import/base.rb +585 -0
- data/lib/hammer_cli_import/configfile.rb +392 -0
- data/lib/hammer_cli_import/contenthost.rb +243 -0
- data/lib/hammer_cli_import/contentview.rb +198 -0
- data/lib/hammer_cli_import/csvhelper.rb +68 -0
- data/lib/hammer_cli_import/deltahash.rb +86 -0
- data/lib/hammer_cli_import/fixtime.rb +27 -0
- data/lib/hammer_cli_import/hostcollection.rb +52 -0
- data/lib/hammer_cli_import/import.rb +31 -0
- data/lib/hammer_cli_import/importtools.rb +351 -0
- data/lib/hammer_cli_import/organization.rb +110 -0
- data/lib/hammer_cli_import/persistentmap.rb +225 -0
- data/lib/hammer_cli_import/repository.rb +91 -0
- data/lib/hammer_cli_import/repositoryenable.rb +250 -0
- data/lib/hammer_cli_import/templatesnippet.rb +67 -0
- data/lib/hammer_cli_import/user.rb +155 -0
- data/lib/hammer_cli_import/version.rb +25 -0
- data/lib/hammer_cli_import.rb +53 -0
- metadata +117 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
require 'uri'
|
22
|
+
|
23
|
+
module HammerCLIImport
|
24
|
+
class ImportCommand
|
25
|
+
class RepositoryImportCommand < BaseCommand
|
26
|
+
extend ImportTools::Repository::Extend
|
27
|
+
include ImportTools::Repository::Include
|
28
|
+
|
29
|
+
command_name 'repository'
|
30
|
+
reportname = 'repositories'
|
31
|
+
desc "Import repositories (from spacewalk-report #{reportname})."
|
32
|
+
|
33
|
+
csv_columns 'id', 'org_id', 'repo_label', 'source_url', 'repo_type'
|
34
|
+
|
35
|
+
persistent_maps :organizations, :repositories, :products
|
36
|
+
|
37
|
+
add_repo_options
|
38
|
+
|
39
|
+
def mk_product_hash(data, product_name)
|
40
|
+
{
|
41
|
+
:name => product_name,
|
42
|
+
:organization_id => get_translated_id(:organizations, data['org_id'].to_i)
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def mk_repo_hash(data, product_id)
|
47
|
+
{
|
48
|
+
:name => data['repo_label'],
|
49
|
+
:product_id => product_id,
|
50
|
+
:url => data['source_url'],
|
51
|
+
:content_type => data['repo_type']
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def import_single_row(data)
|
56
|
+
begin
|
57
|
+
product_name = URI.parse(data['source_url']).host.split('.').last(2).join('.').upcase
|
58
|
+
rescue
|
59
|
+
error 'Skipping ' + data['repo_label'] + ' ' + to_singular(:repositories) + ' import, invalid source_url.'
|
60
|
+
report_summary :skipped, :repositories
|
61
|
+
return
|
62
|
+
end
|
63
|
+
product_hash = mk_product_hash(data, product_name)
|
64
|
+
composite_id = [data['org_id'].to_i, product_name]
|
65
|
+
product_id = create_entity(:products, product_hash, composite_id)['id']
|
66
|
+
repo_hash = mk_repo_hash data, product_id
|
67
|
+
|
68
|
+
repo = create_entity(:repositories, repo_hash, data['id'].to_i)
|
69
|
+
with_synced_repo(repo)
|
70
|
+
end
|
71
|
+
|
72
|
+
def delete_single_row(data)
|
73
|
+
# check just becasue we're calling get_translated_id
|
74
|
+
unless @pm[:repositories][data['id'].to_i]
|
75
|
+
info to_singular(:repositories).capitalize + ' with id ' + data['id'] + " wasn't imported. Skipping deletion."
|
76
|
+
return
|
77
|
+
end
|
78
|
+
# find out product id
|
79
|
+
repo_id = get_translated_id(:repositories, data['id'].to_i)
|
80
|
+
product_id = lookup_entity(:repositories, repo_id)['product']['id']
|
81
|
+
# delete repo
|
82
|
+
delete_entity(:repositories, data['id'].to_i)
|
83
|
+
# delete its product, if it's not associated with any other repositories
|
84
|
+
product = lookup_entity(:products, product_id, true)
|
85
|
+
|
86
|
+
delete_entity_by_import_id(:products, product_id) if product['repository_count'] == 0
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,250 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
require 'hammer_cli_import'
|
22
|
+
require 'json'
|
23
|
+
|
24
|
+
module HammerCLIImport
|
25
|
+
class ImportCommand
|
26
|
+
class RepositoryEnableCommand < BaseCommand
|
27
|
+
extend ImportTools::Repository::Extend
|
28
|
+
include ImportTools::Repository::Include
|
29
|
+
include ImportTools::ContentView::Include
|
30
|
+
|
31
|
+
command_name 'repository-enable'
|
32
|
+
reportname = 'channels'
|
33
|
+
desc "Enable any Red Hat repositories accessible to any Organization (from spacewalk-report #{reportname})."
|
34
|
+
|
35
|
+
option ['--repository-map'],
|
36
|
+
'FILE_NAME',
|
37
|
+
'JSON file mapping channel-labels to repository information',
|
38
|
+
:default => File.expand_path('../../channel_data_pretty.json', File.dirname(__FILE__)) do |filename|
|
39
|
+
raise ArgumentError, "Channel-to-repository-map file #{filename} does not exist" unless File.exist? filename
|
40
|
+
filename
|
41
|
+
end
|
42
|
+
|
43
|
+
option ['--dry-run'],
|
44
|
+
:flag,
|
45
|
+
'Only show the repositories that would be enabled',
|
46
|
+
:default => false
|
47
|
+
|
48
|
+
add_repo_options
|
49
|
+
|
50
|
+
# Required or BaseCommand gets angry at you
|
51
|
+
csv_columns 'channel_id', 'channel_label', 'channel_name', 'number_of_packages', 'org_id'
|
52
|
+
persistent_maps :organizations, :products,
|
53
|
+
:redhat_repositories, :redhat_content_views, :repositories
|
54
|
+
|
55
|
+
# BaseCommand will read our channel-csv for us
|
56
|
+
def import_single_row(row)
|
57
|
+
handle_row(row, true)
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete_single_row(row)
|
61
|
+
handle_row(row, false)
|
62
|
+
end
|
63
|
+
|
64
|
+
def handle_row(row, enable)
|
65
|
+
if row['org_id'] # Not a Red Hat channel
|
66
|
+
info " Skipping #{row['channel_label']} in organization #{row['org_id']}"
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
# read_channel_mapping_data will be called only once per subcommand
|
71
|
+
@channel_to_repo ||= read_channel_mapping_data(option_repository_map)
|
72
|
+
channel_label = row['channel_label']
|
73
|
+
channel_id = row['channel_id'].to_i
|
74
|
+
repo_set_info = @channel_to_repo[channel_label]
|
75
|
+
|
76
|
+
if repo_set_info.nil? # not mapped channel (like proxy)
|
77
|
+
info " Skipping nontransferable #{row['channel_label']}"
|
78
|
+
return
|
79
|
+
end
|
80
|
+
|
81
|
+
# rely on we see only products in imported organizations
|
82
|
+
get_cache(:products).each do |product_id, product|
|
83
|
+
rsets = list_server_entities(:repository_sets, {:product_id => product_id}, true)
|
84
|
+
|
85
|
+
rsets.each do |rs|
|
86
|
+
next if repo_set_info['set-url'] != rs['contentUrl'] &&
|
87
|
+
repo_set_info['set-url'].gsub('$releasever', repo_set_info['version']) != rs['contentUrl']
|
88
|
+
|
89
|
+
product_org = lookup_entity_in_cache(:organizations, {'label' => product['organization']['label']})
|
90
|
+
composite_rhcv_id = [get_original_id(:organizations, product_org['id']), channel_id]
|
91
|
+
if enable
|
92
|
+
# Turn on the specific repository
|
93
|
+
rh_repo = enable_repos(product_org, product_id, rs['id'], repo_set_info, row)
|
94
|
+
next if rh_repo.nil? || option_dry_run?
|
95
|
+
|
96
|
+
# Finally, if requested, kick off a sync
|
97
|
+
with_synced_repo rh_repo do
|
98
|
+
cv = create_entity(
|
99
|
+
:redhat_content_views,
|
100
|
+
{
|
101
|
+
:organization_id => product_org['id'],
|
102
|
+
:name => row['channel_name'],
|
103
|
+
:description => 'Red Hat channel migrated from Satellite 5',
|
104
|
+
:repository_ids => [rh_repo['id']]
|
105
|
+
},
|
106
|
+
composite_rhcv_id)
|
107
|
+
begin
|
108
|
+
publish_content_view(cv['id'], :redhat_content_views)
|
109
|
+
rescue RestClient::Exception => e
|
110
|
+
msg = JSON.parse(e.response)['displayMessage']
|
111
|
+
error "#{e.http_code} trying to publish content-view #{row['channel_name']} :\n #{msg}\n"
|
112
|
+
next
|
113
|
+
end
|
114
|
+
end
|
115
|
+
else
|
116
|
+
if @pm[:redhat_content_views][composite_rhcv_id]
|
117
|
+
delete_content_view(get_translated_id(:redhat_content_views, composite_rhcv_id), :redhat_content_views)
|
118
|
+
end
|
119
|
+
disable_repos(product_org, product_id, rs['id'], repo_set_info, channel_label)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Hydrate the channel-to-repository-data mapping struct
|
126
|
+
def read_channel_mapping_data(filename)
|
127
|
+
channel_map = {}
|
128
|
+
|
129
|
+
File.open(filename, 'r') do |f|
|
130
|
+
json = f.read
|
131
|
+
channel_map = JSON.parse(json)
|
132
|
+
end
|
133
|
+
return channel_map
|
134
|
+
end
|
135
|
+
|
136
|
+
# this way we're able to get from the server, what repositories within a repository-set are enabled
|
137
|
+
def find_repo_in_reposet(product_id, repo_set_id, info)
|
138
|
+
repos = api_call(
|
139
|
+
:repository_sets,
|
140
|
+
:available_repositories,
|
141
|
+
'product_id' => product_id,
|
142
|
+
'id' => repo_set_id)
|
143
|
+
|
144
|
+
if repos['results'][0] && repos['results'][0]['substitutions'].size == 1
|
145
|
+
return lookup_entity_in_array(repos['results'],
|
146
|
+
{'substitutions' => {'basearch' => info['arch']}})
|
147
|
+
end
|
148
|
+
return lookup_entity_in_array(repos['results'],
|
149
|
+
{'substitutions' => {'basearch' => info['arch'], 'releasever' => info['version']}})
|
150
|
+
end
|
151
|
+
|
152
|
+
# and this is quite a pain - to get real ids of the enabled repositories
|
153
|
+
# search according to the repository name
|
154
|
+
def find_enabled_repo(product_id, repo_set_id, repo_name)
|
155
|
+
reposet = api_call(
|
156
|
+
:repository_sets,
|
157
|
+
:show,
|
158
|
+
'product_id' => product_id,
|
159
|
+
'id' => repo_set_id)
|
160
|
+
|
161
|
+
enabled_repo = lookup_entity_in_array(reposet['repositories'], {'name' => repo_name})
|
162
|
+
info "Repository '#{repo_name}' already enabled as #{enabled_repo['id']}."
|
163
|
+
return lookup_entity(:redhat_repositories, enabled_repo['id'])
|
164
|
+
end
|
165
|
+
|
166
|
+
# Given a repository-set and a channel-to-repo info for that channel,
|
167
|
+
# enable the correct repository
|
168
|
+
def enable_repos(org, prod_id, repo_set_id, info, row)
|
169
|
+
channel_label = row['channel_label']
|
170
|
+
channel_id = row ['channel_id'].to_i
|
171
|
+
repo = find_repo_in_reposet(prod_id, repo_set_id, info)
|
172
|
+
if repo.nil?
|
173
|
+
warn "Repository #{info['url']} for (#{info['arch']} x #{info['version']}) not found!"
|
174
|
+
return
|
175
|
+
end
|
176
|
+
|
177
|
+
return find_enabled_repo(prod_id, repo_set_id, repo['repo_name']) if repo['enabled']
|
178
|
+
|
179
|
+
info "Enabling #{info['url']} for channel #{channel_label} in org #{org['id']}"
|
180
|
+
begin
|
181
|
+
unless option_dry_run?
|
182
|
+
rc = api_call(
|
183
|
+
:repository_sets,
|
184
|
+
:enable,
|
185
|
+
'product_id' => prod_id,
|
186
|
+
'id' => repo_set_id,
|
187
|
+
'basearch' => repo['substitutions'].key?('basearch') ? info['arch'] : '',
|
188
|
+
'releasever' => repo['substitutions'].key?('releasever') ? info['version'] : '')
|
189
|
+
|
190
|
+
original_org_id = get_original_id(:organizations, org['id'])
|
191
|
+
map_entity(:redhat_repositories, [original_org_id, channel_id], rc['input']['repository']['id'])
|
192
|
+
# store to cache (using lookup_entity, because :redhat_repositories api
|
193
|
+
# does not return full repository hash)
|
194
|
+
return lookup_entity(:redhat_repositories, rc['input']['repository']['id'], true)
|
195
|
+
end
|
196
|
+
rescue RestClient::Exception => e
|
197
|
+
if e.http_code == 409
|
198
|
+
info '...already enabled.'
|
199
|
+
return find_enabled_repo(prod_id, repo_set_id, repo['repo_name'])
|
200
|
+
else
|
201
|
+
error "...repository enablement failed with error '#{e.http_code}, #{e.message}' - skipping."
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def disable_repos(org, prod_id, repo_set_id, info, channel_label)
|
207
|
+
repo = lookup_entity_in_cache(
|
208
|
+
:redhat_repositories,
|
209
|
+
{
|
210
|
+
'content_id' => repo_set_id,
|
211
|
+
'organization' => {'label' => org['label']}
|
212
|
+
})
|
213
|
+
# find the repo from reposet to get also the substitutions
|
214
|
+
# otherwise it's not possible to disable certain repositories
|
215
|
+
repo = find_repo_in_reposet(prod_id, repo_set_id, info) if repo
|
216
|
+
unless repo
|
217
|
+
error "Unknown repository (#{channel_label} equivalent) to disable."
|
218
|
+
return
|
219
|
+
end
|
220
|
+
info "Disabling #{info['url']} for channel #{channel_label} in org #{org['id']}"
|
221
|
+
begin
|
222
|
+
unless option_dry_run?
|
223
|
+
rc = api_call(
|
224
|
+
:repository_sets,
|
225
|
+
:disable,
|
226
|
+
'product_id' => prod_id,
|
227
|
+
'id' => repo_set_id,
|
228
|
+
'basearch' => repo['substitutions'].key?('basearch') ? info['arch'] : '',
|
229
|
+
'releasever' => repo['substitutions'].key?('releasever') ? info['version'] : '')
|
230
|
+
|
231
|
+
unmap_entity(:redhat_repositories, rc['input']['repository']['id'])
|
232
|
+
get_cache(:redhat_repositories).delete(rc['input']['repository']['id'])
|
233
|
+
return rc['input']['repository']
|
234
|
+
end
|
235
|
+
rescue RestClient::Exception => e
|
236
|
+
if e.http_code == 404
|
237
|
+
error '...no such repository to disable.'
|
238
|
+
else
|
239
|
+
error "...repository disable failed with error '#{e.http_code}, #{e.message}' - skipping."
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def post_import(_file)
|
245
|
+
HammerCLI::EX_OK
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
require 'apipie-bindings'
|
22
|
+
|
23
|
+
module HammerCLIImport
|
24
|
+
class ImportCommand
|
25
|
+
class TemplateSnippetImportCommand < BaseCommand
|
26
|
+
command_name 'template-snippet'
|
27
|
+
reportname = 'kickstart-scripts'
|
28
|
+
desc "Import template snippets (from spacewalk-report #{reportname})."
|
29
|
+
|
30
|
+
csv_columns \
|
31
|
+
'id', 'org_id', 'script_name', 'kickstart_label', 'position',
|
32
|
+
'script_type', 'chroot', 'interpreter', 'data'
|
33
|
+
|
34
|
+
persistent_maps :organizations, :template_snippets
|
35
|
+
|
36
|
+
def mk_snippet_hash(data)
|
37
|
+
template = "%#{data['script_type']}"
|
38
|
+
template += ' --nochroot' if data['chroot'] == 'N'
|
39
|
+
template += " --interpreter #{data['interpreter']}" if data['interpreter']
|
40
|
+
template += "\n"
|
41
|
+
template += data['data'] if data['data']
|
42
|
+
template += "\n" unless template.end_with? "\n"
|
43
|
+
template += "%end\n"
|
44
|
+
{
|
45
|
+
:name => "#{data['kickstart_label']}-#{data['org_id']}-" \
|
46
|
+
"#{data['position']}-#{data['script_name']}-#{data['script_type']}",
|
47
|
+
:template => template,
|
48
|
+
# nowadays templates do not get associated with an organization
|
49
|
+
# :organization_id => get_translated_id(:organizations, data['org_id'].to_i),
|
50
|
+
:snippet => true,
|
51
|
+
# audit_comment does not get stored anyway
|
52
|
+
:audit_comment => ''
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def import_single_row(data)
|
57
|
+
snippet = mk_snippet_hash data
|
58
|
+
create_entity(:template_snippets, snippet, data['id'].to_i)
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete_single_row(data)
|
62
|
+
delete_entity(:template_snippets, data['id'].to_i)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,155 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
require 'yaml'
|
22
|
+
|
23
|
+
module HammerCLIImport
|
24
|
+
class ImportCommand
|
25
|
+
class UserImportCommand < BaseCommand
|
26
|
+
command_name 'user'
|
27
|
+
reportname = 'users'
|
28
|
+
desc "Import Users (from spacewalk-report #{reportname})."
|
29
|
+
|
30
|
+
option ['--new-passwords'], 'FILE_NAME', 'Output for new passwords' do |filename|
|
31
|
+
raise ArgumentError, "File #{filename} already exists" if File.exist? filename
|
32
|
+
filename
|
33
|
+
end
|
34
|
+
|
35
|
+
option ['--merge-users'], :flag, 'Merge pre-created users (except admin)', :default => false
|
36
|
+
|
37
|
+
option ['--role-mapping'], 'FILE_NAME',
|
38
|
+
'Mapping of Satellite-5 role names to Satellite-6 defined roles',
|
39
|
+
:default => '/etc/hammer/cli.modules.d/import/role_map.yml'
|
40
|
+
|
41
|
+
validate_options do
|
42
|
+
any(:option_new_passwords, :option_delete).required
|
43
|
+
end
|
44
|
+
|
45
|
+
csv_columns 'organization_id', 'user_id', 'username',\
|
46
|
+
'last_name', 'first_name', 'email', 'role', 'active'
|
47
|
+
|
48
|
+
persistent_maps :organizations, :users
|
49
|
+
|
50
|
+
# Override so we can read the role-map *once*, not *once per user*
|
51
|
+
def first_time_only
|
52
|
+
if File.exist? option_role_mapping
|
53
|
+
@role_map = YAML.load_file(option_role_mapping)
|
54
|
+
else
|
55
|
+
warn "Role-mapping file #{option_role_mapping} not found, no roles will be assigned"
|
56
|
+
end
|
57
|
+
return 'loaded'
|
58
|
+
end
|
59
|
+
|
60
|
+
def genpw(username)
|
61
|
+
username + '_' + (0...8).collect { ('a'..'z').to_a[rand(26)] }.join
|
62
|
+
end
|
63
|
+
|
64
|
+
# Admin-flag should be set if any Sat5-role has '_admin_' in its map
|
65
|
+
def admin?(data)
|
66
|
+
return false if @role_map.nil?
|
67
|
+
|
68
|
+
roles = split_multival(data['role'], false)
|
69
|
+
is_admin = false
|
70
|
+
roles.each do |r|
|
71
|
+
is_admin ||= (@role_map[r.gsub(' ', '-')].include? '_admin_')
|
72
|
+
end
|
73
|
+
return is_admin
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return list-of-role-ids that match any sat5-role associated with this user
|
77
|
+
# XXX: Role-api doesn't return what it needs to
|
78
|
+
# Until BZ 1102816 is fixed, this doesn't work
|
79
|
+
# It does serve to show the infrastructure/approach required
|
80
|
+
def role_ids_for(data)
|
81
|
+
role_list = []
|
82
|
+
return role_list if @role_map.nil?
|
83
|
+
|
84
|
+
users_roles = split_multival(data['role'], false)
|
85
|
+
fm_roles = api_call(:roles, :index, 'per_page' => 999999)['results']
|
86
|
+
debug fm_roles.inspect
|
87
|
+
users_roles.each do |s5r|
|
88
|
+
fm_roles.each do |fr|
|
89
|
+
role_list << fr['id'] if @role_map[s5r.gsub(' ', '-')].include? fr['name']
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
return role_list
|
94
|
+
end
|
95
|
+
|
96
|
+
def mk_user_hash(data)
|
97
|
+
username = data['username']
|
98
|
+
username = 'sat5_admin' if username == 'admin'
|
99
|
+
{
|
100
|
+
:login => username,
|
101
|
+
:firstname => data['first_name'],
|
102
|
+
:lastname => data['last_name'],
|
103
|
+
:mail => data['email'],
|
104
|
+
:auth_source_id => 1,
|
105
|
+
:password => genpw(username),
|
106
|
+
:organization_ids => [get_translated_id(:organizations, data['organization_id'].to_i)],
|
107
|
+
:location_ids => [],
|
108
|
+
:admin => admin?(data),
|
109
|
+
:role_ids => role_ids_for(data)
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def post_import(_)
|
114
|
+
return if @new_passwords.nil? || @new_passwords.empty?
|
115
|
+
CSVHelper.csv_write_hashes option_new_passwords, [:mail, :login, :password], @new_passwords
|
116
|
+
end
|
117
|
+
|
118
|
+
def import_single_row(data)
|
119
|
+
@first_time ||= first_time_only
|
120
|
+
user = mk_user_hash data
|
121
|
+
new_user = true
|
122
|
+
|
123
|
+
user_id = data['user_id'].to_i
|
124
|
+
login = user[:login]
|
125
|
+
|
126
|
+
unless @pm[:users][user_id].nil?
|
127
|
+
info "User #{login} already imported."
|
128
|
+
return
|
129
|
+
end
|
130
|
+
|
131
|
+
if option_merge_users?
|
132
|
+
existing_user = lookup_entity_in_cache :users, 'login' => user[:login]
|
133
|
+
|
134
|
+
unless existing_user.nil?
|
135
|
+
info "User with login #{login} already exists. Associating..."
|
136
|
+
map_entity :users, user_id, existing_user['id']
|
137
|
+
new_user = false
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
return unless new_user
|
142
|
+
|
143
|
+
create_entity :users, user, user_id
|
144
|
+
|
145
|
+
@new_passwords ||= []
|
146
|
+
@new_passwords << {:login => user[:login], :password => user[:password], :mail => user[:mail]}
|
147
|
+
end
|
148
|
+
|
149
|
+
def delete_single_row(data)
|
150
|
+
delete_entity(:users, data['user_id'].to_i)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
module HammerCLIImport
|
21
|
+
def self.version
|
22
|
+
@version ||= Gem::Version.new('0.10.21')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This file is part of hammer-cli-import.
|
5
|
+
#
|
6
|
+
# hammer-cli-import is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# hammer-cli-import is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with hammer-cli-import. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hammer_cli'
|
21
|
+
|
22
|
+
module HammerCLIImport
|
23
|
+
# def self.exception_handler_class
|
24
|
+
# HammerCLIImport::ExceptionHandler
|
25
|
+
# end
|
26
|
+
|
27
|
+
require 'hammer_cli_import/asynctasksreactor'
|
28
|
+
require 'hammer_cli_import/csvhelper'
|
29
|
+
require 'hammer_cli_import/deltahash'
|
30
|
+
require 'hammer_cli_import/fixtime'
|
31
|
+
require 'hammer_cli_import/importtools'
|
32
|
+
require 'hammer_cli_import/persistentmap'
|
33
|
+
|
34
|
+
require 'hammer_cli_import/base'
|
35
|
+
require 'hammer_cli_import/import'
|
36
|
+
|
37
|
+
require 'hammer_cli_import/all'
|
38
|
+
require 'hammer_cli_import/activationkey'
|
39
|
+
require 'hammer_cli_import/configfile'
|
40
|
+
require 'hammer_cli_import/contentview'
|
41
|
+
require 'hammer_cli_import/contenthost'
|
42
|
+
require 'hammer_cli_import/hostcollection'
|
43
|
+
require 'hammer_cli_import/organization'
|
44
|
+
require 'hammer_cli_import/repository'
|
45
|
+
require 'hammer_cli_import/repositoryenable'
|
46
|
+
require 'hammer_cli_import/templatesnippet.rb'
|
47
|
+
require 'hammer_cli_import/user'
|
48
|
+
require 'hammer_cli_import/version'
|
49
|
+
|
50
|
+
# This has to be after all subcommands
|
51
|
+
require 'hammer_cli_import/autoload'
|
52
|
+
end
|
53
|
+
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=ruby
|