Project

General

Profile

Download (31.2 KB) Statistics
| Branch: | Tag: | Revision:

hammer-cli-csv / lib / hammer_cli_csv / base.rb @ 9e11b4c5

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
# rubocop:disable ClassLength
19
module HammerCLICsv
20
  class BaseCommand < HammerCLI::Apipie::Command
21
    option %w(-v --verbose), :flag, 'be verbose'
22
    option %w(--threads), 'THREAD_COUNT', 'Number of threads to hammer with', :default => 1
23
    option %w(--csv-export), :flag, 'Export current data instead of importing'
24
    option %w(--csv-file), 'FILE_NAME', 'CSV file (default to /dev/stdout with --csv-export, otherwise required)'
25
    option %w(--prefix), 'PREFIX', 'Prefix for all name columns'
26

    
27
    NAME = 'Name'
28
    COUNT = 'Count'
29

    
30
    def execute
31
      @server = HammerCLI::Settings.settings[:_params][:host] ||
32
        HammerCLI::Settings.get(:csv, :host) ||
33
        HammerCLI::Settings.get(:katello, :host) ||
34
        HammerCLI::Settings.get(:foreman, :host)
35
      @username = HammerCLI::Settings.settings[:_params][:username] ||
36
        HammerCLI::Settings.get(:csv, :username) ||
37
        HammerCLI::Settings.get(:katello, :username) ||
38
        HammerCLI::Settings.get(:foreman, :username)
39
      @password = HammerCLI::Settings.settings[:_params][:password] ||
40
        HammerCLI::Settings.get(:csv, :password) ||
41
        HammerCLI::Settings.get(:katello, :password) ||
42
        HammerCLI::Settings.get(:foreman, :password)
43

    
44
      @server_status = check_server_status(@server, @username, @password)
45

    
46
      if @server_status['release'] == 'Headpin'
47
        @headpin = HeadpinApi.new({
48
                                    :server => @server,
49
                                    :username => @username,
50
                                    :password => @password
51
                                  })
52
      else
53
        @api = ApipieBindings::API.new({
54
                                         :uri => @server,
55
                                         :username => @username,
56
                                         :password => @password,
57
                                         :api_version => 2
58
                                       })
59
      end
60

    
61
      option_csv_export? ? export : import
62
      HammerCLI::EX_OK
63
    end
64

    
65
    def check_server_status(server, username, password)
66
      url = "#{server}/api/status"
67
      uri = URI(url)
68
      nethttp = Net::HTTP.new(uri.host, uri.port)
69
      nethttp.use_ssl = uri.scheme == 'https'
70
      nethttp.verify_mode = OpenSSL::SSL::VERIFY_NONE
71
      server_status = nethttp.start do |http|
72
        request = Net::HTTP::Get.new uri.request_uri
73
        request.basic_auth(username, password)
74
        response = http.request(request)
75
        JSON.parse(response.body)
76
      end
77

    
78
      url = "#{server}/api/v2/plugins"
79
      uri = URI(url)
80
      nethttp = Net::HTTP.new(uri.host, uri.port)
81
      nethttp.use_ssl = uri.scheme == 'https'
82
      nethttp.verify_mode = OpenSSL::SSL::VERIFY_NONE
83
      server_status['plugins'] = nethttp.start do |http|
84
        request = Net::HTTP::Get.new uri.request_uri
85
        request.basic_auth(username, password)
86
        response = http.request(request)
87
        JSON.parse(response.body)['results']
88
      end
89

    
90
      server_status
91
    end
92

    
93
    def namify(name_format, number = 0)
94
      if name_format.index('%')
95
        name = name_format % number
96
      else
97
        name = name_format
98
      end
99
      name = "#{option_prefix}#{name}" if option_prefix
100
      name
101
    end
102

    
103
    def labelize(name)
104
      name.gsub(/[^a-z0-9\-_]/i, '_')
105
    end
106

    
107
    def thread_import(return_headers = false, filename=nil, name_column=nil)
108
      filename ||= option_csv_file || '/dev/stdin'
109
      csv = []
110
      CSV.foreach(filename, {
111
          :skip_blanks => true,
112
          :headers => :first_row,
113
          :return_headers => return_headers
114
      }) do |line|
115
        csv << line
116
      end
117
      lines_per_thread = csv.length / option_threads.to_i + 1
118
      splits = []
119

    
120
      option_threads.to_i.times do |current_thread|
