Project

General

Profile

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

hammer-cli-csv / lib / hammer_cli_csv / base.rb @ f92e695a

1
require 'apipie-bindings'
2
require 'hammer_cli'
3
require 'json'
4
require 'open-uri'
5
require 'csv'
6
require 'hammer_cli_csv/csv'
7

    
8
# rubocop:disable ClassLength
9
module HammerCLICsv
10
  class BaseCommand < HammerCLI::Apipie::Command
11
    include ::HammerCLICsv::Utils::Config
12

    
13
    option %w(-v --verbose), :flag, 'be verbose'
14
    option %w(--threads), 'THREAD_COUNT', 'Number of threads to hammer with',
15
           :default => 1, :hidden => true
16
    option %w(--export), :flag, 'Export current data instead of importing'
17
    option %w(--search), 'SEARCH', 'Only export search results'
18
    option %w(--file), 'FILE_NAME', 'CSV file (default to /dev/stdout with --export, otherwise required)'
19
    option %w(--prefix), 'PREFIX', 'Prefix for all name columns',
20
           :hidden => true
21
    option %w(--organization), 'ORGANIZATION', _('Only process organization matching this name')
22
    option %w(--continue-on-error), :flag, _('Continue processing even if individual resource error')
23

    
24
    option %w(--csv-file), 'FILE_NAME', 'Option --csv-file is deprecated. Use --file',
25
           :deprecated => "Use --file", :hidden => true,
26
           :attribute_name => :option_file
27
    option %w(--csv-export), :flag, 'Option --csv-export is deprecated. Use --export',
28
           :deprecated => "Use --export", :hidden => true,
29
           :attribute_name => :option_export
30

    
31
    NAME = 'Name'
32
    COUNT = 'Count'
33

    
34
    def self.supported?
35
      false
36
    end
37

    
38
    def supported?
39
      self.class.supported?
40
    end
41

    
42
    def help
43
      print_message _('**** This command is unsupported and is provided as tech preview. ****') unless supported?
44
      super + self.class.help_columns
45
    end
46

    
47
    def self.help_columns
48
      ''
49
    end
50

    
51
    def execute
52
      @api = api_connection
53
      @server_status = check_server_status(@server)
54

    
55
      if option_export?
56
        if option_file
57
          CSV.open(option_file, 'wb', {:force_quotes => false}) do |csv|
58
            export csv
59
          end
60
        else
61
          CSV do |csv|
62
            export csv
63
          end
64
        end
65
      else
66
        import
67
      end
68
      HammerCLI::EX_OK
69
    end
70

    
71
    def authenticate_request(request)
72
      if HammerCLI.context[:api_connection]
73
        HammerCLIForeman.foreman_api_connection.authenticator.authenticate(request, {})
74
      else
75
        request.basic_auth(
76
          HammerCLIForeman.credentials.username,
77
          HammerCLIForeman.credentials.password
78
        )
79
      end
80
      request
81
    end
82

    
83
    def check_server_status(server)
84
      url = "#{server}/api/status"
85
      uri = URI(url)
86
      nethttp = Net::HTTP.new(uri.host, uri.port)
87
      nethttp.use_ssl = uri.scheme == 'https'
88
      nethttp.verify_mode = OpenSSL::SSL::VERIFY_NONE
89
      server_status = nethttp.start do |http|
90
        request = Net::HTTP::Get.new uri
91
        authenticate_request(request)
92
        response = http.request(request)
93
        JSON.parse(response.body)
94
      end
95

    
96
      url = "#{server}/api/v2/plugins"
97
      uri = URI(url)
98
      nethttp = Net::HTTP.new(uri.host, uri.port)
99
      nethttp.use_ssl = uri.scheme == 'https'
100
      nethttp.verify_mode = OpenSSL::SSL::VERIFY_NONE
101
      server_status['plugins'] = nethttp.start do |http|
102
        request = Net::HTTP::Get.new uri
103
        authenticate_request(request)
104
        response = http.request(request)
105
        JSON.parse(response.body)['results']
106
      end
107

    
108
      server_status
109
    end
110

    
111
    def namify(name_format, number = 0)
112
      return '' unless name_format
113
      if name_format.index('%')
114
        name = name_format % number
115
      else
116
        name = name_format
117
      end
118
      name = "#{option_prefix}#{name}" if option_prefix
119
      name
120
    end
121

    
122
    def labelize(name)
123
      name.gsub(/[^a-z0-9\-_]/i, '_')
124
    end
125

    
126
    def thread_import(return_headers = false, filename=nil, name_column=nil)
127
      filename ||= option_file || '/dev/stdin'
128
      csv = []
129
      CSV.new(open(filename), {
130
          :skip_blanks => true,
131
          :headers => :first_row,
132
          :return_headers => return_headers
133
      }).each do |line|
134
        csv << line
135
      end
136
      lines_per_thread = csv.length / option_threads.to_i + 1
