Project

General

Profile

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

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

1
# Copyright (c) 2013 Red Hat
2
#
3
# MIT License
4
#
5
# Permission is hereby granted, free of charge, to any person obtaining
6
# a copy of this software and associated documentation files (the
7
# "Software"), to deal in the Software without restriction, including
8
# without limitation the rights to use, copy, modify, merge, publish,
9
# distribute, sublicense, and/or sell copies of the Software, and to
10
# permit persons to whom the Software is furnished to do so, subject to
11
# the following conditions:
12
#
13
# The above copyright notice and this permission notice shall be
14
# included in all copies or substantial portions of the Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
#
24
#
25

    
26
require 'hammer_cli'
27
require 'katello_api'
28
require 'foreman_api'
29
require 'json'
30
require 'csv'
31

    
32
module HammerCLICsv
33
  class BaseCommand < HammerCLI::AbstractCommand
34

    
35
    NAME = 'Name'
36
    COUNT = 'Count'
37

    
38
    option ["-v", "--verbose"], :flag, "be verbose"
39
    option ['--threads'], 'THREAD_COUNT', 'Number of threads to hammer with', :default => 1
40
    option ['--csv-export'], :flag, 'Export current data instead of importing'
41
    option ['--csv-file'], 'FILE_NAME', 'CSV file (default to /dev/stdout with --csv-export, otherwise required)'
42
    option ['--server'], 'SERVER', 'Server URL'
43
    option ['-u', '--username'], 'USERNAME', 'Username to access server'
44
    option ['-p', '--password'], 'PASSWORD', 'Password to access server'
45

    
46
    def execute
47
      if !csv_file
48
        csv_file = '/dev/stdout' if csv_export? # TODO: how to get this to actually set value?
49
        signal_usage_error "--csv-file required" if !csv_file
50
      end
51

    
52
      @init_options = {
53
        :base_url => server   || HammerCLI::Settings.get(:host),
54
        :username => username || HammerCLI::Settings.get(:username),
55
        :password => password || HammerCLI::Settings.get(:password)
56
      }
57

    
58
      @k_system_api ||= KatelloApi::Resources::System.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
59
      @k_systemgroup_api ||= KatelloApi::Resources::SystemGroup.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
60
      @k_environment_api ||= KatelloApi::Resources::Environment.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
61
      @k_contentview_api ||= KatelloApi::Resources::ContentView.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
62
      @k_provider_api ||= KatelloApi::Resources::Provider.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
63
      @k_product_api ||= KatelloApi::Resources::Product.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
64
      @k_repository_api ||= KatelloApi::Resources::Repository.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
65
      @k_contentviewdefinition_api ||= KatelloApi::Resources::ContentViewDefinition.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
66
      @k_subscription_api ||= KatelloApi::Resources::Subscription.new(@init_options.merge({:base_url => "#{@init_options[:base_url]}"}))
67

    
68
      @f_architecture_api ||= ForemanApi::Resources::Architecture.new(@init_options)
69
      @f_domain_api ||= ForemanApi::Resources::Domain.new(@init_options)
70
      @f_environment_api ||= ForemanApi::Resources::Environment.new(@init_options)
71
      @f_host_api ||= ForemanApi::Resources::Host.new(@init_options)
72
      @f_operatingsystem_api ||= ForemanApi::Resources::OperatingSystem.new(@init_options)
73
      @f_organization_api ||= ForemanApi::Resources::Organization.new(@init_options)
74
      @f_partitiontable_api ||= ForemanApi::Resources::Ptable.new(@init_options)
75
      @f_puppetfacts_api ||= ForemanApi::Resources::FactValue.new(@init_options)
76
      @f_user_api ||= ForemanApi::Resources::User.new(@init_options)
77

    
78
      csv_export? ? export : import
79
      HammerCLI::EX_OK
80
    end
81

    
82
    def get_lines(filename)
83
      file = File.open(filename ,'r')
84
      contents = file.readlines
85
      file.close
86
      contents
87
    end
88

    
89
    def namify(name_format, number)
90
      if name_format.index('%')
91
        name_format % number
92
      else
93
        name_format
94
      end
95
    end
96

    
97
    def labelize(name)
98
      name.gsub(/[^a-z0-9\-_]/i, "_")