121
        start_index = ((current_thread) * lines_per_thread).to_i
122
        finish_index = ((current_thread + 1) * lines_per_thread).to_i
123
        finish_index = csv.length if finish_index > csv.length
124
        if start_index <= finish_index
125
          lines = csv[start_index...finish_index].clone
126
          splits << Thread.new do
127
            lines.each do |line|
128
              if line[name_column || NAME][0] != '#'
129
                yield line
130
              end
131
            end
132
          end
133
        end
134
      end
135

    
136
      splits.each do |thread|
137
        thread.join
138
      end
139
    end
140

    
141
    def hammer_context
142
      {
143
        :interactive => false,
144
        :username => 'admin', # TODO: this needs to come from config/settings
145
        :password => 'changeme' # TODO: this needs to come from config/settings
146
      }
147
    end
148

    
149
    def hammer(context = nil)
150
      HammerCLI::MainCommand.new('', context || hammer_context)
151
    end
152

    
153
    def foreman_organization(options = {})
154
      @organizations ||= {}
155

    
156
      if options[:name]
157
        return nil if options[:name].nil? || options[:name].empty?
158
        options[:id] = @organizations[options[:name]]
159
        if !options[:id]
160
          organization = @api.resource(:organizations).call(:index, {
161
                                                              :per_page => 999999,
162
                                                              'search' => "name=\"#{options[:name]}\""
163
                                                            })['results']
164
          raise "Organization '#{options[:name]}' not found" if !organization || organization.empty?
165
          options[:id] = organization[0]['id']
166
          @organizations[options[:name]] = options[:id]
167
        end
168
        result = options[:id]
169
      else
170
        return nil if options[:id].nil?
171
        options[:name] = @organizations.key(options[:id])
172
        if !options[:name]
173
          organization = @api.resource(:organizations).call(:show, {'id' => options[:id]})
174
          raise "Organization 'id=#{options[:id]}' not found" if !organization || organization.empty?
175
          options[:name] = organization['name']
176
          @organizations[options[:name]] = options[:id]
177
        end
178
        result = options[:name]
179
      end
180

    
181
      result
182
    end
183

    
184
    def foreman_location(options = {})
185
      @locations ||= {}
186

    
187
      if options[:name]
188
        return nil if options[:name].nil? || options[:name].empty?
189
        options[:id] = @locations[options[:name]]
190
        if !options[:id]
191
          location = @api.resource(:locations).call(:index, {
192
                                                      :per_page => 999999,
193
                                                      'search' => "name=\"#{options[:name]}\""
194
                                                    })['results']
195
          raise "Location '#{options[:name]}' not found" if !location || location.empty?
196
          options[:id] = location[0]['id']
197
          @locations[options[:name]] = options[:id]
198
        end
199
        result = options[:id]
200
      else
201
        return nil if options[:id].nil?
202
        options[:name] = @locations.key(options[:id])
203
        if !options[:name]
204
          location = @api.resource(:locations).call(:show, {'id' => options[:id]})
205
          raise "Location 'id=#{options[:id]}' not found" if !location || location.empty?
206
          options[:name] = location['name']
207
          @locations[options[:name]] = options[:id]
208
        end
209
        result = options[:name]
210
      end
211

    
212
      result
213
    end
214

    
215
    def foreman_role(options = {})
216
      @roles ||= {}
217

    
218
      if options[:name]
219
        return nil if options[:name].nil? || options[:name].empty?
220
        options[:id] = @roles[options[:name]]
221
        if !options[:id]
222
          role = @api.resource(:roles).call(:index, {
223
                                              :per_page => 999999,
224
                                              'search' => "name=\"#{options[:name]}\""
225
                                            })['results']
226
          raise "Role '#{options[:name]}' not found" if !role || role.empty?
227
          options[:id] = role[0]['id']
228
          @roles[options[:name]] = options[:id]
229
        end
230
        result = options[:id]
231
      else
232
        return nil if options[:id].nil?
233
        options[:name] = @roles.key(options[:id])
234
        if !options[:name]
235
          role = @api.resource(:roles).call(:show, {'id' => options[:id]})
236
          raise "Role 'id=#{options[:id]}' not found" if !role || role.empty?
237
          options[:name] = role['name']
238
          @roles[options[:name]] = options[:id]
239
        end
240
        result = options[:name]
241
      end
242

    
243
      result
244
    end