137
      splits = []
138

    
139
      option_threads.to_i.times do |current_thread|
140
        start_index = ((current_thread) * lines_per_thread).to_i
141
        finish_index = ((current_thread + 1) * lines_per_thread).to_i
142
        finish_index = csv.length if finish_index > csv.length
143
        if start_index <= finish_index
144
          lines = csv[start_index...finish_index].clone
145
          splits << Thread.new do
146
            lines.each do |line|
147
              next if !line[name_column || NAME].nil? && line[name_column || NAME][0] == '#'
148
              begin
149
                logger.debug(line)
150
                yield line
151
              rescue RuntimeError => e
152
                message = "#{e}\n#{line}"
153
                option_continue_on_error? ? $stderr.puts(_("Error: %{message}") % {:message => message}) : raise(message)
154
              end
155
            end
156
          end
157
        end
158
      end
159

    
160
      splits.each do |thread|
161
        thread.join
162
      end
163
    end
164

    
165
    def hammer_context
166
      {
167
        :interactive => false,
168
        :username => 'admin', # TODO: this needs to come from config/settings
169
        :password => 'changeme' # TODO: this needs to come from config/settings
170
      }
171
    end
172

    
173
    def hammer(context = nil)
174
      HammerCLI::MainCommand.new('', context || hammer_context)
175
    end
176

    
177
    def foreman_organization(options = {})
178
      @organizations ||= {}
179

    
180
      if options[:name]
181
        return nil if options[:name].nil? || options[:name].empty?
182
        options[:id] = @organizations[options[:name]]
183
        if !options[:id]
184
          organization = @api.resource(:organizations).call(:index, {
185
                                                              :per_page => 999999,
186
                                                              'search' => "name=\"#{options[:name]}\""
187
                                                            })['results']
188
          raise _("Organization '%{name}' not found") % {:name => options[:name]} if !organization || organization.empty?
189
          options[:id] = organization[0]['id']
190
          @organizations[options[:name]] = options[:id]
191
        end
192
        result = options[:id]
193
      else
194
        return nil if options[:id].nil?
195
        options[:name] = @organizations.key(options[:id])
196
        if !options[:name]
197
          organization = @api.resource(:organizations).call(:show, {'id' => options[:id]})
198
          raise _("Organization 'id=%{id}' not found") % {:id => options[:id]} if !organization || organization.empty?
199
          options[:name] = organization['name']
200
          @organizations[options[:name]] = options[:id]
201
        end
202
        result = options[:name]
203
      end
204

    
205
      result
206
    end
207

    
208
    def foreman_location(options = {})
209
      @locations ||= {}
210

    
211
      if options[:name]
212
        return nil if options[:name].nil? || options[:name].empty?
213
        options[:id] = @locations[options[:name]]
214
        if !options[:id]
215
          location = @api.resource(:locations).call(:index, {
216
                                                      :per_page => 999999,
217
                                                      'search' => "name=\"#{options[:name]}\""
218
                                                    })['results']
219
          raise _("Location '%{name}' not found") % {:name => options[:name]} if !location || location.empty?
220
          options[:id] = location[0]['id']
221
          @locations[options[:name]] = options[:id]
222
        end
223
        result = options[:id]
224
      else
225
        return nil if options[:id].nil?
226
        options[:name] = @locations.key(options[:id])
227
        if !options[:name]
228
          location = @api.resource(:locations).call(:show, {'id' => options[:id]})
229
          raise _("Location 'id=%{id}' not found") % {:id => options[:id]} if !location || location.empty?
230
          options[:name] = location['name']
231
          @locations[options[:name]] = options[:id]
232
        end
233
        result = options[:name]
234
      end
235

    
236
      result
237
    end
238

    
239
    def foreman_role(options = {})
240
      @roles ||= {}
241

    
242
      if options[:name]
243
        return nil if options[:name].nil? || options[:name].empty?
244
        options[:id] = @roles[options[:name]]
245
        if !options[:id]
246
          role = @api.resource(:roles).call(:index, {
247
                                              :per_page => 999999,
248
                                              'search' => "name=\"#{options[:name]}\""
249
                                            })['results']
250
          raise _("Role '%{name}' not found") % {:name => options[:name]} if !role || role.empty?
251
          options[:id] = role[0]['id']
252
          @roles[options[:name]] = options[:id]
253
        end
254
        result = options[:id]
255
      else
256
        return nil if options[:id].nil?
257
        options[:name] = @roles.key(options[:id])
258
        if !options[:name]
259
          role = @api.resource(:roles).call(:show, {'id' => options[:id]})
260
          raise _("Role 'id=%{id}' not found") % {:id => options[:id]} if !role || role.empty?
261
          options[:name] = role['name']
262
          @roles[options[:name]] = options[:id]
263
        end
264
        result = options[:name]
265
      end
266

    
267
      result
268
    end
