hammer_cli_csv 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +15 -0
  2. data/lib/hammer_cli_csv.rb +48 -0
  3. data/lib/hammer_cli_csv/activation_keys.rb +170 -0
  4. data/lib/hammer_cli_csv/architectures.rb +95 -0
  5. data/lib/hammer_cli_csv/base.rb +706 -0
  6. data/lib/hammer_cli_csv/compute_profiles.rb +94 -0
  7. data/lib/hammer_cli_csv/compute_resources.rb +92 -0
  8. data/lib/hammer_cli_csv/content_hosts.rb +357 -0
  9. data/lib/hammer_cli_csv/content_view_filters.rb +158 -0
  10. data/lib/hammer_cli_csv/content_views.rb +86 -0
  11. data/lib/hammer_cli_csv/csv.rb +23 -0
  12. data/lib/hammer_cli_csv/domains.rb +103 -0
  13. data/lib/hammer_cli_csv/exception_handler.rb +53 -0
  14. data/lib/hammer_cli_csv/host_collections.rb +108 -0
  15. data/lib/hammer_cli_csv/hosts.rb +118 -0
  16. data/lib/hammer_cli_csv/import.rb +82 -0
  17. data/lib/hammer_cli_csv/installation_medias.rb +88 -0
  18. data/lib/hammer_cli_csv/lifecycle_environments.rb +116 -0
  19. data/lib/hammer_cli_csv/locations.rb +84 -0
  20. data/lib/hammer_cli_csv/operating_systems.rb +95 -0
  21. data/lib/hammer_cli_csv/organizations.rb +107 -0
  22. data/lib/hammer_cli_csv/partition_tables.rb +98 -0
  23. data/lib/hammer_cli_csv/products.rb +179 -0
  24. data/lib/hammer_cli_csv/provisioning_templates.rb +96 -0
  25. data/lib/hammer_cli_csv/puppet_environments.rb +105 -0
  26. data/lib/hammer_cli_csv/puppet_facts.rb +99 -0
  27. data/lib/hammer_cli_csv/puppet_reports.rb +244 -0
  28. data/lib/hammer_cli_csv/reports.rb +91 -0
  29. data/lib/hammer_cli_csv/roles.rb +115 -0
  30. data/lib/hammer_cli_csv/smart_proxies.rb +88 -0
  31. data/lib/hammer_cli_csv/subnets.rb +121 -0
  32. data/lib/hammer_cli_csv/subscriptions.rb +135 -0
  33. data/lib/hammer_cli_csv/users.rb +133 -0
  34. data/lib/hammer_cli_csv/version.rb +16 -0
  35. data/test/activation_keys_test.rb +17 -0
  36. data/test/apipie_resource_mock.rb +77 -0
  37. data/test/config.template.yml +17 -0
  38. data/test/csv_test_helper.rb +65 -0
  39. data/test/data/activation-keys.csv +119 -0
  40. data/test/data/architectures.csv +5 -0
  41. data/test/data/content-hosts.csv +4 -0
  42. data/test/data/content-view-filters.csv +2 -0
  43. data/test/data/content-views.csv +6 -0
  44. data/test/data/domains.csv +8 -0
  45. data/test/data/host-collections.csv +16 -0
  46. data/test/data/hosts.csv +12 -0
  47. data/test/data/installation-medias.csv +7 -0
  48. data/test/data/lifecycle-environments.csv +6 -0
  49. data/test/data/locations.csv +10 -0
  50. data/test/data/operating-systems.csv +16 -0
  51. data/test/data/organizations.csv +5 -0
  52. data/test/data/partition-tables.csv +187 -0
  53. data/test/data/products.csv +19 -0
  54. data/test/data/puppet-environments.csv +6 -0
  55. data/test/data/puppet-facts.csv +9 -0
  56. data/test/data/reports.csv +4 -0
  57. data/test/data/roles.csv +159 -0
  58. data/test/data/smart-proxies.csv +2 -0
  59. data/test/data/subscriptions.csv +19 -0
  60. data/test/data/users.csv +119 -0
  61. data/test/helpers/command.rb +67 -0
  62. data/test/helpers/resource_disabled.rb +69 -0
  63. data/test/hosts_test.rb +47 -0
  64. data/test/organizations_test.rb +74 -0
  65. data/test/roles_test.rb +39 -0
  66. data/test/setup_test.rb +164 -0
  67. data/test/systems_test.rb +71 -0
  68. data/test/users_test.rb +35 -0
  69. metadata +174 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzY3ZmEyZWZkYzk3MTA0NDAzMDNkNzIxYTRhNDc5ZmJhYWVjNDQ5MA==