245

    
246
    def foreman_permission(options = {})
247
      @permissions ||= {}
248

    
249
      if options[:name]
250
        return nil if options[:name].nil? || options[:name].empty?
251
        options[:id] = @permissions[options[:name]]
252
        if !options[:id]
253
          permission = @api.resource(:permissions).call(:index, {
254
                                                          :per_page => 999999,
255
                                                          'name' => options[:name]
256
                                                        })['results']
257
          raise "Permission '#{options[:name]}' not found" if !permission || permission.empty?
258
          options[:id] = permission[0]['id']
259
          @permissions[options[:name]] = options[:id]
260
        end
261
        result = options[:id]
262
      else
263
        return nil if options[:id].nil?
264
        options[:name] = @permissions.key(options[:id])
265
        if !options[:name]
266
          permission = @api.resource(:permissions).call(:show, {'id' => options[:id]})
267
          raise "Permission 'id=#{options[:id]}' not found" if !permission || permission.empty?
268
          options[:name] = permission['name']
269
          @permissions[options[:name]] = options[:id]
270
        end
271
        result = options[:name]
272
      end
273

    
274
      result
275
    end
276

    
277
    def foreman_filter(role, resource, search)
278
      search = nil if search && search.empty?
279
      filters = @api.resource(:filters).call(:index, {
280
                                               :per_page => 999999,
281
                                               'search' => "role=\"#{role}\""
282
                                             })['results']
283
      filters.each do |filter|
284
        resource_type = (filter['resource_type'] || '').split(':')[-1] # To remove "Katello::" when present
285
        return filter['id'] if resource_type == resource && filter['search'] == search
286
      end
287

    
288
      nil
289
    end
290

    
291
    def foreman_environment(options = {})
292
      @environments ||= {}
293

    
294
      if options[:name]
295
        return nil if options[:name].nil? || options[:name].empty?
296
        options[:id] = @environments[options[:name]]
297
        if !options[:id]
298
          environment = @api.resource(:environments).call(:index, {
299
                                                            :per_page => 999999,
300
                                                            'search' => "name=\"#{ options[:name] }\""
301
                                                          })['results']
302
          raise "Puppet environment '#{options[:name]}' not found" if !environment || environment.empty?
303
          options[:id] = environment[0]['id']
304
          @environments[options[:name]] = options[:id]
305
        end
306
        result = options[:id]
307
      else
308
        return nil if options[:id].nil?
309
        options[:name] = @environments.key(options[:id])
310
        if !options[:name]
311
          environment = @api.resource(:environments).call(:show, {'id' => options[:id]})
312
          raise "Puppet environment '#{options[:name]}' not found" if !environment || environment.empty?
313
          options[:name] = environment['name']
314
          @environments[options[:name]] = options[:id]
315
        end
316
        result = options[:name]
317
      end
318

    
319
      result
320
    end
321

    
322
    def foreman_template_kind(options = {})
323
      @template_kinds ||= {}
324

    
325
      if options[:name]
326
        return nil if options[:name].nil? || options[:name].empty?
327
        options[:id] = @template_kinds[options[:name]]
328
        if !options[:id]
329
          template_kind = @api.resource(:template_kinds).call(:index, {
330
                                              :per_page => 999999,
331
                                              'search' => "name=\"#{options[:name]}\""
332
                                            })['results']
333
          raise "Template kind '#{options[:name]}' not found" if !template_kind || template_kind.empty?
334
          options[:id] = template_kind[0]['id']
335
          @template_kinds[options[:name]] = options[:id]
336
        end
337
        result = options[:id]
338
      else
339
        return nil if options[:id].nil?
340
        options[:name] = @template_kinds.key(options[:id])
341
        if !options[:name]
342
          template_kind = @api.resource(:template_kinds).call(:show, {'id' => options[:id]})
343
          raise "Template kind 'id=#{options[:id]}' not found" if !template_kind || template_kind.empty?
344
          options[:name] = template_kind['name']
345
          @template_kinds[options[:name]] = options[:id]
346
        end
347
        result = options[:name]
348
      end
349

    
350
      result
351
    end
352

    
353
    def foreman_operatingsystem(options = {})
354
      @operatingsystems ||= {}
355

    
356
      if options[:name]
357
        return nil if options[:name].nil? || options[:name].empty?
358
        options[:id] = @operatingsystems[options[:name]]
359
        if !options[:id]