99
    end
100

    
101
    def thread_import(return_headers=false)
102
      csv = []
103
      CSV.foreach(csv_file, {:skip_blanks => true, :headers => :first_row, :return_headers => return_headers}) do |line|
104
        csv << line
105
      end
106
      lines_per_thread = csv.length/threads.to_i + 1
107
      splits = []
108

    
109
      threads.to_i.times do |current_thread|
110
        start_index = ((current_thread) * lines_per_thread).to_i
111
        finish_index = ((current_thread + 1) * lines_per_thread).to_i
112
        lines = csv[start_index...finish_index].clone
113
        splits << Thread.new do
114
          lines.each do |line|
115
            if line[NAME][0] != '#'
116
              yield line
117
            end
118
          end
119
        end
120
      end
121

    
122
      splits.each do |thread|
123
        thread.join
124
      end
125
    end
126

    
127
    def foreman_organization(options={})
128
      @organizations ||= {}
129

    
130
      if options[:name]
131
        return nil if options[:name].nil? || options[:name].empty?
132
        options[:id] = @organizations[options[:name]]
133
        if !options[:id]
134
          organization = @f_organization_api.index({'search' => "name=\"#{options[:name]}\""})[0]['results']
135
          raise RuntimeError.new("Organization '#{options[:name]}' not found") if !organization || organization.empty?
136
          options[:id] = organization[0]['id']
137
          @organizations[options[:name]] = options[:id]
138
        end
139
        result = options[:id]
140
      else
141
        return nil if options[:id].nil?
142
        options[:name] = @organizations.key(options[:id])
143
        if !options[:name]
144
          organization = @f_organization_api.show({'id' => options[:id]})[0]
145
          raise RuntimeError.new("Organization 'id=#{options[:id]}' not found") if !organization || organization.empty?
146
          options[:name] = organization['name']
147
          @organizations[options[:name]] = options[:id]
148
        end
149
        result = options[:name]
150
      end
151

    
152
      result
153
    end
154

    
155
    def foreman_environment(options={})
156
      @environments ||= {}
157

    
158
      if options[:name]
159
        return nil if options[:name].nil? || options[:name].empty?
160
        options[:id] = @environments[options[:name]]
161
        if !options[:id]
162
          environment = @f_environment_api.index({'search' => "name=\"#{options[:name]}\""})[0]['results']
163
          raise RuntimeError.new("Puppet environment '#{options[:name]}' not found") if !environment || environment.empty?
164
          options[:id] = environment[0]['id']
165
          @environments[options[:name]] = options[:id]
166
        end
167
        result = options[:id]
168
      else
169
        return nil if options[:id].nil?
170
        options[:name] = @environments.key(options[:id])
171
        if !options[:name]
172
          environment = @f_environment_api.show({'id' => options[:id]})[0]
173
          raise RuntimeError.new("Puppet environment '#{options[:name]}' not found") if !environment || environment.empty?
174
          options[:name] = environment['name']
175
          @environments[options[:name]] = options[:id]
176
        end
177
        result = options[:name]
178
      end
179

    
180
      result
181
    end
182

    
183
    def foreman_operatingsystem(options={})
184
      @operatingsystems ||= {}
185

    
186
      if options[:name]
187
        return nil if options[:name].nil? || options[:name].empty?
188
        options[:id] = @operatingsystems[options[:name]]
189
        if !options[:id]
190
          (osname, major, minor) = split_os_name(options[:name])
191
          search = "name=\"#{osname}\" and major=\"#{major}\" and minor=\"#{minor}\""
192
          operatingsystems = @f_operatingsystem_api.index({'search' => search})[0]['results']
193
          operatingsystem = operatingsystems[0]
194
          raise RuntimeError.new("Operating system '#{options[:name]}' not found") if !operatingsystem || operatingsystem.empty?
195
          options[:id] = operatingsystem['id']
196
          @operatingsystems[options[:name]] = options[:id]
197
        end
198
        result = options[:id]
199
      else
200
        return nil if options[:id].nil?
201
        options[:name] = @operatingsystems.key(options[:id])
202
        if !options[:name]
203
          operatingsystem = @f_operatingsystem_api.show({'id' => options[:id]})[0]