269

    
270
    def foreman_permission(options = {})
271
      @permissions ||= {}
272

    
273
      if options[:name]
274
        return nil if options[:name].nil? || options[:name].empty?
275
        options[:id] = @permissions[options[:name]]
276
        if !options[:id]
277
          permission = @api.resource(:permissions).call(:index, {
278
                                                          :per_page => 999999,
279
                                                          'name' => options[:name]
280
                                                        })['results']
281
          raise _("Permission '%{name}' not found") % {:name => options[:name]} if !permission || permission.empty?
282
          options[:id] = permission[0]['id']
283
          @permissions[options[:name]] = options[:id]
284
        end
285
        result = options[:id]
286
      else
287
        return nil if options[:id].nil?
288
        options[:name] = @permissions.key(options[:id])
289
        if !options[:name]
290
          permission = @api.resource(:permissions).call(:show, {'id' => options[:id]})
291
          raise _("Permission 'id=%{id}' not found") % {:id => options[:id]} if !permission || permission.empty?
292
          options[:name] = permission['name']
293
          @permissions[options[:name]] = options[:id]
294
        end
295
        result = options[:name]
296
      end
297

    
298
      result
299
    end
300

    
301
    def foreman_filter(role, resource, search)
302
      search = nil if search && search.empty?
303
      filters = @api.resource(:filters).call(:index, {
304
                                               :per_page => 999999,
305
                                               'search' => "role=\"#{role}\""
306
                                             })['results']
307
      filters.each do |filter|
308
        resource_type = (filter['resource_type'] || '').split(':')[-1] # To remove "Katello::" when present
309
        return filter['id'] if resource_type == resource && filter['search'] == search
310
      end
311

    
312
      nil
313
    end
314

    
315
    def foreman_environment(options = {})
316
      @environments ||= {}
317

    
318
      if options[:name]
319
        return nil if options[:name].nil? || options[:name].empty?
320
        options[:id] = @environments[options[:name]]
321
        if !options[:id]
322
          environment = @api.resource(:environments).call(:index, {
323
                                                            :per_page => 999999,
324
                                                            'search' => "name=\"#{ options[:name] }\""
325
                                                          })['results']
326
          raise _("Puppet environment '%{name}' not found") % {:name => options[:name]} if !environment || environment.empty?
327
          options[:id] = environment[0]['id']
328
          @environments[options[:name]] = options[:id]
329
        end
330
        result = options[:id]
331
      else
332
        return nil if options[:id].nil?
333
        options[:name] = @environments.key(options[:id])
334
        if !options[:name]
335
          environment = @api.resource(:environments).call(:show, {'id' => options[:id]})
336
          raise _("Puppet environment 'id=%{id}' not found") % {:id => options[:id]} if !environment || environment.empty?
337
          options[:name] = environment['name']
338
          @environments[options[:name]] = options[:id]
339
        end
340
        result = options[:name]
341
      end
342

    
343
      result
344
    end
345

    
346
    def foreman_template_kind(options = {})
347
      @template_kinds ||= {}
348

    
349
      if options[:name]
350
        return nil if options[:name].nil? || options[:name].empty?
351
        options[:id] = @template_kinds[options[:name]]
352
        if !options[:id]
353
          template_kind = @api.resource(:template_kinds).call(:index, {
354
                                              :per_page => 999999,
355
                                              'search' => "name=\"#{options[:name]}\""
356
                                            })['results']
357
          raise _("Template kind '%{name}' not found") % {:name => options[:name]} if !template_kind || template_kind.empty?
358
          options[:id] = template_kind[0]['id']
359
          @template_kinds[options[:name]] = options[:id]
360
        end
361
        result = options[:id]
362
      else
363
        return nil if options[:id].nil?
364
        options[:name] = @template_kinds.key(options[:id])
365
        if !options[:name]
366
          template_kind = @api.resource(:template_kinds).call(:show, {'id' => options[:id]})
367
          raise _("Template kind 'id=%{id}' not found") % {:id => options[:id]} if !template_kind || template_kind.empty?
368
          options[:name] = template_kind['name']
369
          @template_kinds[options[:name]] = options[:id]
370
        end
371
        result = options[:name]
372
      end
373

    
374
      result
375
    end
376

    
377
    def foreman_operatingsystem(options = {})
378
      @operatingsystems ||= {}
379

    
380
      if options[:name]
381
        return nil if options[:name].nil? || options[:name].empty?
382
        options[:id] = @operatingsystems[options[:name]]
383
        if !options[:id]
384
          (osname, major, minor) = split_os_name(options[:name])
385
          search = "name=\"#{osname}\" and major=\"#{major}\" and minor=\"#{minor}\""
386
          operatingsystems = @api.resource(:operatingsystems).call(:index, {
387
                                                                     :per_page => 999999,
388
                                                                     'search' => search
389
                                                                   })['results']
390
          operatingsystem = operatingsystems[0]