5
+ data.tar.gz: !binary |-
6
+ MjBjNWJhOTBhOTE1YTU2MDI3YTAwYTRhMWI4OWJmNDQxMjY5ZmI0OQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YWJjZDUxZDZiZjMwOTZiN2JlOWYwZmI0MTk0YTQwN2Y2OTYxMTdlYzc3Njlj
10
+ ZTkyNThkZjJiMzM0OTMzYTgzYWZkNjBhNDk1Y2MyMmY0M2U2MzZjYTYwMzY3
11
+ YjY0NzViZWZhNTAyNDY1NzBlNWUxYWZkMDA5MjgyMWFlZGRmYTE=
12
+ data.tar.gz: !binary |-
13
+ Njg1OTg0NWMxNzRiODNkYzM4NDdhMDcyMmIzMTE2YzliNzc5ZTE0YTE3MWU3
14
+ ZjNhZGUyYTk0YjBlZTkzMTg2MzhmYjMzMDQwNDY1MzhmNWYxOWU5NDBiZjBl
15
+ MWNlYWI0MjA0MzRjYmVkNmYxZWIxZTM4MjE3OWMyOGQ1ZDIwNmQ=
@@ -0,0 +1,48 @@
1
+ # Copyright 2013-2014 Red Hat, Inc.
2
+ #
3
+ # This software is licensed to you under the GNU General Public
4
+ # License as published by the Free Software Foundation; either version
5
+ # 2 of the License (GPLv2) or (at your option) any later version.
6
+ # There is NO WARRANTY for this software, express or implied,
7
+ # including the implied warranties of MERCHANTABILITY,
8
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
9
+ # have received a copy of GPLv2 along with this software; if not, see
10
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11
+
12
+ require 'hammer_cli'
13
+ require 'hammer_cli/exit_codes'
14
+
15
+ module HammerCLICsv
16
+ require 'hammer_cli_csv/base'
17
+ require 'hammer_cli_csv/exception_handler'
18
+
19
+ require 'hammer_cli_csv/csv'
20
+ require 'hammer_cli_csv/activation_keys'
21
+ require 'hammer_cli_csv/architectures'
22
+ require 'hammer_cli_csv/compute_profiles'
23
+ require 'hammer_cli_csv/compute_resources'
24
+ require 'hammer_cli_csv/content_hosts'
25
+ require 'hammer_cli_csv/content_views'
26
+ require 'hammer_cli_csv/content_view_filters'
27
+ require 'hammer_cli_csv/domains'
28
+ require 'hammer_cli_csv/host_collections'
29
+ require 'hammer_cli_csv/hosts'
30
+ require 'hammer_cli_csv/import'
31
+ require 'hammer_cli_csv/installation_medias'
32
+ require 'hammer_cli_csv/lifecycle_environments'
33
+ require 'hammer_cli_csv/locations'
34
+ require 'hammer_cli_csv/operating_systems'
35
+ require 'hammer_cli_csv/organizations'
36
+ require 'hammer_cli_csv/partition_tables'
37
+ require 'hammer_cli_csv/products'
38
+ require 'hammer_cli_csv/provisioning_templates'
39
+ require 'hammer_cli_csv/puppet_environments'
40
+ require 'hammer_cli_csv/puppet_facts'
41
+ require 'hammer_cli_csv/puppet_reports'
42
+ require 'hammer_cli_csv/reports'
43
+ require 'hammer_cli_csv/roles'
44
+ require 'hammer_cli_csv/smart_proxies'
45
+ require 'hammer_cli_csv/subnets'
46
+ require 'hammer_cli_csv/subscriptions'
47
+ require 'hammer_cli_csv/users'
48
+ end
@@ -0,0 +1,170 @@
1
+ # Copyright 2013-2014 Red Hat, Inc.
2
+ #
3
+ # This software is licensed to you under the GNU General Public
4
+ # License as published by the Free Software Foundation; either version
5
+ # 2 of the License (GPLv2) or (at your option) any later version.
6
+ # There is NO WARRANTY for this software, express or implied,
7
+ # including the implied warranties of MERCHANTABILITY,
8
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
9
+ # have received a copy of GPLv2 along with this software; if not, see
10
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11
+
12
+ module HammerCLICsv
13
+ class CsvCommand
14
+ class ActivationKeysCommand < BaseCommand
15
+ command_name 'activation-keys'
16
+ desc 'import or export activation keys'
17
+
18
+ ORGANIZATION = 'Organization'
19
+ DESCRIPTION = 'Description'
20
+ LIMIT = 'Limit'
21
+ ENVIRONMENT = 'Environment'
22
+ CONTENTVIEW = 'Content View'
23
+ SYSTEMGROUPS = 'System Groups'
24
+ SUBSCRIPTIONS = 'Subscriptions'
25
+
26
+ def export
27
+ CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => false}) do |csv|
28
+ csv << [NAME, COUNT, ORGANIZATION, DESCRIPTION, LIMIT, ENVIRONMENT, CONTENTVIEW,
29
+ SYSTEMGROUPS, SUBSCRIPTIONS]
30
+ @api.resource(:organizations)
31
+ .call(:index, {
32
+ :per_page => 999999
33
+ })['results'].each do |organization|
34
+ @api.resource(:activation_keys)
35
+ .call(:index, {
36
+ 'per_page' => 999999,
37
+ 'organization_id' => organization['id']
38
+ })['results'].each do |activationkey|
39
+ puts "Writing activation key '#{activationkey['name']}'" if option_verbose?
40
+ name = namify(activationkey['name'])
41
+ count = 1
42
+ description = activationkey['description']
43
+ limit = activationkey['usage_limit'].to_i < 0 ? 'Unlimited' : sytemgroup['usage_limit']
44
+ environment = activationkey['environment']['label']
45
+ contentview = activationkey['content_view']['name']
46
+ hostcollections = export_column(activationkey, 'systemGroups', 'name')
47
+ subscriptions = CSV.generate do |column|
48
+ column << @api.resource(:subscriptions).call(:index, {
49
+ 'activation_key_id' => activationkey['id']
50
+ })['results'].collect do |subscription|
51
+ amount = subscription['amount'] == 0 ? 'Automatic' : subscription['amount']
52
+ "#{amount}|#{subscription['product_name']}"
53
+ end
54
+ end
55
+ subscriptions.delete!("\n")
56
+ csv << [name, count, organization['label'], description, limit, environment, contentview,
57
+ hostcollections, subscriptions]
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def import
64
+ @existing = {}
65
+
66
+ thread_import do |line|
67
+ create_activationkeys_from_csv(line)
68
+ end
69
+ end
70
+
71
+ def create_activationkeys_from_csv(line)
72
+ if !@existing[line[ORGANIZATION]]
73
+ @existing[line[ORGANIZATION]] = {}
74
+ @api.resource(:activation_keys)
75
+ .call(:index, {
76
+ 'per_page' => 999999,
77
+ 'organization_id' => foreman_organization(:name => line[ORGANIZATION])
78
+ })['results'].each do |activationkey|
79
+ @existing[line[ORGANIZATION]][activationkey['name']] = activationkey['id'] if activationkey
80
+ end
81
+ end
82
+
83
+ line[COUNT].to_i.times do |number|
84
+ name = namify(line[NAME], number)
85
+
86
+ if !@existing[line[ORGANIZATION]].include? name
87
+ print "Creating activation key '#{name}'..." if option_verbose?
88
+ activationkey = @api.resource(:activation_keys)
89
+ .call(:create, {
90
+ 'name' => name,
91
+ 'environment_id' => lifecycle_environment(line[ORGANIZATION],
92
+ :name => line[ENVIRONMENT]),
93
+ 'content_view_id' => katello_contentview(line[ORGANIZATION],
94
+ :name => line[CONTENTVIEW]),
95
+ 'description' => line[DESCRIPTION],
96
+ 'usage_limit' => usage_limit(line[LIMIT])
97
+ })
98
+ @existing[line[ORGANIZATION]][activationkey['name']] = activationkey['id']
99
+ else
100
+ print "Updating activation key '#{name}'..." if option_verbose?
101
+ activationkey = @api.resource(:activation_keys)
102
+ .call(:update, {
103
+ 'id' => @existing[line[ORGANIZATION]][name],
104
+ 'name' => name,
105
+ 'environment_id' => lifecycle_environment(line[ORGANIZATION],
106
+ :name => line[ENVIRONMENT]),
107
+ 'content_view_id' => katello_contentview(line[ORGANIZATION],
108
+ :name => line[CONTENTVIEW]),
109
+ 'description' => line[DESCRIPTION],
110
+ 'usage_limit' => usage_limit(line[LIMIT])
111
+ })
112
+ end
113
+
114
+ update_subscriptions(activationkey, line)
115
+ update_groups(activationkey, line)
116
+
117
+ puts 'done' if option_verbose?
118
+ end
119
+ end
120
+
121
+ def update_groups(activationkey, line)
122
+ if line[SYSTEMGROUPS] && line[SYSTEMGROUPS] != ''
123
+ # TODO: note that existing system groups are not removed
124
+ CSV.parse_line(line[SYSTEMGROUPS], {:skip_blanks => true}).each do |name|
125
+ @api.resource(:host_collections)
126
+ .call(:add_activation_keys, {
127
+ 'id' => katello_hostcollection(line[ORGANIZATION], :name => name),
128
+ 'activation_key_ids' => [activationkey['id']]
129
+ })
130
+ end
131
+ end
132
+ end
133
+
134
+ def update_subscriptions(activationkey, line)
135
+ if line[SUBSCRIPTIONS] && line[SUBSCRIPTIONS] != ''
136
+ subscriptions = CSV.parse_line(line[SUBSCRIPTIONS], {:skip_blanks => true}).collect do |subscription_details|
137
+ (amount, name) = subscription_details.split('|')
138
+ {
139
+ :id => katello_subscription(line[ORGANIZATION], :name => name),
140
+ :quantity => amount
141
+ }
142
+ end
143
+
144
+ # TODO: should there be a destroy_all similar to systems?
145
+ @api.resource(:subscriptions)
146
+ .call(:index, {
147
+ 'per_page' => 999999,
148
+ 'activation_key_id' => activationkey['id']
149
+ })['results'].each do |subscription|
150
+ @api.resource(:subscriptions)
151
+ .call(:destroy, {
152
+ 'id' => subscription['id'],
153
+ 'activation_key_id' => activationkey['id']
154
+ })
155
+ end
156
+
157
+ @api.resource(:subscriptions)
158
+ .call(:create, {
159
+ 'activation_key_id' => activationkey['id'],
160
+ 'subscriptions' => subscriptions
161
+ })
162
+ end
163
+ end
164
+
165
+ def usage_limit(limit)
166
+ Integer(limit) rescue -1
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,95 @@
1
+ # Copyright 2013-2014 Red Hat, Inc.
2
+ #
3
+ # This software is licensed to you under the GNU General Public
4
+ # License as published by the Free Software Foundation; either version
5
+ # 2 of the License (GPLv2) or (at your option) any later version.
6
+ # There is NO WARRANTY for this software, express or implied,
7
+ # including the implied warranties of MERCHANTABILITY,
8
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
9
+ # have received a copy of GPLv2 along with this software; if not, see
10
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11
+
12
+ #
13
+ # -= Architectures CSV =-
14
+ #
15
+ # Columns
16
+ # Name
17
+ # - Architecture name
18
+ # - May contain '%d' which will be replaced with current iteration number of Count
19
+ # - eg. "os%d" -> "os1"
20
+ # Count
21
+ # - Number of times to iterate on this line of the CSV file
22
+ #
23
+
24
+ require 'hammer_cli'
25
+ require 'json'
26
+ require 'csv'
27
+
28
+ module HammerCLICsv
29
+ class CsvCommand
30
+ class ArchitecturesCommand < BaseCommand
31
+ command_name 'architectures'
32
+ desc 'import or export architectures'
33
+
34
+ OPERATINGSYSTEMS = 'Operating Systems'
35
+
36
+ def export
37
+ CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv|
38
+ csv << [NAME, COUNT, ORGANIZATIONS, OPERATINGSYSTEMS]
39
+ @api.resource(:architectures).call(:index, {:per_page => 999999})['results'].each do |architecture|
40
+ name = architecture['name']
41
+ count = 1
42
+ # TODO: http://projects.theforeman.org/issues/4198
43
+ #operatingsystems = architecture['operatingsystem_ids'].collect do |operatingsystem_id|
44
+ # foreman_operatingsystem(:id => operatingsystem_id)
45
+ #end.join(',')
46
+ operatingsystems = ''
47
+ csv << [name, count, operatingsystems]
48
+ end
49
+ end
50
+ end
51
+
52
+ def import
53
+ @existing = {}
54
+ @api.resource(:architectures).call(:index, {:per_page => 999999})['results'].each do |architecture|
55
+ @existing[architecture['name']] = architecture['id'] if architecture
56
+ end
57
+
58
+ thread_import do |line|
59
+ create_architectures_from_csv(line)
60
+ end
61
+ end
62
+
63
+ def create_architectures_from_csv(line)
64
+ line[COUNT].to_i.times do |number|
65
+ name = namify(line[NAME], number)
66
+ architecture_id = @existing[name]
67
+ operatingsystem_ids = CSV.parse_line(line[OPERATINGSYSTEMS]).collect do |operatingsystem_name|
68
+ foreman_operatingsystem(:name => operatingsystem_name)
69
+ end
70
+ if !architecture_id
71
+ print "Creating architecture '#{name}'..." if option_verbose?
72
+ architecture_id = @api.resource(:architectures).call(:create, {
73
+ 'architecture' => {
74
+ 'name' => name,
75
+ 'operatingsystem_ids' => operatingsystem_ids
76
+ }
77
+ })
78
+ else
79
+ print "Updating architecture '#{name}'..." if option_verbose?
80
+ @api.resource(:architectures).call(:update, {
81
+ 'id' => architecture_id,
82
+ 'architecture' => {
83
+ 'name' => name,
84
+ 'operatingsystem_ids' => operatingsystem_ids
85
+ }
86
+ })
87
+ end
88
+ print "done\n" if option_verbose?
89
+ end
90
+ rescue RuntimeError => e
91
+ raise "#{e}\n #{line}"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,706 @@
1
+ # Copyright 2013-2014 Red Hat, Inc.
2
+ #
3
+ # This software is licensed to you under the GNU General Public
4
+ # License as published by the Free Software Foundation; either version
5
+ # 2 of the License (GPLv2) or (at your option) any later version.
6
+ # There is NO WARRANTY for this software, express or implied,
7
+ # including the implied warranties of MERCHANTABILITY,
8
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
9
+ # have received a copy of GPLv2 along with this software; if not, see
10
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11
+
12
+ require 'apipie-bindings'
13
+ require 'hammer_cli'
14
+ require 'json'
15
+ require 'csv'
16
+ require 'hammer_cli_csv/csv'
17
+
18
+ module HammerCLICsv
19
+ class BaseCommand < HammerCLI::Apipie::Command
20
+ option %w(-v --verbose), :flag, 'be verbose'
21
+ option %w(--threads), 'THREAD_COUNT', 'Number of threads to hammer with', :default => 1
22
+ option %w(--csv-export), :flag, 'Export current data instead of importing'
23
+ option %w(--csv-file), 'FILE_NAME', 'CSV file (default to /dev/stdout with --csv-export, otherwise required)'
24
+ option %w(--prefix), 'PREFIX', 'Prefix for all name columns'
25
+ option %w(--server), 'SERVER', 'Server URL'
26
+ option %w(-u --username), 'USERNAME', 'Username to access server'
27
+ option %w(-p --password), 'PASSWORD', 'Password to access server'
28
+
29
+ NAME = 'Name'
30
+ COUNT = 'Count'
31
+
32
+ def execute
33
+ if !option_csv_file
34
+ if option_csv_export?
35
+ # rubocop:disable UselessAssignment
36
+ option_csv_file = '/dev/stdout'
37
+ else
38
+ # rubocop:disable UselessAssignment
39
+ option_csv_file = '/dev/stdin'
40
+ end
41
+ end
42
+
43
+ @api = ApipieBindings::API.new({
44
+ :uri => option_server || HammerCLI::Settings.get(:csv, :host),
45
+ :username => option_username || HammerCLI::Settings.get(:csv, :username),
46
+ :password => option_password || HammerCLI::Settings.get(:csv, :password),
47
+ :api_version => 2
48
+ })
49
+
50
+ option_csv_export? ? export : import
51
+ HammerCLI::EX_OK
52
+ end
53
+
54
+ def namify(name_format, number = 0)
55
+ if name_format.index('%')
56
+ name = name_format % number
57
+ else
58
+ name = name_format
59
+ end
60
+ name = "#{option_prefix}#{name}" if option_prefix
61
+ name
62
+ end
63
+
64
+ def labelize(name)
65
+ name.gsub(/[^a-z0-9\-_]/i, '_')
66
+ end
67
+
68
+ def thread_import(return_headers = false)
69
+ csv = []
70
+ CSV.foreach(option_csv_file || '/dev/stdin', {
71
+ :skip_blanks => true,
72
+ :headers => :first_row,
73
+ :return_headers => return_headers
74
+ }) do |line|
75
+ csv << line
76
+ end
77
+ lines_per_thread = csv.length / option_threads.to_i + 1
78
+ splits = []
79
+
80
+ option_threads.to_i.times do |current_thread|
81
+ start_index = ((current_thread) * lines_per_thread).to_i
82
+ finish_index = ((current_thread + 1) * lines_per_thread).to_i
83
+ finish_index = csv.length if finish_index > csv.length
84
+ if start_index <= finish_index
85
+ lines = csv[start_index...finish_index].clone
86
+ splits << Thread.new do
87
+ lines.each do |line|
88
+ if line[NAME][0] != '#'
89
+ yield line
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ splits.each do |thread|
97
+ thread.join
98
+ end
99
+ end
100
+
101
+ def hammer_context
102
+ {
103
+ :interactive => false,
104
+ :username => 'admin', # TODO: this needs to come from config/settings
105
+ :password => 'changeme' # TODO: this needs to come from config/settings
106
+ }
107
+ end
108
+
109
+ def hammer(context = nil)
110
+ HammerCLI::MainCommand.new('', context || hammer_context)
111
+ end
112
+
113
+ def foreman_organization(options = {})
114
+ @organizations ||= {}
115
+
116
+ if options[:name]
117
+ return nil if options[:name].nil? || options[:name].empty?
118
+ options[:id] = @organizations[options[:name]]
119
+ if !options[:id]
120
+ organization = @api.resource(:organizations).call(:index, {
121
+ :per_page => 999999,
122
+ 'search' => "name=\"#{options[:name]}\""
123
+ })['results']
124
+ raise "Organization '#{options[:name]}' not found" if !organization || organization.empty?
125
+ options[:id] = organization[0]['id']
126
+ @organizations[options[:name]] = options[:id]
127
+ end
128
+ result = options[:id]
129
+ else
130
+ return nil if options[:id].nil?
131
+ options[:name] = @organizations.key(options[:id])
132
+ if !options[:name]
133
+ organization = @api.resource(:organizations).call(:show, {'id' => options[:id]})
134
+ raise "Organization 'id=#{options[:id]}' not found" if !organization || organization.empty?
135
+ options[:name] = organization['name']
136
+ @organizations[options[:name]] = options[:id]
137
+ end
138
+ result = options[:name]
139
+ end
140
+
141
+ result
142
+ end
143
+
144
+ def foreman_location(options = {})
145
+ @locations ||= {}
146
+
147
+ if options[:name]
148
+ return nil if options[:name].nil? || options[:name].empty?
149
+ options[:id] = @locations[options[:name]]
150
+ if !options[:id]
151
+ location = @api.resource(:locations).call(:index, {
152
+ :per_page => 999999,
153
+ 'search' => "name=\"#{options[:name]}\""
154
+ })['results']
155
+ raise "Location '#{options[:name]}' not found" if !location || location.empty?
156
+ options[:id] = location[0]['id']
157
+ @locations[options[:name]] = options[:id]
158
+ end
159
+ result = options[:id]
160
+ else
161
+ return nil if options[:id].nil?
162
+ options[:name] = @locations.key(options[:id])
163
+ if !options[:name]
164
+ location = @api.resource(:locations).call(:show, {'id' => options[:id]})
165
+ raise "Location 'id=#{options[:id]}' not found" if !location || location.empty?
166
+ options[:name] = location['name']
167
+ @locations[options[:name]] = options[:id]
168
+ end
169
+ result = options[:name]
170
+ end
171
+
172
+ result
173
+ end
174
+
175
+ def foreman_role(options = {})
176
+ @roles ||= {}
177
+
178
+ if options[:name]
179
+ return nil if options[:name].nil? || options[:name].empty?
180
+ options[:id] = @roles[options[:name]]
181
+ if !options[:id]
182
+ role = @api.resource(:roles).call(:index, {
183
+ :per_page => 999999,
184
+ 'search' => "name=\"#{options[:name]}\""
185
+ })['results']
186
+ raise "Role '#{options[:name]}' not found" if !role || role.empty?
187
+ options[:id] = role[0]['id']
188
+ @roles[options[:name]] = options[:id]
189
+ end
190
+ result = options[:id]
191
+ else
192
+ return nil if options[:id].nil?
193
+ options[:name] = @roles.key(options[:id])
194
+ if !options[:name]
195
+ role = @api.resource(:roles).call(:show, {'id' => options[:id]})
196
+ raise "Role 'id=#{options[:id]}' not found" if !role || role.empty?
197
+ options[:name] = role['name']
198
+ @roles[options[:name]] = options[:id]
199
+ end
200
+ result = options[:name]
201
+ end
202
+
203
+ result
204
+ end
205
+
206
+ def foreman_permission(options = {})
207
+ @permissions ||= {}
208
+
209
+ if options[:name]
210
+ return nil if options[:name].nil? || options[:name].empty?
211
+ options[:id] = @permissions[options[:name]]
212
+ if !options[:id]
213
+ permission = @api.resource(:permissions).call(:index, {
214
+ :per_page => 999999,
215
+ 'name' => options[:name]
216
+ })['results']
217
+ raise "Permission '#{options[:name]}' not found" if !permission || permission.empty?
218
+ options[:id] = permission[0]['id']
219
+ @permissions[options[:name]] = options[:id]
220
+ end
221
+ result = options[:id]
222
+ else
223
+ return nil if options[:id].nil?
224
+ options[:name] = @permissions.key(options[:id])
225
+ if !options[:name]
226
+ permission = @api.resource(:permissions).call(:show, {'id' => options[:id]})
227
+ raise "Permission 'id=#{options[:id]}' not found" if !permission || permission.empty?
228
+ options[:name] = permission['name']
229
+ @permissions[options[:name]] = options[:id]
230
+ end
231
+ result = options[:name]
232
+ end
233
+
234
+ result
235
+ end
236
+
237
+ def foreman_filter(role, resource, search)
238
+ search = nil if search && search.empty?
239
+ filters = @api.resource(:filters).call(:index, {
240
+ :per_page => 999999,
241
+ 'search' => "role=\"#{role}\""
242
+ })['results']
243
+ filters.each do |filter|
244
+ return filter['id'] if filter['resource_type'] == resource && filter['search'] == search
245
+ end
246
+
247
+ nil
248
+ end
249
+
250
+ def foreman_environment(options = {})
251
+ @environments ||= {}
252
+
253
+ if options[:name]
254
+ return nil if options[:name].nil? || options[:name].empty?
255
+ options[:id] = @environments[options[:name]]
256
+ if !options[:id]
257
+ environment = @api.resource(:environments).call(:index, {
258
+ :per_page => 999999,
259
+ 'search' => "name=\"#{ options[:name] }\""
260
+ })['results']
261
+ raise "Puppet environment '#{options[:name]}' not found" if !environment || environment.empty?
262
+ options[:id] = environment[0]['id']
263
+ @environments[options[:name]] = options[:id]
264
+ end
265
+ result = options[:id]
266
+ else
267
+ return nil if options[:id].nil?
268
+ options[:name] = @environments.key(options[:id])
269
+ if !options[:name]
270
+ environment = @api.resource(:environments).call(:show, {'id' => options[:id]})
271
+ raise "Puppet environment '#{options[:name]}' not found" if !environment || environment.empty?
272
+ options[:name] = environment['name']
273
+ @environments[options[:name]] = options[:id]
274
+ end
275
+ result = options[:name]
276
+ end
277
+
278
+ result
279
+ end
280
+
281
+ def foreman_template_kind(options = {})
282
+ @template_kinds ||= {}
283
+
284
+ if options[:name]
285
+ return nil if options[:name].nil? || options[:name].empty?
286
+ options[:id] = @template_kinds[options[:name]]
287
+ if !options[:id]
288
+ template_kind = @api.resource(:template_kinds).call(:index, {
289
+ :per_page => 999999,
290
+ 'search' => "name=\"#{options[:name]}\""
291
+ })['results']
292
+ raise "Template kind '#{options[:name]}' not found" if !template_kind || template_kind.empty?
293
+ options[:id] = template_kind[0]['id']
294
+ @template_kinds[options[:name]] = options[:id]
295
+ end
296
+ result = options[:id]
297
+ else
298
+ return nil if options[:id].nil?
299
+ options[:name] = @template_kinds.key(options[:id])
300
+ if !options[:name]
301
+ template_kind = @api.resource(:template_kinds).call(:show, {'id' => options[:id]})
302
+ raise "Template kind 'id=#{options[:id]}' not found" if !template_kind || template_kind.empty?
303
+ options[:name] = template_kind['name']
304
+ @template_kinds[options[:name]] = options[:id]
305
+ end
306
+ result = options[:name]
307
+ end
308
+
309
+ result
310
+ end
311
+
312
+ def foreman_operatingsystem(options = {})
313
+ @operatingsystems ||= {}
314
+
315
+ if options[:name]
316
+ return nil if options[:name].nil? || options[:name].empty?
317
+ options[:id] = @operatingsystems[options[:name]]
318
+ if !options[:id]
319
+ (osname, major, minor) = split_os_name(options[:name])
320
+ search = "name=\"#{osname}\" and major=\"#{major}\" and minor=\"#{minor}\""
321
+ operatingsystems = @api.resource(:operatingsystems).call(:index, {
322
+ :per_page => 999999,
323
+ 'search' => search
324
+ })['results']
325
+ operatingsystem = operatingsystems[0]
326
+ raise "Operating system '#{options[:name]}' not found" if !operatingsystem || operatingsystem.empty?
327
+ options[:id] = operatingsystem['id']
328
+ @operatingsystems[options[:name]] = options[:id]
329
+ end
330
+ result = options[:id]
331
+ else
332
+ return nil if options[:id].nil?
333
+ options[:name] = @operatingsystems.key(options[:id])
334
+ if !options[:name]
335
+ operatingsystem = @api.resource(:operatingsystems).call(:show, {'id' => options[:id]})
336
+ raise "Operating system 'id=#{options[:id]}' not found" if !operatingsystem || operatingsystem.empty?
337
+ options[:name] = build_os_name(operatingsystem['name'],
338
+ operatingsystem['major'],
339
+ operatingsystem['minor'])
340
+ @operatingsystems[options[:name]] = options[:id]
341
+ end
342
+ result = options[:name]
343
+ end
344
+
345
+ result
346
+ end
347
+
348
+ def foreman_architecture(options = {})
349
+ @architectures ||= {}
350
+
351
+ if options[:name]
352
+ return nil if options[:name].nil? || options[:name].empty?
353
+ options[:id] = @architectures[options[:name]]
354
+ if !options[:id]
355
+ architecture = @api.resource(:architectures).call(:index, {
356
+ :per_page => 999999,
357
+ 'search' => "name=\"#{options[:name]}\""
358
+ })['results']
359
+ raise "Architecture '#{options[:name]}' not found" if !architecture || architecture.empty?
360
+ options[:id] = architecture[0]['id']
361
+ @architectures[options[:name]] = options[:id]
362
+ end
363
+ result = options[:id]
364
+ else
365
+ return nil if options[:id].nil?
366
+ options[:name] = @architectures.key(options[:id])
367
+ if !options[:name]
368
+ architecture = @api.resource(:architectures).call(:show, {'id' => options[:id]})
369
+ raise "Architecture 'id=#{options[:id]}' not found" if !architecture || architecture.empty?
370
+ options[:name] = architecture['name']
371
+ @architectures[options[:name]] = options[:id]
372
+ end
373
+ result = options[:name]
374
+ end
375
+
376
+ result
377
+ end
378
+
379
+ def foreman_domain(options = {})
380
+ @domains ||= {}
381
+
382
+ if options[:name]
383
+ return nil if options[:name].nil? || options[:name].empty?
384
+ options[:id] = @domains[options[:name]]
385
+ if !options[:id]
386
+ domain = @api.resource(:domains).call(:index, {
387
+ :per_page => 999999,
388
+ 'search' => "name=\"#{options[:name]}\""
389
+ })['results']
390
+ raise "Domain '#{options[:name]}' not found" if !domain || domain.empty?
391
+ options[:id] = domain[0]['id']
392
+ @domains[options[:name]] = options[:id]
393
+ end
394
+ result = options[:id]
395
+ else
396
+ return nil if options[:id].nil?
397
+ options[:name] = @domains.key(options[:id])
398
+ if !options[:name]
399
+ domain = @api.resource(:domains).call(:show, {'id' => options[:id]})
400
+ raise "Domain 'id=#{options[:id]}' not found" if !domain || domain.empty?
401
+ options[:name] = domain['name']
402
+ @domains[options[:name]] = options[:id]
403
+ end
404
+ result = options[:name]
405
+ end
406
+
407
+ result
408
+ end
409
+
410
+ def foreman_partitiontable(options = {})
411
+ @ptables ||= {}
412
+
413
+ if options[:name]
414
+ return nil if options[:name].nil? || options[:name].empty?
415
+ options[:id] = @ptables[options[:name]]
416
+ if !options[:id]
417
+ ptable = @api.resource(:ptables).call(:index, {
418
+ :per_page => 999999,
419
+ 'search' => "name=\"#{options[:name]}\""
420
+ })['results']
421
+ raise "Partition table '#{options[:name]}' not found" if !ptable || ptable.empty?
422
+ options[:id] = ptable[0]['id']
423
+ @ptables[options[:name]] = options[:id]
424
+ end
425
+ result = options[:id]
426
+ elsif options[:id]
427
+ return nil if options[:id].nil?
428
+ options[:name] = @ptables.key(options[:id])
429
+ if !options[:name]
430
+ ptable = @api.resource(:ptables).call(:show, {'id' => options[:id]})
431
+ options[:name] = ptable['name']
432
+ @ptables[options[:name]] = options[:id]
433
+ end
434
+ result = options[:name]
435
+ elsif !options[:name] && !options[:id]
436
+ result = ''
437
+ end
438
+
439
+ result
440
+ end
441
+
442
+ def lifecycle_environment(organization, options = {})
443
+ @lifecycle_environments ||= {}
444
+ @lifecycle_environments[organization] ||= {
445
+ }
446
+
447
+ if options[:name]
448
+ return nil if options[:name].nil? || options[:name].empty?
449
+ options[:id] = @lifecycle_environments[organization][options[:name]]
450
+ if !options[:id]
451
+ @api.resource(:lifecycle_environments)
452
+ .call(:index, {
453
+ :per_page => 999999,
454
+ 'organization_id' => foreman_organization(:name => organization)
455
+ })['results'].each do |environment|
456
+ @lifecycle_environments[organization][environment['name']] = environment['id']
457
+ end
458
+ options[:id] = @lifecycle_environments[organization][options[:name]]
459
+ raise "Lifecycle environment '#{options[:name]}' not found" if !options[:id]
460
+ end
461
+ result = options[:id]
462
+ else
463
+ return nil if options[:id].nil?
464
+ options[:name] = @lifecycle_environments.key(options[:id])
465
+ if !options[:name]
466
+ environment = @api.resource(:lifecycle_environments).call(:show, {'id' => options[:id]})
467
+ raise "Lifecycle environment '#{options[:name]}' not found" if !environment || environment.empty?
468
+ options[:name] = environment['name']
469
+ @lifecycle_environments[options[:name]] = options[:id]
470
+ end
471
+ result = options[:name]
472
+ end
473
+
474
+ result
475
+ end
476
+
477
+ def katello_contentview(organization, options = {})
478
+ @contentviews ||= {}
479
+ @contentviews[organization] ||= {}
480
+
481
+ if options[:name]
482
+ return nil if options[:name].nil? || options[:name].empty?
483
+ options[:id] = @contentviews[organization][options[:name]]
484
+ if !options[:id]
485
+ @api.resource(:content_views).call(:index, {
486
+ :per_page => 999999,
487
+ 'organization_id' => foreman_organization(:name => organization)
488
+ })['results'].each do |contentview|
489
+ @contentviews[organization][contentview['name']] = contentview['id']
490
+ end
491
+ options[:id] = @contentviews[organization][options[:name]]
492
+ raise "Content view '#{options[:name]}' not found" if !options[:id]
493
+ end
494
+ result = options[:id]
495
+ else
496
+ return nil if options[:id].nil?
497
+ options[:name] = @contentviews.key(options[:id])
498
+ if !options[:name]
499
+ contentview = @api.resource(:content_views).call(:show, {'id' => options[:id]})
500
+ raise "Puppet contentview '#{options[:name]}' not found" if !contentview || contentview.empty?
501
+ options[:name] = contentview['name']
502
+ @contentviews[options[:name]] = options[:id]
503
+ end
504
+ result = options[:name]
505
+ end
506
+
507
+ result
508
+ end
509
+
510
+ def katello_repository(organization, options = {})
511
+ @repositories ||= {}
512
+ @repositories[organization] ||= {}
513
+
514
+ if options[:name]
515
+ return nil if options[:name].nil? || options[:name].empty?
516
+ options[:id] = @repositories[organization][options[:name]]
517
+ if !options[:id]
518
+ @api.resource(:repositories)
519
+ .call(:index, {
520
+ :per_page => 999999,
521
+ 'organization_id' => foreman_organization(:name => organization)
522
+ })['results'].each do |repository|
523
+ @repositories[organization][repository['name']] = repository['id']
524
+ end
525
+ options[:id] = @repositories[organization][options[:name]]
526
+ raise "Repository '#{options[:name]}' not found" if !options[:id]
527
+ end
528
+ result = options[:id]
529
+ else
530
+ return nil if options[:id].nil?
531
+ options[:name] = @repositories.key(options[:id])
532
+ if !options[:name]
533
+ repository = @api.resource(:repositories).call(:show, {'id' => options[:id]})
534
+ raise "Puppet repository '#{options[:name]}' not found" if !repository || repository.empty?
535
+ options[:name] = repository['name']
536
+ @repositoriesr[options[:name]] = options[:id]
537
+ end
538
+ result = options[:name]
539
+ end
540
+
541
+ result
542
+ end
543
+
544
+ def katello_subscription(organization, options = {})
545
+ @subscriptions ||= {}
546
+ @subscriptions[organization] ||= {}
547
+
548
+ if options[:name]
549
+ return nil if options[:name].nil? || options[:name].empty?
550
+ options[:id] = @subscriptions[organization][options[:name]]
551
+ if !options[:id]
552
+ results = @api.resource(:subscriptions).call(:index, {
553
+ :per_page => 999999,
554
+ 'organization_id' => foreman_organization(:name => organization),
555
+ 'search' => "name:\"#{options[:name]}\""
556
+ })
557
+ raise "No subscriptions match '#{options[:name]}'" if results['subtotal'] == 0
558
+ raise "Too many subscriptions match '#{options[:name]}'" if results['subtotal'] > 1
559
+ subscription = results['results'][0]
560
+ @subscriptions[organization][options[:name]] = subscription['id']
561
+ options[:id] = @subscriptions[organization][options[:name]]
562
+ raise "Subscription '#{options[:name]}' not found" if !options[:id]
563
+ end
564
+ result = options[:id]
565
+ else
566
+ return nil if options[:id].nil?
567
+ options[:name] = @subscriptions.key(options[:id])
568
+ if !options[:name]
569
+ subscription = @api.resource(:subscriptions).call(:show, {'id' => options[:id]})
570
+ raise "Subscription '#{options[:name]}' not found" if !subscription || subscription.empty?
571
+ options[:name] = subscription['name']
572
+ @subscriptions[options[:name]] = options[:id]
573
+ end
574
+ result = options[:name]
575
+ end
576
+
577
+ result
578
+ end
579
+
580
+ def katello_hostcollection(organization, options = {})
581
+ @hostcollections ||= {}
582
+ @hostcollections[organization] ||= {}
583
+
584
+ if options[:name]
585
+ return nil if options[:name].nil? || options[:name].empty?
586
+ options[:id] = @hostcollections[organization][options[:name]]
587
+ if !options[:id]
588
+ @api.resource(:host_collections).call(:index,
589
+ {
590
+ :per_page => 999999,
591
+ 'organization_id' => foreman_organization(:name => organization),
592
+ 'search' => "name:\"#{options[:name]}\""
593
+ })['results'].each do |hostcollection|
594
+ @hostcollections[organization][hostcollection['name']] = hostcollection['id'] if hostcollection
595
+ end
596
+ options[:id] = @hostcollections[organization][options[:name]]
597
+ raise "System group '#{options[:name]}' not found" if !options[:id]
598
+ end
599
+ result = options[:id]
600
+ else
601
+ return nil if options[:id].nil?
602
+ options[:name] = @hostcollections.key(options[:id])
603
+ if !options[:name]
604
+ hostcollection = @api.resource(:host_collections).call(:show, {'id' => options[:id]})
605
+ raise "System group '#{options[:name]}' not found" if !hostcollection || hostcollection.empty?
606
+ options[:name] = hostcollection['name']
607
+ @hostcollections[options[:name]] = options[:id]
608
+ end
609
+ result = options[:name]
610
+ end
611
+
612
+ result
613
+ end
614
+
615
+ def build_os_name(name, major, minor)
616
+ name += " #{major}" if major && major != ''
617
+ name += ".#{minor}" if minor && minor != ''
618
+ name
619
+ end
620
+
621
+ # "Red Hat 6.4" => "Red Hat", "6", "4"
622
+ # "Red Hat 6" => "Red Hat", "6", ''
623
+ def split_os_name(name)
624
+ tokens = name.split(' ')
625
+ is_number = Float(tokens[-1]) rescue false
626
+ if is_number
627
+ (major, minor) = tokens[-1].split('.').flatten
628
+ name = tokens[0...-1].join(' ')
629
+ else
630
+ name = tokens.join(' ')
631
+ end
632
+ [name, major || '', minor || '']
633
+ end
634
+
635
+ def export_column(object, name, field)
636
+ return '' unless object[name]
637
+ values = CSV.generate do |column|
638
+ column << object[name].collect do |fields|
639
+ fields[field]
640
+ end
641
+ end
642
+ values.delete!("\n")
643
+ end
644
+
645
+ def collect_column(column)
646
+ return [] if column.nil? || column.empty?
647
+ CSV.parse_line(column, {:skip_blanks => true}).collect do |value|
648
+ yield value
649
+ end
650
+ end
651
+
652
+ def pluralize(name)
653
+ case name
654
+ when /smart_proxy/
655
+ 'smart_proxies'
656
+ else
657
+ "#{name}s"
658
+ end
659
+ end
660
+
661
+ def associate_organizations(id, organizations, name)
662
+ return if organizations.nil?
663
+
664
+ associations ||= {}
665
+ CSV.parse_line(organizations).each do |organization|
666
+ organization_id = foreman_organization(:name => organization)
667
+ if associations[organization].nil?
668
+ associations[organization] = @api.resource(:organizations).call(:show, {'id' => organization_id})[pluralize(name)].collect do |reference_object|
669
+ reference_object['id']
670
+ end
671
+ end
672
+ associations[organization] += [id] if !associations[organization].include? id
673
+ @api.resource(:organizations)
674
+ .call(:update, {
675
+ 'id' => organization_id,
676
+ 'organization' => {
677
+ "#{name}_ids" => associations[organization]
678
+ }
679
+ })
680
+ end if organizations && !organizations.empty?
681
+ end
682
+
683
+ def associate_locations(id, locations, name)
684
+ return if locations.nil?
685
+
686
+ associations ||= {}
687
+ CSV.parse_line(locations).each do |location|
688
+ location_id = foreman_location(:name => location)
689
+ if associations[location].nil?
690
+ associations[location] = @api.resource(:locations).call(:show, {'id' => location_id})[pluralize(name)].collect do |reference_object|
691
+ reference_object['id']
692
+ end
693
+ end
694
+ associations[location] += [id] if !associations[location].include? id
695
+
696
+ @api.resource(:locations)
697
+ .call(:update, {
698
+ 'id' => location_id,
699
+ 'location' => {
700
+ "#{name}_ids" => associations[location]
701
+ }
702
+ })
703
+ end if locations && !locations.empty?
704
+ end
705
+ end
706
+ end