204
          raise RuntimeError.new("Operating system 'id=#{options[:id]}' not found") if !operatingsystem || operatingsystem.empty?
205
          options[:name] = build_os_name(operatingsystem['name'],
206
                                         operatingsystem['major'],
207
                                         operatingsystem['minor'])
208
          @operatingsystems[options[:name]] = options[:id]
209
        end
210
        result = options[:name]
211
      end
212

    
213
      result
214
    end
215

    
216
    def foreman_architecture(options={})
217
      @architectures ||= {}
218

    
219
      if options[:name]
220
        return nil if options[:name].nil? || options[:name].empty?
221
        options[:id] = @architectures[options[:name]]
222
        if !options[:id]
223
          architecture = @f_architecture_api.index({'search' => "name=\"#{options[:name]}\""})[0]['results']
224
          raise RuntimeError.new("Architecture '#{options[:name]}' not found") if !architecture || architecture.empty?
225
          options[:id] = architecture[0]['id']
226
          @architectures[options[:name]] = options[:id]
227
        end
228
        result = options[:id]
229
      else
230
        return nil if options[:id].nil?
231
        options[:name] = @architectures.key(options[:id])
232
        if !options[:name]
233
          architecture = @f_architecture_api.show({'id' => options[:id]})[0]
234
          raise RuntimeError.new("Architecture 'id=#{options[:id]}' not found") if !architecture || architecture.empty?
235
          options[:name] = architecture['name']
236
          @architectures[options[:name]] = options[:id]
237
        end
238
        result = options[:name]
239
      end
240

    
241
      result
242
    end
243

    
244
    def foreman_domain(options={})
245
      @domains ||= {}
246

    
247
      if options[:name]
248
        return nil if options[:name].nil? || options[:name].empty?
249
        options[:id] = @domains[options[:name]]
250
        if !options[:id]
251
          domain = @f_domain_api.index({'search' => "name=\"#{options[:name]}\""})[0]['results']
252
          raise RuntimeError.new("Domain '#{options[:name]}' not found") if !domain || domain.empty?
253
          options[:id] = domain[0]['id']
254
          @domains[options[:name]] = options[:id]
255
        end
256
        result = options[:id]
257
      else
258
        return nil if options[:id].nil?
259
        options[:name] = @domains.key(options[:id])
260
        if !options[:name]
261
          domain = @f_domain_api.show({'id' => options[:id]})[0]
262
          raise RuntimeError.new("Domain 'id=#{options[:id]}' not found") if !domain || domain.empty?
263
          options[:name] = domain['name']
264
          @domains[options[:name]] = options[:id]
265
        end
266
        result = options[:name]
267
      end
268

    
269
      result
270
    end
271

    
272
    def foreman_partitiontable(options={})
273
      @ptables ||= {}
274

    
275
      if options[:name]
276
        return nil if options[:name].nil? || options[:name].empty?
277
        options[:id] = @ptables[options[:name]]
278
        if !options[:id]
279
          ptable = @f_partitiontable_api.index({'search' => "name=\"#{options[:name]}\""})[0]['results']
280
          raise RuntimeError.new("Partition table '#{options[:name]}' not found") if !ptable || ptable.empty?
281
          options[:id] = ptable[0]['id']
282
          @ptables[options[:name]] = options[:id]
283
        end
284
        result = options[:id]
285
      elsif options[:id]
286
        return nil if options[:id].nil?
287
        options[:name] = @ptables.key(options[:id])
288
        if !options[:name]
289
          ptable = @f_partitiontable_api.show({'id' => options[:id]})[0]
290
          options[:name] = ptable['name']
291
          @ptables[options[:name]] = options[:id]
292
        end
293
        result = options[:name]
294
      elsif !options[:name] && !options[:id]
295
        result = ''
296
      end
297

    
298
      result
299
    end
300

    
301
    def katello_environment(organization, options={})
302
      @environments ||= {}
303
      @environments[organization] ||= {}
304

    
305
      if options[:name]
306
        return nil if options[:name].nil? || options[:name].empty?
307
        options[:id] = @environments[organization][options[:name]]
308
        if !options[:id]
309
          @k_environment_api.index({'organization_id' => organization})[0].each do |environment|
310
            @environments[organization][environment['environment']['name']] = environment['environment']['id']