360
          (osname, major, minor) = split_os_name(options[:name])
361
          search = "name=\"#{osname}\" and major=\"#{major}\" and minor=\"#{minor}\""
362
          operatingsystems = @api.resource(:operatingsystems).call(:index, {
363
                                                                     :per_page => 999999,
364
                                                                     'search' => search
365
                                                                   })['results']
366
          operatingsystem = operatingsystems[0]
367
          raise "Operating system '#{options[:name]}' not found" if !operatingsystem || operatingsystem.empty?
368
          options[:id] = operatingsystem['id']
369
          @operatingsystems[options[:name]] = options[:id]
370
        end
371
        result = options[:id]
372
      else
373
        return nil if options[:id].nil?
374
        options[:name] = @operatingsystems.key(options[:id])
375
        if !options[:name]
376
          operatingsystem = @api.resource(:operatingsystems).call(:show, {'id' => options[:id]})
377
          raise "Operating system 'id=#{options[:id]}' not found" if !operatingsystem || operatingsystem.empty?
378
          options[:name] = build_os_name(operatingsystem['name'],
379
                                         operatingsystem['major'],
380
                                         operatingsystem['minor'])
381
          @operatingsystems[options[:name]] = options[:id]
382
        end
383
        result = options[:name]
384
      end
385

    
386
      result
387
    end
388

    
389
    def foreman_architecture(options = {})
390
      @architectures ||= {}
391

    
392
      if options[:name]
393
        return nil if options[:name].nil? || options[:name].empty?
394
        options[:id] = @architectures[options[:name]]
395
        if !options[:id]
396
          architecture = @api.resource(:architectures).call(:index, {
397
                                                              :per_page => 999999,
398
                                                              'search' => "name=\"#{options[:name]}\""
399
                                                            })['results']
400
          raise "Architecture '#{options[:name]}' not found" if !architecture || architecture.empty?
401
          options[:id] = architecture[0]['id']
402
          @architectures[options[:name]] = options[:id]
403
        end
404
        result = options[:id]
405
      else
406
        return nil if options[:id].nil?
407
        options[:name] = @architectures.key(options[:id])
408
        if !options[:name]
409
          architecture = @api.resource(:architectures).call(:show, {'id' => options[:id]})
410
          raise "Architecture 'id=#{options[:id]}' not found" if !architecture || architecture.empty?
411
          options[:name] = architecture['name']
412
          @architectures[options[:name]] = options[:id]
413
        end
414
        result = options[:name]
415
      end
416

    
417
      result
418
    end
419

    
420
    def foreman_domain(options = {})
421
      @domains ||= {}
422

    
423
      if options[:name]
424
        return nil if options[:name].nil? || options[:name].empty?
425
        options[:id] = @domains[options[:name]]
426
        if !options[:id]
427
          domain = @api.resource(:domains).call(:index, {
428
                                                  :per_page => 999999,
429
                                                  'search' => "name=\"#{options[:name]}\""
430
                                                })['results']
431
          raise "Domain '#{options[:name]}' not found" if !domain || domain.empty?
432
          options[:id] = domain[0]['id']
433
          @domains[options[:name]] = options[:id]
434
        end
435
        result = options[:id]
436
      else
437
        return nil if options[:id].nil?
438
        options[:name] = @domains.key(options[:id])
439
        if !options[:name]
440
          domain = @api.resource(:domains).call(:show, {'id' => options[:id]})
441
          raise "Domain 'id=#{options[:id]}' not found" if !domain || domain.empty?
442
          options[:name] = domain['name']
443
          @domains[options[:name]] = options[:id]
444
        end
445
        result = options[:name]
446
      end
447

    
448
      result
449
    end
450

    
451
    def foreman_partitiontable(options = {})
452
      @ptables ||= {}
453

    
454
      if options[:name]
455
        return nil if options[:name].nil? || options[:name].empty?
456
        options[:id] = @ptables[options[:name]]
457
        if !options[:id]
458
          ptable = @api.resource(:ptables).call(:index, {
459
                                                  :per_page => 999999,
460
                                                  'search' => "name=\"#{options[:name]}\""
461
                                                })['results']
462
          raise "Partition table '#{options[:name]}' not found" if !ptable || ptable.empty?
463
          options[:id] = ptable[0]['id']
464
          @ptables[options[:name]] = options[:id]
465
        end
466
        result = options[:id]
