hammer_cli_csv 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,118 @@
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
+ # -= Hosts CSV =-
14
+ #
15
+ # Columns
16
+ # Name
17
+ # - Host 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
+ # MAC Address
23
+ # - MAC address
24
+ # - May contain '%d' which will be replaced with current iteration number of Count
25
+ # - eg. "FF:FF:FF:FF:FF:%02x" -> "FF:FF:FF:FF:FF:0A"
26
+ # - Warning: be sure to keep count below 255 or MAC hex will exceed limit
27
+ #
28
+
29
+ require 'hammer_cli'
30
+ require 'json'
31
+ require 'csv'
32
+ require 'uri'
33
+
34
+ module HammerCLICsv
35
+ class CsvCommand
36
+ class HostsCommand < BaseCommand
37
+ command_name 'hosts'
38
+ desc 'import or export hosts'
39
+
40
+ ORGANIZATION = 'Organization'
41
+ ENVIRONMENT = 'Environment'
42
+ OPERATINGSYSTEM = 'Operating System'
43
+ ARCHITECTURE = 'Architecture'
44
+ MACADDRESS = 'MAC Address'
45
+ DOMAIN = 'Domain'
46
+ PARTITIONTABLE = 'Partition Table'
47
+
48
+ def export
49
+ CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv|
50
+ csv << [NAME, COUNT, ORGANIZATION, ENVIRONMENT, OPERATINGSYSTEM, ARCHITECTURE, MACADDRESS, DOMAIN, PARTITIONTABLE]
51
+ @api.resource(:hosts).call(:index, {:per_page => 999999})['results'].each do |host|
52
+ host = @api.resource(:hosts).call(:show, {'id' => host['id']})
53
+ raise "Host 'id=#{host['id']}' not found" if !host || host.empty?
54
+
55
+ name = host['name']
56
+ count = 1
57
+ organization = foreman_organization(:id => host['organization_id'])
58
+ environment = foreman_environment(:id => host['environment_id'])
59
+ operatingsystem = foreman_operatingsystem(:id => host['operatingsystem_id'])
60
+ architecture = foreman_architecture(:id => host['architecture_id'])
61
+ mac = host['mac']
62
+ domain = foreman_domain(:id => host['domain_id'])
63
+ ptable = foreman_partitiontable(:id => host['ptable_id'])
64
+
65
+ csv << [name, count, organization, environment, operatingsystem, architecture, mac, domain, ptable]
66
+ end
67
+ end
68
+ end
69
+
70
+ def import
71
+ @existing = {}
72
+ @api.resource(:hosts).call(:index, {:per_page => 999999})['results'].each do |host|
73
+ @existing[host['name']] = host['id'] if host
74
+ end
75
+
76
+ thread_import do |line|
77
+ create_hosts_from_csv(line)
78
+ end
79
+ end
80
+
81
+ def create_hosts_from_csv(line)
82
+ line[COUNT].to_i.times do |number|
83
+ name = namify(line[NAME], number)
84
+ if !@existing.include? name
85
+ print "Creating host '#{name}'..." if option_verbose?
86
+ @api.resource(:hosts).call(:create, {
87
+ 'name' => name,
88
+ 'root_pass' => 'changeme',
89
+ 'mac' => namify(line[MACADDRESS], number),
90
+ 'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
91
+ 'environment_id' => foreman_environment(:name => line[ENVIRONMENT]),
92
+ 'operatingsystem_id' => foreman_operatingsystem(:name => line[OPERATINGSYSTEM]),
93
+ 'architecture_id' => foreman_architecture(:name => line[ARCHITECTURE]),
94
+ 'domain_id' => foreman_domain(:name => line[DOMAIN]),
95
+ 'ptable_id' => foreman_partitiontable(:name => line[PARTITIONTABLE])
96
+ })
97
+ else
98
+ print "Updating host '#{name}'..." if option_verbose?
99
+ @api.resource(:hosts).call(:update, {
100
+ 'id' => @existing[name],
101
+ 'name' => name,
102
+ 'mac' => namify(line[MACADDRESS], number),
103
+ 'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
104
+ 'environment_id' => foreman_environment(:name => line[ENVIRONMENT]),
105
+ 'operatingsystem_id' => foreman_operatingsystem(:name => line[OPERATINGSYSTEM]),
106
+ 'architecture_id' => foreman_architecture(:name => line[ARCHITECTURE]),
107
+ 'domain_id' => foreman_domain(:name => line[DOMAIN]),
108
+ 'ptable_id' => foreman_partitiontable(:name => line[PARTITIONTABLE])
109
+ })
110
+ end
111
+ print "done\n" if option_verbose?
112
+ end
113
+ rescue RuntimeError => e
114
+ raise "#{e}\n #{line}"
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,82 @@
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_csv'
14
+ require 'hammer_cli_foreman'
15
+ require 'hammer_cli_katello'
16
+ require 'json'
17
+ require 'csv'
18
+ require 'uri'
19
+
20
+ module HammerCLICsv
21
+ class CsvCommand
22
+ class ImportCommand < HammerCLI::Apipie::Command
23
+ command_name 'import'
24
+ desc 'import by directory'
25
+
26
+ option %w(-v --verbose), :flag, 'be verbose'
27
+ option %w(--threads), 'THREAD_COUNT', 'Number of threads to hammer with', :default => 1
28
+ option %w(--server), 'SERVER', 'Server URL'
29
+ option %w(-u --username), 'USERNAME', 'Username to access server'
30
+ option %w(-p --password), 'PASSWORD', 'Password to access server'
31
+ option '--dir', 'DIRECTORY', 'directory to import from'
32
+
33
+ RESOURCES = %w( organizations locations roles users puppet_environments operating_systems
34
+ domains architectures partition_tables lifecycle_environments host_collections
35
+ subscriptions activation_keys hosts content_hosts reports )
36
+ RESOURCES.each do |resource|
37
+ dashed = resource.sub('_', '-')
38
+ option "--#{dashed}", 'FILE', "csv file for #{dashed}"
39
+ end
40
+
41
+ def execute
42
+ @api = ApipieBindings::API.new({
43
+ :uri => option_server || HammerCLI::Settings.get(:csv, :host),
44
+ :username => option_username || HammerCLI::Settings.get(:csv, :username),
45
+ :password => option_password || HammerCLI::Settings.get(:csv, :password),
46
+ :api_version => 2
47
+ })
48
+
49
+ # Swing the hammers
50
+ RESOURCES.each do |resource|
51
+ hammer_resource(resource)
52
+ end
53
+
54
+ HammerCLI::EX_OK
55
+ end
56
+
57
+ def hammer(context = nil)
58
+ context ||= {
59
+ :interactive => false,
60
+ :username => 'admin', # TODO: this needs to come from config/settings
61
+ :password => 'changeme' # TODO: this needs to come from config/settings
62
+ }
63
+
64
+ HammerCLI::MainCommand.new('', context)
65
+ end
66
+
67
+ def hammer_resource(resource)
68
+ return if !self.send("option_#{resource}") && !option_dir
69
+ options_file = self.send("option_#{resource}") || "#{option_dir}/#{resource.sub('_', '-')}.csv"
70
+ if !File.exists? options_file
71
+ return if option_dir
72
+ raise "File for #{resource} '#{options_file}' does not exist"
73
+ end
74
+
75
+ args = %W( csv #{resource.sub('_', '-')} --csv-file #{options_file} )
76
+ args << '-v' if option_verbose?
77
+ args += %W( --threads #{option_threads} )
78
+ hammer.run(args)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,88 @@
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 InstallationMediasCommand < BaseCommand
15
+ command_name 'installation-medias'
16
+ desc 'import or export installation media'
17
+
18
+ OSFAMILY = 'OS Family'
19
+ PATH = 'Path'
20
+ ORGANIZATIONS = 'Organizations'
21
+
22
+ def export
23
+ CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv|
24
+ csv << [NAME, COUNT, PATH, OSFAMILY]
25
+ @api.resource(:media).call(:index, {:per_page => 999999})['results'].each do |installation_media|
26
+ name = installation_media['name']
27
+ count = 1
28
+ path = installation_media['path']
29
+ os_family = installation_media['os_family']
30
+ csv << [name, count, path, os_family]
31
+ end
32
+ end
33
+ end
34
+
35
+ def import
36
+ @existing = {}
37
+ @api.resource(:media).call(:index, {:per_page => 999999})['results'].each do |installation_media|
38
+ @existing[installation_media['name']] = installation_media['id'] if installation_media
39
+ end
40
+
41
+ thread_import do |line|
42
+ create_installation_medias_from_csv(line)
43
+ end
44
+ end
45
+
46
+ def create_installation_medias_from_csv(line)
47
+ line[COUNT].to_i.times do |number|
48
+ name = namify(line[NAME], number)
49
+ if !@existing.include? name
50
+ print "Creating installation_media '#{name}'..." if option_verbose?
51
+ installation_media_id = @api.resource(:media).call(:create, {
52
+ 'name' => name
53
+ })['id']
54
+ else
55
+ print "Updating installation_media '#{name}'..." if option_verbose?
56
+ installation_media_id = @api.resource(:media).call(:update, {
57
+ 'id' => @existing[name],
58
+ 'name' => name
59
+ })['id']
60
+ end
61
+
62
+ # Update associated resources
63
+ installation_medias ||= {}
64
+ CSV.parse_line(line[ORGANIZATIONS]).each do |organization|
65
+ organization_id = foreman_organization(:name => organization)
66
+ if installation_medias[organization].nil?
67
+ installation_medias[organization] = @api.resource(:organizations).call(:show, {'id' => organization_id})['installation_medias'].collect do |installation_media|
68
+ installation_media['id']
69
+ end
70
+ end
71
+ installation_medias[organization] += [installation_media_id] if !installation_medias[organization].include? installation_media_id
72
+
73
+ @api.resource(:organizations).call(:update, {
74
+ 'id' => organization_id,
75
+ 'organization' => {
76
+ 'installation_media_ids' => installation_medias[organization]
77
+ }
78
+ })
79
+ end
80
+
81
+ print "done\n" if option_verbose?
82
+ end
83
+ rescue RuntimeError => e
84
+ raise "#{e}\n #{line}"
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,116 @@
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
+ # -= Environments CSV =-
14
+ #
15
+ # Columns
16
+ # Name
17
+ # - Environment 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 LifecycleEnvironmentsCommand < BaseCommand
31
+ command_name 'lifecycle-environments'
32
+ desc 'import or export lifecycle environments'
33
+
34
+ ORGANIZATION = 'Organization'
35
+ PRIORENVIRONMENT = 'Prior Environment'
36
+ DESCRIPTION = 'Description'
37
+
38
+ def export
39
+ CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv|
40
+ csv << [NAME, COUNT, ORGANIZATION, PRIORENVIRONMENT, DESCRIPTION]
41
+ @api.resource(:organizations)
42
+ .call(:index, {
43
+ 'per_page' => 999999
44
+ })['results'].each do |organization|
45
+ @api.resource(:lifecycle_environments)
46
+ .call(:index, {
47
+ 'per_page' => 999999,
48
+ 'organization_id' => organization['id']
49
+ })['results'].each do |environment|
50
+ if environment['name'] != 'Library'
51
+ name = environment['name']
52
+ count = 1
53
+ prior = environment['prior']
54
+ description = environment['description']
55
+ csv << [name, count, organization['name'], prior, description]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def import
63
+ @existing = {}
64
+ @api.resource(:organizations)
65
+ .call(:index, {
66
+ 'per_page' => 999999
67
+ })['results'].each do |organization|
68
+ @api.resource(:lifecycle_environments)
69
+ .call(:index, {
70
+ 'per_page' => 999999,
71
+ 'organization_id' => foreman_organization(:name => organization['name'])
72
+ })['results'].each do |environment|
73
+ @existing[organization['name']] ||= {}
74
+ @existing[organization['name']][environment['name']] = environment['id'] if environment
75
+ end
76
+ end
77
+
78
+ thread_import do |line|
79
+ create_environments_from_csv(line)
80
+ end
81
+ end
82
+
83
+ def create_environments_from_csv(line)
84
+ line[COUNT].to_i.times do |number|
85
+ name = namify(line[NAME], number)
86
+ prior = namify(line[PRIORENVIRONMENT], number)
87
+ raise "Organization '#{line[ORGANIZATION]}' does not exist" if !@existing.include? line[ORGANIZATION]
88
+ if !@existing[line[ORGANIZATION]].include? name
89
+ print "Creating environment '#{name}'..." if option_verbose?
90
+ @api.resource(:lifecycle_environments)
91
+ .call(:create, {
92
+ 'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
93
+ 'name' => name,
94
+ 'prior' => lifecycle_environment(line[ORGANIZATION], :name => prior),
95
+ 'description' => line[DESCRIPTION]
96
+ })
97
+ else
98
+ print "Updating environment '#{name}'..." if option_verbose?
99
+ @api.resource(:lifecycle_environments)
100
+ .call(:update, {
101
+ 'id' => @existing[line[ORGANIZATION]][name],
102
+ 'name' => name,
103
+ 'new_name' => name,
104
+ 'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
105
+ 'prior' => prior,
106
+ 'description' => line[DESCRIPTION]
107
+ })
108
+ end
109
+ print "done\n" if option_verbose?
110
+ end
111
+ rescue RuntimeError => e
112
+ raise "#{e}\n #{line}"
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,84 @@
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
+ # -= Locations CSV =-
14
+ #
15
+ # Columns
16
+ # Name
17
+ # - Name of the location.
18
+ # - May contain '%d' which will be replaced with current iteration number of Count
19
+ # - eg. "location%d" -> "location1"
20
+ # Count
21
+ # - Number of times to iterate on this line of the CSV file
22
+ # Parent
23
+ # - Parent location
24
+ #
25
+
26
+ require 'hammer_cli'
27
+ require 'json'
28
+ require 'csv'
29
+
30
+ module HammerCLICsv
31
+ class CsvCommand
32
+ class LocationsCommand < BaseCommand
33
+ command_name 'locations'
34
+ desc 'import or export locations'
35
+
36
+ PARENT = 'Parent Location'
37
+
38
+ def export
39
+ CSV.open(option_csv_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv|
40
+ csv << [NAME, COUNT, PARENT]
41
+ @api.resource(:locations).call(:index, {:per_page => 999999})['results'].each do |location|
42
+ csv << [location['name'], 1]
43
+ end
44
+ end
45
+ end
46
+
47
+ def import
48
+ @existing = {}
49
+ @api.resource(:locations).call(:index, {:per_page => 999999})['results'].each do |location|
50
+ @existing[location['name']] = location['id'] if location
51
+ end
52
+
53
+ thread_import do |line|
54
+ create_locations_from_csv(line)
55
+ end
56
+ end
57
+
58
+ def create_locations_from_csv(line)
59
+ line[COUNT].to_i.times do |number|
60
+ name = namify(line[NAME], number)
61
+ location_id = @existing[name]
62
+ if !location_id
63
+ print "Creating location '#{name}'... " if option_verbose?
64
+ @api.resource(:locations).call(:create, {
65
+ 'location' => {
66
+ 'name' => name,
67
+ 'parent_id' => foreman_location(:name => line[PARENT])
68
+ }
69
+ })
70
+ else
71
+ print "Updating location '#{name}'... " if option_verbose?
72
+ @api.resource(:locations).call(:update, {
73
+ 'id' => location_id,
74
+ 'location' => {
75
+ 'parent_id' => foreman_location(:name => line[PARENT])
76
+ }
77
+ })
78
+ end
79
+ print "done\n" if option_verbose?
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end