391
          raise _("Operating system '%{name}' not found") % {:name => options[:name]} if !operatingsystem || operatingsystem.empty?
392
          options[:id] = operatingsystem['id']
393
          @operatingsystems[options[:name]] = options[:id]
394
        end
395
        result = options[:id]
396
      else
397
        return nil if options[:id].nil?
398
        options[:name] = @operatingsystems.key(options[:id])
399
        if !options[:name]
400
          operatingsystem = @api.resource(:operatingsystems).call(:show, {'id' => options[:id]})
401
          raise _("Operating system 'id=%{id}' not found") % {:id => options[:id]} if !operatingsystem || operatingsystem.empty?
402
          options[:name] = build_os_name(operatingsystem['name'],
403
                                         operatingsystem['major'],
404
                                         operatingsystem['minor'])
405
          @operatingsystems[options[:name]] = options[:id]
406
        end
407
        result = options[:name]
408
      end
409

    
410
      result
411
    end
412

    
413
    def foreman_architecture(options = {})
414
      @architectures ||= {}
415

    
416
      if options[:name]
417
        return nil if options[:name].nil? || options[:name].empty?
418
        options[:id] = @architectures[options[:name]]
419
        if !options[:id]
420
          architecture = @api.resource(:architectures).call(:index, {
421
                                                              :per_page => 999999,
422
                                                              'search' => "name=\"#{options[:name]}\""
423
                                                            })['results']
424
          raise _("Architecture '%{name}' not found") % {:name => options[:name]} if !architecture || architecture.empty?
425
          options[:id] = architecture[0]['id']
426
          @architectures[options[:name]] = options[:id]
427
        end
428
        result = options[:id]
429
      else
430
        return nil if options[:id].nil?
431
        options[:name] = @architectures.key(options[:id])
432
        if !options[:name]
433
          architecture = @api.resource(:architectures).call(:show, {'id' => options[:id]})
434
          raise _("Architecture 'id=%{id}' not found") % {:id => options[:id]} if !architecture || architecture.empty?
435
          options[:name] = architecture['name']
436
          @architectures[options[:name]] = options[:id]
437
        end
438
        result = options[:name]
439
      end
440

    
441
      result
442
    end
443

    
444
    def foreman_domain(options = {})
445
      @domains ||= {}
446

    
447
      if options[:name]
448
        return nil if options[:name].nil? || options[:name].empty?
449
        options[:id] = @domains[options[:name]]
450
        if !options[:id]
451
          domain = @api.resource(:domains).call(:index, {
452
                                                  :per_page => 999999,
453
                                                  'search' => "name=\"#{options[:name]}\""
454
                                                })['results']
455
          raise _("Domain '%{name}' not found") % {:name => options[:name]} if !domain || domain.empty?
456
          options[:id] = domain[0]['id']
457
          @domains[options[:name]] = options[:id]
458
        end
459
        result = options[:id]
460
      else
461
        return nil if options[:id].nil?
462
        options[:name] = @domains.key(options[:id])
463
        if !options[:name]
464
          domain = @api.resource(:domains).call(:show, {'id' => options[:id]})
465
          raise _("Domain 'id=%{id}' not found") % {:id => options[:id]} if !domain || domain.empty?
466
          options[:name] = domain['name']
467
          @domains[options[:name]] = options[:id]
468
        end
469
        result = options[:name]
470
      end
471

    
472
      result
473
    end
474

    
475
    def foreman_partitiontable(options = {})
476
      @ptables ||= {}
477

    
478
      if options[:name]
479
        return nil if options[:name].nil? || options[:name].empty?
480
        options[:id] = @ptables[options[:name]]
481
        if !options[:id]
482
          ptable = @api.resource(:ptables).call(:index, {
483
                                                  :per_page => 999999,
484
                                                  'search' => "name=\"#{options[:name]}\""
485
                                                })['results']
486
          raise _("Partition table '%{name}' not found") % {:name => options[:name]} if !ptable || ptable.empty?
487
          options[:id] = ptable[0]['id']
488
          @ptables[options[:name]] = options[:id]
489
        end
490
        result = options[:id]
491
      elsif options[:id]
492
        return nil if options[:id].nil?
493
        options[:name] = @ptables.key(options[:id])
494
        if !options[:name]
495
          ptable = @api.resource(:ptables).call(:show, {'id' => options[:id]})
496
          options[:name] = ptable['name']
497
          @ptables[options[:name]] = options[:id]
498
        end
499
        result = options[:name]
500
      elsif !options[:name] && !options[:id]
501
        result = ''
502
      end
503

    
504
      result
505
    end
506

    
507
    def foreman_medium(options = {})
508
      @media ||= {}
509

    
510
      if options[:name]
511
        return nil if options[:name].nil? || options[:name].empty?
512
        options[:id] = @media[options[:name]]
513
        if !options[:id]