467
      elsif options[:id]
468
        return nil if options[:id].nil?
469
        options[:name] = @ptables.key(options[:id])
470
        if !options[:name]
471
          ptable = @api.resource(:ptables).call(:show, {'id' => options[:id]})
472
          options[:name] = ptable['name']
473
          @ptables[options[:name]] = options[:id]
474
        end
475
        result = options[:name]
476
      elsif !options[:name] && !options[:id]
477
        result = ''
478
      end
479

    
480
      result
481
    end
482

    
483
    def lifecycle_environment(organization, options = {})
484
      @lifecycle_environments ||= {}
485
      @lifecycle_environments[organization] ||= {
486
      }
487

    
488
      if options[:name]
489
        return nil if options[:name].nil? || options[:name].empty?
490
        options[:id] = @lifecycle_environments[organization][options[:name]]
491
        if !options[:id]
492
          @api.resource(:lifecycle_environments).call(:index, {
493
              :per_page => 999999,
494
              'organization_id' => foreman_organization(:name => organization)
495
          })['results'].each do |environment|
496
            @lifecycle_environments[organization][environment['name']] = environment['id']
497
          end
498
          options[:id] = @lifecycle_environments[organization][options[:name]]
499
          raise "Lifecycle environment '#{options[:name]}' not found" if !options[:id]
500
        end
501
        result = options[:id]
502
      else
503
        return nil if options[:id].nil?
504
        options[:name] = @lifecycle_environments.key(options[:id])
505
        if !options[:name]
506
          environment = @api.resource(:lifecycle_environments).call(:show, {'id' => options[:id]})
507
          raise "Lifecycle environment '#{options[:name]}' not found" if !environment || environment.empty?
508
          options[:name] = environment['name']
509
          @lifecycle_environments[options[:name]] = options[:id]
510
        end
511
        result = options[:name]
512
      end
513

    
514
      result
515
    end
516

    
517
    def katello_contentview(organization, options = {})
518
      @contentviews ||= {}
519
      @contentviews[organization] ||= {}
520

    
521
      if options[:name]
522
        return nil if options[:name].nil? || options[:name].empty?
523
        options[:id] = @contentviews[organization][options[:name]]
524
        if !options[:id]
525
          @api.resource(:content_views).call(:index, {
526
              :per_page => 999999,
527
              'organization_id' => foreman_organization(:name => organization)
528
          })['results'].each do |contentview|
529
            @contentviews[organization][contentview['name']] = contentview['id']
530
          end
531
          options[:id] = @contentviews[organization][options[:name]]
532
          raise "Content view '#{options[:name]}' not found" if !options[:id]
533
        end
534
        result = options[:id]
535
      else
536
        return nil if options[:id].nil?
537
        options[:name] = @contentviews.key(options[:id])
538
        if !options[:name]
539
          contentview = @api.resource(:content_views).call(:show, {'id' => options[:id]})
540
          raise "Puppet contentview '#{options[:name]}' not found" if !contentview || contentview.empty?
541
          options[:name] = contentview['name']
542
          @contentviews[options[:name]] = options[:id]
543
        end
544
        result = options[:name]
545
      end
546

    
547
      result
548
    end
549

    
550
    def katello_contentviewversion(organization, name, version='latest')
551
      @contentviewversions ||= {}
552
      @contentviewversions[organization] ||= {}
553
      versionname = "#{version}|#{name}"
554

    
555
      return nil if name.nil? || name.empty?
556
      id = @contentviewversions[organization][versionname]
557
      if !id
558
        contentview_id = katello_contentview(organization, :name => name)
559
        contentviewversions = @api.resource(:content_view_versions).call(:index, {
560
                                  :per_page => 999999,
561
                                  'content_view_id' => contentview_id
562
                              })['results'].sort { |a, b| a['created_at'] <=> b['created_at'] }
563
        if version == 'latest'
564
          @contentviewversions[organization][versionname] = contentviewversions[-1]['id']
565
        else
566
          contentviewversions.each do |contentviewversion|
567
            if contentviewversion['version'] == version.to_f
568
              @contentviewversions[organization][versionname] = contentviewversion['id']
569
            end
570
          end
571
        end
572
        id = @contentviewversions[organization][versionname]
573
        raise "Content view version '#{name}' with version '#{version}' not found" if !id
574
      end
575

    
576
      id
577
    end
578

    
579
    def katello_repository(organization, options = {})