311
          end
312
          options[:id] = @environments[organization][options[:name]]
313
          raise RuntimeError.new("Puppet environment '#{options[:name]}' not found") if !options[:id]
314
        end
315
        result = options[:id]
316
      else
317
        return nil if options[:id].nil?
318
        options[:name] = @environments.key(options[:id])
319
        if !options[:name]
320
          environment = @k_environment_api.show({'id' => options[:id]})[0]
321
          raise RuntimeError.new("Puppet environment '#{options[:name]}' not found") if !environment || environment.empty?
322
          options[:name] = environment['name']
323
          @environments[options[:name]] = options[:id]
324
        end
325
        result = options[:name]
326
      end
327

    
328
      result
329
    end
330

    
331
    def katello_contentview(organization, options={})
332
      @contentviews ||= {}
333
      @contentviews[organization] ||= {}
334

    
335
      if options[:name]
336
        return nil if options[:name].nil? || options[:name].empty?
337
        options[:id] = @contentviews[organization][options[:name]]
338
        if !options[:id]
339
          puts "CONTENTVIEWS=#{@k_contentview_api.index({'organization_id' => organization, 'environment_id' => 2, 'label' => 'Default_Organization_View'})[0]}"
340
          @k_contentview_api.index({
341
                                     'organization_id' => organization,
342
                                     'label' => options[:name]
343
                                   })[0].each do |contentview|
344
            puts contentview
345
            @contentviews[organization][contentview['contentview']['name']] = contentview['contentview']['id']
346
          end
347
          options[:id] = @contentviews[organization][options[:name]]
348
          raise RuntimeError.new("Puppet contentview '#{options[:name]}' not found") if !options[:id]
349
        end
350
        result = options[:id]
351
      else
352
        return nil if options[:id].nil?
353
        options[:name] = @contentviews.key(options[:id])
354
        if !options[:name]
355
          contentview = @k_contentview_api.show({'id' => options[:id]})[0]
356
          raise RuntimeError.new("Puppet contentview '#{options[:name]}' not found") if !contentview || contentview.empty?
357
          options[:name] = contentview['name']
358
          @contentviews[options[:name]] = options[:id]
359
        end
360
        result = options[:name]
361
      end
362

    
363
      result
364
    end
365

    
366
    def katello_subscription(organization, options={})
367
      @subscriptions ||= {}
368
      @subscriptions[organization] ||= {}
369

    
370
      if options[:name]
371
        return nil if options[:name].nil? || options[:name].empty?
372
        options[:id] = @subscriptions[organization][options[:name]]
373
        if !options[:id]
374
          puts @k_subscription_api.index({
375
                                           'organization_id' => organization,
376
                                           'search' => "product_id:#{options[:name]}"
377
                                         })[0]
378
          @k_subscription_api.index({
379
                                      'organization_id' => organization,
380
                                      'search' => "'product_id:#{name}'"
381
                                    })[0]['results'][0].each do |subscription|
382
            puts subscription
383
            @subscriptions[organization][subscription['subscription']['name']] = subscription['subscription']['id']
384
          end
385
          options[:id] = @subscriptions[organization][options[:name]]
386
          raise RuntimeError.new("Puppet subscription '#{options[:name]}' not found") if !options[:id]
387
        end
388
        result = options[:id]
389
      else
390
        return nil if options[:id].nil?
391
        options[:name] = @subscriptions.key(options[:id])
392
        if !options[:name]
393
          subscription = @k_subscription_api.show({'id' => options[:id]})[0]
394
          raise RuntimeError.new("Puppet subscription '#{options[:name]}' not found") if !subscription || subscription.empty?
395
          options[:name] = subscription['name']
396
          @subscriptions[options[:name]] = options[:id]
397
        end
398
        result = options[:name]
399
      end
400

    
401
      result
402
    end
403

    
404
    def build_os_name(name, major, minor)
405
      name += " #{major}" if major && major != ""
406
      name += ".#{minor}" if minor && minor != ""
407
      name
408
    end
409

    
410
    def split_os_name(name)
411
      (name, major, minor) = name.split(' ').collect {|s| s.split('.')}.flatten
412
      [name, major || "", minor || ""]
413
    end
414
  end
415
end