514
          ptable = @api.resource(:media).call(:index, {
515
                                                  :per_page => 999999,
516
                                                  'search' => "name=\"#{options[:name]}\""
517
                                                })['results']
518
          raise _("Partition table '%{name}' not found") % {:name => options[:name]} if !ptable || ptable.empty?
519
          options[:id] = ptable[0]['id']
520
          @media[options[:name]] = options[:id]
521
        end
522
        result = options[:id]
523
      elsif options[:id]
524
        return nil if options[:id].nil?
525
        options[:name] = @media.key(options[:id])
526
        if !options[:name]
527
          ptable = @api.resource(:media).call(:show, {'id' => options[:id]})
528
          options[:name] = ptable['name']
529
          @media[options[:name]] = options[:id]
530
        end
531
        result = options[:name]
532
      elsif !options[:name] && !options[:id]
533
        result = ''
534
      end
535

    
536
      result
537
    end
538

    
539
    def foreman_host(options = {})
540
      @query_hosts ||= {}
541

    
542
      if options[:name]
543
        return nil if options[:name].nil? || options[:name].empty?
544
        options[:id] = @query_hosts[options[:name]]
545
        if !options[:id]
546
          host = @api.resource(:hosts).call(:index, {
547
                                              :per_page => 999999,
548
                                              'search' => "name=\"#{options[:name]}\""
549
                                            })['results']
550
          raise _("Host '%{name}' not found") % {:name => options[:name]} if !host || host.empty?
551
          options[:id] = host[0]['id']
552
          @query_hosts[options[:name]] = options[:id]
553
        end
554
        result = options[:id]
555
      else
556
        return nil if options[:id].nil?
557
        options[:name] = @query_hosts.key(options[:id])
558
        if !options[:name]
559
          host = @api.resource(:hosts).call(:show, {'id' => options[:id]})
560
          raise _("Host 'id=%{id}' not found") % {:id => options[:id]} if !host || host.empty?
561
          options[:name] = host['name']
562
          @query_hosts[options[:name]] = options[:id]
563
        end
564
        result = options[:name]
565
      end
566

    
567
      result
568
    end
569

    
570
    def foreman_hostgroup(options = {})
571
      @query_hostgroups ||= {}
572

    
573
      if options[:name]
574
        return nil if options[:name].nil? || options[:name].empty?
575
        options[:id] = @query_hostgroups[options[:name]]
576
        if !options[:id]
577
          hostgroup = @api.resource(:hostgroups).call(:index, {
578
                                              :per_page => 999999,
579
                                              'search' => "name=\"#{options[:name]}\""
580
                                            })['results']
581
          raise _("Host Group '%{name}' not found") % {:name => options[:name]} if !hostgroup || hostgroup.empty?
582
          options[:id] = hostgroup[0]['id']
583
          @query_hostgroups[options[:name]] = options[:id]
584
        end
585
        result = options[:id]
586
      else
587
        return nil if options[:id].nil?
588
        options[:name] = @query_hostgroups.key(options[:id])
589
        if !options[:name]
590
          hostgroup = @api.resource(:hostgroups).call(:show, {'id' => options[:id]})
591
          raise _("Host Group 'id=%{id}' not found") % {:id => options[:id]} if !hostgroup || hostgroup.empty?
592
          options[:name] = hostgroup['name']
593
          @query_hostgroups[options[:name]] = options[:id]
594
        end
595
        result = options[:name]
596
      end
597

    
598
      result
599
    end
600

    
601
    def foreman_provisioning_template(options = {})
602
      @query_config_templates ||= {}
603

    
604
      if options[:name]
605
        return nil if options[:name].nil? || options[:name].empty?
606
        options[:id] = @query_config_templates[options[:name]]
607
        if !options[:id]
608
          config_template = @api.resource(:config_templates).call(:index, {
609
                                              :per_page => 999999,
610
                                              'search' => "name=\"#{options[:name]}\""
611
                                            })['results']
612
          raise _("Provisioning template '%{name}' not found") % {:name => options[:name]} if !config_template || config_template.empty?
613
          options[:id] = config_template[0]['id']
614
          @query_config_templates[options[:name]] = options[:id]
615
        end
616
        result = options[:id]
617
      else
618
        return nil if options[:id].nil?
619
        options[:name] = @query_config_templates.key(options[:id])
620
        if !options[:name]
621
          config_template = @api.resource(:config_templates).call(:show, {'id' => options[:id]})
622
          raise _("Provisioning template 'id=%{id}' not found") % {:id => options[:id]} if !config_template || config_template.empty?
623
          options[:name] = config_template['name']
624
          @query_config_templates[options[:name]] = options[:id]
625
        end
626
        result = options[:name]
627
      end
628

    
629
      result
630
    end
631

    
632
    def foreman_smart_proxy(options = {})
633
      @query_smart_proxies ||= {}
634

    
635
      if options[:name]