580
      @repositories ||= {}
581
      @repositories[organization] ||= {}
582

    
583
      if options[:name]
584
        return nil if options[:name].nil? || options[:name].empty?
585
        options[:id] = @repositories[organization][options[:name]]
586
        if !options[:id]
587
          @api.resource(:repositories).call(:index, {
588
              :per_page => 999999,
589
              'organization_id' => foreman_organization(:name => organization)
590
          })['results'].each do |repository|
591
            @repositories[organization][repository['name']] = repository['id']
592
          end
593
          options[:id] = @repositories[organization][options[:name]]
594
          raise "Repository '#{options[:name]}' not found" if !options[:id]
595
        end
596
        result = options[:id]
597
      else
598
        return nil if options[:id].nil?
599
        options[:name] = @repositories.key(options[:id])
600
        if !options[:name]
601
          repository = @api.resource(:repositories).call(:show, {'id' => options[:id]})
602
          raise "Puppet repository '#{options[:name]}' not found" if !repository || repository.empty?
603
          options[:name] = repository['name']
604
          @repositoriesr[options[:name]] = options[:id]
605
        end
606
        result = options[:name]
607
      end
608

    
609
      result
610
    end
611

    
612
    def katello_subscription(organization, options = {})
613
      @subscriptions ||= {}
614
      @subscriptions[organization] ||= {}
615

    
616
      if options[:name]
617
        return nil if options[:name].nil? || options[:name].empty?
618
        options[:id] = @subscriptions[organization][options[:name]]
619
        if !options[:id]
620
          results = @api.resource(:subscriptions).call(:index, {
621
              :per_page => 999999,
622
              'organization_id' => foreman_organization(:name => organization),
623
              'search' => "name:\"#{options[:name]}\""
624
          })
625
          raise "No subscriptions match '#{options[:name]}'" if results['subtotal'] == 0
626
          raise "Too many subscriptions match '#{options[:name]}'" if results['subtotal'] > 1
627
          subscription = results['results'][0]
628
          @subscriptions[organization][options[:name]] = subscription['id']
629
          options[:id] = @subscriptions[organization][options[:name]]
630
          raise "Subscription '#{options[:name]}' not found" if !options[:id]
631
        end
632
        result = options[:id]
633
      else
634
        return nil if options[:id].nil?
635
        options[:name] = @subscriptions.key(options[:id])
636
        if !options[:name]
637
          subscription = @api.resource(:subscriptions).call(:show, {'id' => options[:id]})
638
          raise "Subscription '#{options[:name]}' not found" if !subscription || subscription.empty?
639
          options[:name] = subscription['name']
640
          @subscriptions[options[:name]] = options[:id]
641
        end
642
        result = options[:name]
643
      end
644

    
645
      result
646
    end
647

    
648
    def katello_hostcollection(organization, options = {})
649
      @hostcollections ||= {}
650
      @hostcollections[organization] ||= {}
651

    
652
      if options[:name]
653
        return nil if options[:name].nil? || options[:name].empty?
654
        options[:id] = @hostcollections[organization][options[:name]]
655
        if !options[:id]
656
          @api.resource(:host_collections).call(:index,
657
                  {
658
                    :per_page => 999999,
659
                    'organization_id' => foreman_organization(:name => organization),
660
                    'search' => search_string('host-collections',options[:name])
661
                  })['results'].each do |hostcollection|
662
            @hostcollections[organization][hostcollection['name']] = hostcollection['id'] if hostcollection
663
          end
664
          options[:id] = @hostcollections[organization][options[:name]]
665
          raise "Host collection '#{options[:name]}' not found" if !options[:id]
666
        end
667
        result = options[:id]
668
      else
669
        return nil if options[:id].nil?
670
        options[:name] = @hostcollections.key(options[:id])
671
        if !options[:name]
672
          hostcollection = @api.resource(:host_collections).call(:show, {'id' => options[:id]})
673
          raise "Host collection '#{options[:name]}' not found" if !hostcollection || hostcollection.empty?
674
          options[:name] = hostcollection['name']
675
          @hostcollections[options[:name]] = options[:id]
676
        end
677
        result = options[:name]
678
      end
679

    
680
      result
681
    end
682

    
683
    def katello_product(organization, options = {})
684
      @products ||= {}
685
      @products[organization] ||= {}
686

    
687
      if options[:name]
688
        return nil if options[:name].nil? || options[:name].empty?