636
        return nil if options[:name].nil? || options[:name].empty?
637
        options[:id] = @query_smart_proxies[options[:name]]
638
        if !options[:id]
639
          smart_proxy = @api.resource(:smart_proxies).call(:index, {
640
                                              :per_page => 999999,
641
                                              'search' => "name=\"#{options[:name]}\""
642
                                            })['results']
643
          raise _("Smart Proxy '%{name}' not found") % {:name => options[:name]} if !smart_proxy || smart_proxy.empty?
644
          options[:id] = smart_proxy[0]['id']
645
          @query_smart_proxies[options[:name]] = options[:id]
646
        end
647
        result = options[:id]
648
      else
649
        return nil if options[:id].nil?
650
        options[:name] = @query_smart_proxies.key(options[:id])
651
        if !options[:name]
652
          smart_proxy = @api.resource(:smart_proxies).call(:show, {'id' => options[:id]})
653
          raise _("Smart Proxy 'id=%{id}' not found") % {:id => options[:id]} if !smart_proxy || smart_proxy.empty?
654
          options[:name] = smart_proxy['name']
655
          @query_smart_proxies[options[:name]] = options[:id]
656
        end
657
        result = options[:name]
658
      end
659

    
660
      result
661
    end
662

    
663
    def lifecycle_environment(organization, options = {})
664
      @lifecycle_environments ||= {}
665
      @lifecycle_environments[organization] ||= {
666
      }
667

    
668
      if options[:name]
669
        return nil if options[:name].nil? || options[:name].empty?
670
        options[:id] = @lifecycle_environments[organization][options[:name]]
671
        if !options[:id]
672
          @api.resource(:lifecycle_environments).call(:index, {
673
              :per_page => 999999,
674
              'organization_id' => foreman_organization(:name => organization)
675
          })['results'].each do |environment|
676
            @lifecycle_environments[organization][environment['name']] = environment['id']
677
          end
678
          options[:id] = @lifecycle_environments[organization][options[:name]]
679
          raise _("Lifecycle environment '%{name}' not found") % {:name => options[:name]} if !options[:id]
680
        end
681
        result = options[:id]
682
      else
683
        return nil if options[:id].nil?
684
        options[:name] = @lifecycle_environments.key(options[:id])
685
        if !options[:name]
686
          environment = @api.resource(:lifecycle_environments).call(:show, {'id' => options[:id]})
687
          raise _("Lifecycle environment '%{name}' not found") % {:name => options[:name]} if !environment || environment.empty?
688
          options[:name] = environment['name']
689
          @lifecycle_environments[options[:name]] = options[:id]
690
        end
691
        result = options[:name]
692
      end
693

    
694
      result
695
    end
696

    
697
    def katello_contentview(organization, options = {})
698
      @contentviews ||= {}
699
      @contentviews[organization] ||= {}
700

    
701
      if options[:name]
702
        return nil if options[:name].nil? || options[:name].empty?
703
        options[:id] = @contentviews[organization][options[:name]]
704
        if !options[:id]
705
          @api.resource(:content_views).call(:index, {
706
              :per_page => 999999,
707
              'organization_id' => foreman_organization(:name => organization)
708
          })['results'].each do |contentview|
709
            @contentviews[organization][contentview['name']] = contentview['id']
710
          end
711
          options[:id] = @contentviews[organization][options[:name]]
712
          raise _("Content view '%{name}' not found") % {:name => options[:name]} if !options[:id]
713
        end
714
        result = options[:id]
715
      else
716
        return nil if options[:id].nil?
717
        options[:name] = @contentviews.key(options[:id])
718
        if !options[:name]
719
          contentview = @api.resource(:content_views).call(:show, {'id' => options[:id]})
720
          raise _("Puppet contentview 'id=%{id}' not found") % {:id => options[:id]} if !contentview || contentview.empty?
721
          options[:name] = contentview['name']
722
          @contentviews[options[:name]] = options[:id]
723
        end
724
        result = options[:name]
725
      end
726

    
727
      result
728
    end
729

    
730
    def katello_contentviewversion(organization, name, version='latest')
731
      @contentviewversions ||= {}
732
      @contentviewversions[organization] ||= {}
733
      versionname = "#{version}|#{name}"
734

    
735
      return nil if name.nil? || name.empty?
736
      id = @contentviewversions[organization][versionname]
737
      if !id
738
        contentview_id = katello_contentview(organization, :name => name)
739
        contentviewversions = @api.resource(:content_view_versions).call(:index, {
740
                                  :per_page => 999999,
741
                                  'content_view_id' => contentview_id
742
                              })['results'].sort { |a, b| a['created_at'] <=> b['created_at'] }
743
        if version == 'latest'
744
          @contentviewversions[organization][versionname] = contentviewversions[-1]['id']
745
        else
746
          contentviewversions.each do |contentviewversion|
747
            if contentviewversion['version'] == version.to_f