689
        options[:id] = @products[organization][options[:name]]
690
        if !options[:id]
691
          @api.resource(:products).call(:index,
692
                  {
693
                    :per_page => 999999,
694
                    'organization_id' => foreman_organization(:name => organization),
695
                    'search' => search_string('host-collections',options[:name])
696
                  })['results'].each do |product|
697
            @products[organization][product['name']] = product['id'] if product
698
          end
699
          options[:id] = @products[organization][options[:name]]
700
          raise "Host collection '#{options[:name]}' not found" if !options[:id]
701
        end
702
        result = options[:id]
703
      else
704
        return nil if options[:id].nil?
705
        options[:name] = @products.key(options[:id])
706
        if !options[:name]
707
          product = @api.resource(:host_collections).call(:show, {'id' => options[:id]})
708
          raise "Host collection '#{options[:name]}' not found" if !product || product.empty?
709
          options[:name] = product['name']
710
          @products[options[:name]] = options[:id]
711
        end
712
        result = options[:name]
713
      end
714

    
715
      result
716
    end
717

    
718
    def build_os_name(name, major, minor)
719
      name += " #{major}" if major && major != ''
720
      name += ".#{minor}" if minor && minor != ''
721
      name
722
    end
723

    
724
    # "Red Hat 6.4" => "Red Hat", "6", "4"
725
    # "Red Hat 6"   => "Red Hat", "6", ''
726
    def split_os_name(name)
727
      tokens = name.split(' ')
728
      is_number = Float(tokens[-1]) rescue false
729
      if is_number
730
        (major, minor) = tokens[-1].split('.').flatten
731
        name = tokens[0...-1].join(' ')
732
      else
733
        name = tokens.join(' ')
734
      end
735
      [name, major || '', minor || '']
736
    end
737

    
738
    def export_column(object, name, field)
739
      return '' unless object[name]
740
      values = CSV.generate do |column|
741
        column << object[name].collect do |fields|
742
          fields[field]
743
        end
744
      end
745
      values.delete!("\n")
746
    end
747

    
748
    def collect_column(column)
749
      return [] if column.nil? || column.empty?
750
      CSV.parse_line(column, {:skip_blanks => true}).collect do |value|
751
        yield value
752
      end
753
    end
754

    
755
    def pluralize(name)
756
      case name
757
      when /smart_proxy/
758
        'smart_proxies'
759
      else
760
        "#{name}s"
761
      end
762
    end
763

    
764
    def associate_organizations(id, organizations, name)
765
      return if organizations.nil?
766

    
767
      associations ||= {}
768
      CSV.parse_line(organizations).each do |organization|
769
        organization_id = foreman_organization(:name => organization)
770
        if associations[organization].nil?
771
          associations[organization] = @api.resource(:organizations).call(:show, {'id' => organization_id})[pluralize(name)].collect do |reference_object|
772
            reference_object['id']
773
          end
774
        end
775
        associations[organization] += [id] if !associations[organization].include? id
776
        @api.resource(:organizations).call(:update, {
777
            'id' => organization_id,
778
            'organization' => {
779
                "#{name}_ids" => associations[organization]
780
            }
781
        })
782
      end if organizations && !organizations.empty?
783
    end
784

    
785
    def associate_locations(id, locations, name)
786
      return if locations.nil?
787

    
788
      associations ||= {}
789
      CSV.parse_line(locations).each do |location|
790
        location_id = foreman_location(:name => location)
791
        if associations[location].nil?
792
          associations[location] = @api.resource(:locations).call(:show, {'id' => location_id})[pluralize(name)].collect do |reference_object|
793
            reference_object['id']
794
          end
795
        end
796
        associations[location] += [id] if !associations[location].include? id
797

    
798
        @api.resource(:locations).call(:update, {
799
            'id' => location_id,
800
            'location' => {
801
                "#{name}_ids" => associations[location]
802
            }
803
        })
804
      end if locations && !locations.empty?
805
    end
806

    
807
    private
808

    
809
    def search_string(resource, name)
810
      operator = case resource
811
                 when "gpg-key", "sync-plan", "lifecycle-environment", "host-collections"
812
                   @server_status['version'] && @server_status['version'].match(/\A1\.6/) ? ':' : '='
813
                 else
814
                   ':'
815
                 end
816
      "name#{operator}\"#{name}\""
817
    end
818
  end
819
end