748
              @contentviewversions[organization][versionname] = contentviewversion['id']
749
            end
750
          end
751
        end
752
        id = @contentviewversions[organization][versionname]
753
        raise _("Content view version '%{name}' with version '%{version}' not found") % {:name => name, :version => version} if !id
754
      end
755

    
756
      id
757
    end
758

    
759
    def katello_repository(organization, options = {})
760
      @repositories ||= {}
761
      @repositories[organization] ||= {}
762

    
763
      if options[:name]
764
        return nil if options[:name].nil? || options[:name].empty?
765
        options[:id] = @repositories[organization][options[:name]]
766
        if !options[:id]
767
          @api.resource(:repositories).call(:index, {
768
              :per_page => 999999,
769
              'organization_id' => foreman_organization(:name => organization)
770
          })['results'].each do |repository|
771
            @repositories[organization][repository['name']] = repository['id']
772
          end
773
          options[:id] = @repositories[organization][options[:name]]
774
          raise _("Repository '%{name}' not found") % {:name => options[:name]} if !options[:id]
775
        end
776
        result = options[:id]
777
      else
778
        return nil if options[:id].nil?
779
        options[:name] = @repositories.key(options[:id])
780
        if !options[:name]
781
          repository = @api.resource(:repositories).call(:show, {'id' => options[:id]})
782
          raise _("Puppet repository 'id=%{id}' not found") % {:id => options[:id]} if !repository || repository.empty?
783
          options[:name] = repository['name']
784
          @repositoriesr[options[:name]] = options[:id]
785
        end
786
        result = options[:name]
787
      end
788

    
789
      result
790
    end
791

    
792
    def katello_hostcollection(organization, options = {})
793
      @hostcollections ||= {}
794
      @hostcollections[organization] ||= {}
795

    
796
      if options[:name]
797
        return nil if options[:name].nil? || options[:name].empty?
798
        options[:id] = @hostcollections[organization][options[:name]]
799
        if !options[:id]
800
          @api.resource(:host_collections).call(:index,
801
                  {
802
                    :per_page => 999999,
803
                    'organization_id' => foreman_organization(:name => organization),
804
                    'search' => search_string('host-collections',options[:name])
805
                  })['results'].each do |hostcollection|
806
            @hostcollections[organization][hostcollection['name']] = hostcollection['id'] if hostcollection
807
          end
808
          options[:id] = @hostcollections[organization][options[:name]]
809
          raise _("Host collection '%{name}' not found") % {:name => options[:name]} if !options[:id]
810
        end
811
        result = options[:id]
812
      else
813
        return nil if options[:id].nil?
814
        options[:name] = @hostcollections.key(options[:id])
815
        if !options[:name]
816
          hostcollection = @api.resource(:host_collections).call(:show, {'id' => options[:id]})
817
          raise _("Host collection 'id=%{id}' not found") % {:id => options[:id]} if !hostcollection || hostcollection.empty?
818
          options[:name] = hostcollection['name']
819
          @hostcollections[options[:name]] = options[:id]
820
        end
821
        result = options[:name]
822
      end
823

    
824
      result
825
    end
826

    
827
    def katello_product(organization, options = {})
828
      @products ||= {}
829
      @products[organization] ||= {}
830

    
831
      if options[:name]
832
        return nil if options[:name].nil? || options[:name].empty?
833
        options[:id] = @products[organization][options[:name]]
834
        if !options[:id]
835
          @api.resource(:products).call(:index,
836
                  {
837
                    :per_page => 999999,
838
                    'organization_id' => foreman_organization(:name => organization),
839
                    'search' => search_string('host-collections',options[:name])
840
                  })['results'].each do |product|
841
            @products[organization][product['name']] = product['id'] if product
842
          end
843
          options[:id] = @products[organization][options[:name]]
844
          raise _("Host collection '%{name}' not found") % {:name => options[:name]} if !options[:id]
845
        end
846
        result = options[:id]
847
      else
848
        return nil if options[:id].nil?
849
        options[:name] = @products.key(options[:id])
850
        if !options[:name]
851
          product = @api.resource(:host_collections).call(:show, {'id' => options[:id]})
852
          raise _("Host collection 'id=%{id}' not found") % {:id => options[:id]} if !product || product.empty?
853
          options[:name] = product['name']
854
          @products[options[:name]] = options[:id]
855
        end
856
        result = options[:name]
857
      end
858

    
859
      result
860
    end
861

    
862
    def foreman_container(options = {})
863
      @containers ||= {}
864

    
865
      if options[:name]
866
        return nil if options[:name].nil? || options[:name].empty?
867
        options[:id] = @containers[options[:name]]
868
        if !options[:id]
869
          container = @api.resource(:containers).call(:index, {
870
                                                       :per_page => 999999,
871
                                                       'search' => "name=\"#{options[:name]}\""
872
                                                     })['results']
873
          raise _("Container '%{name}' not found") % {:name => options[:name]} if !container || container.empty?
874
          options[:id] = container[0]['id']
875
          @containers[options[:name]] = options[:id]
876
        end
877
        result = options[:id]
878
      else
879
        return nil if options[:id].nil?
880
        options[:name] = @containers.key(options[:id])
881
        if !options[:name]
882
          container = @api.resource(:containers).call(:show, {'id' => options[:id]})
883
          raise _("Container 'id=%{id}' not found") % {:id => options[:id]} if !container || container.empty?
884
          options[:name] = container['name']
885
          @containers[options[:name]] = options[:id]
886
        end
887
        result = options[:name]
888
      end
889

    
890
      result
891
    end
892

    
893

    
894
    def build_os_name(name, major, minor)
895
      name += " #{major}" if major && major != ''
896
      name += ".#{minor}" if minor && minor != ''
897
      name
898
    end
899

    
900
    # "Red Hat 6.4" => "Red Hat", "6", "4"
901
    # "Red Hat 6"   => "Red Hat", "6", ''
902
    def split_os_name(name)
903
      tokens = name.split(' ')
904
      is_number = Float(tokens[-1]) rescue false
905
      if is_number
906
        (major, minor) = tokens[-1].split('.').flatten
907
        name = tokens[0...-1].join(' ')
908
      else
909
        name = tokens.join(' ')
910
      end
911
      [name, major || '', minor || '']
912
    end
913

    
914
    def export_column(object, name, field=nil)
915
      return '' unless object[name]
916
      values = CSV.generate do |column|
917
        column << object[name].collect do |fields|
918
          field.nil? ? yield(fields) : fields[field]
919
        end
920
      end
921
      values.delete!("\n")
922
    end
923

    
924
    def collect_column(column)
925
      return [] if column.nil? || column.empty?
926
      CSV.parse_line(column, {:skip_blanks => true}).collect do |value|
927
        yield value
928
      end
929
    end
930

    
931
    def pluralize(name)
932
      case name
933
      when /smart_proxy/
934
        'smart_proxies'
935
      else
936
        "#{name}s"
937
      end
938
    end
939

    
940
    def associate_organizations(id, organizations, name)
941
      return if organizations.nil?
942

    
943
      associations ||= {}
944
      CSV.parse_line(organizations).each do |organization|
945
        organization_id = foreman_organization(:name => organization)
946
        if associations[organization].nil?
947
          associations[organization] = @api.resource(:organizations).call(:show, {'id' => organization_id})[pluralize(name)].collect do |reference_object|
948
            reference_object['id']
949
          end
950
        end
951
        associations[organization] += [id] if !associations[organization].include? id
952
        @api.resource(:organizations).call(:update, {
953
            'id' => organization_id,
954
            'organization' => {
955
                "#{name}_ids" => associations[organization]
956
            }
957
        })
958
      end if organizations && !organizations.empty?
959
    end
960

    
961
    def associate_locations(id, locations, name)
962
      return if locations.nil?
963

    
964
      associations ||= {}
965
      CSV.parse_line(locations).each do |location|
966
        location_id = foreman_location(:name => location)
967
        if associations[location].nil?
968
          associations[location] = @api.resource(:locations).call(:show, {'id' => location_id})[pluralize(name)].collect do |reference_object|
969
            reference_object['id']
970
          end
971
        end
972
        associations[location] += [id] if !associations[location].include? id
973

    
974
        @api.resource(:locations).call(:update, {
975
            'id' => location_id,
976
            'location' => {
977
                "#{name}_ids" => associations[location]
978
            }
979
        })
980
      end if locations && !locations.empty?
981
    end
982

    
983
    def apipie_check_param(resource, action, name)
984
      method = @api.resource(pluralize(resource).to_sym).apidoc[:methods].detect do |api_method|
985
        api_method[:name] == action.to_s
986
      end
987
      return false unless method
988

    
989
      found = method[:params].detect do |param|
990
        param[:full_name] == name
991
      end
992
      if !found
993
        nested =  method[:params].detect do |param|
994
          param[:name] == resource.to_s
995
        end
996
        if nested
997
          found = nested[:params].detect do |param|
998
            param[:full_name] == name
999
          end
1000
        end
1001
      end
1002
      found
1003
    end
1004

    
1005
    def count(value)
1006
      return 1 if value.nil? || value.empty?
1007
      value.to_i
1008
    end
1009

    
1010
    private
1011

    
1012
    def search_string(resource, name)
1013
      operator = case resource
1014
                 when "gpg-key", "sync-plan", "lifecycle-environment", "host-collections"
1015
                   @server_status['version'] && @server_status['version'].match(/\A1\.6/) ? ':' : '='
1016
                 else
1017
                   ':'
1018
                 end
1019
      "name#{operator}\"#{name}\""
1020
    end
1021
  end
1022
end