Project

General

Profile

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

hammer-cli-csv / lib / hammer_cli_csv / base.rb @ 0c7641a0

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
    HEADERS = {'Accept' => 'version=2,application/json'}
39

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

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

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

    
60
      @f_architecture_api ||= ForemanApi::Resources::Architecture.new(@init_options)
61
      @f_domain_api ||= ForemanApi::Resources::Domain.new(@init_options)
62
      @f_environment_api ||= ForemanApi::Resources::Environment.new(@init_options)
63
      @f_host_api ||= ForemanApi::Resources::Host.new(@init_options)
64
      @f_operatingsystem_api ||= ForemanApi::Resources::OperatingSystem.new(@init_options)
65
      @f_organization_api ||= ForemanApi::Resources::Organization.new(@init_options)
66
      @f_partitiontable_api ||= ForemanApi::Resources::Ptable.new(@init_options)
67
      @f_puppetfacts_api ||= ForemanApi::Resources::FactValue.new(@init_options)
68
      @f_user_api ||= ForemanApi::Resources::User.new(@init_options)
69
    end
70

    
71
    def get_lines(filename)
72
      file = File.open(filename ,'r')
73
      contents = file.readlines
74
      file.close
75
      contents
76
    end
77

    
78
    def namify(name_format, number)
79
      if name_format.index('%')
80
        name_format % number
81
      else
82
        name_format
83
      end
84
    end
85

    
86
    def thread_import(return_headers=false)
87
      csv = []
88
      CSV.foreach(csv_file, {:skip_blanks => true, :headers => :first_row, :return_headers => return_headers}) do |line|
89
        csv << line
90
      end
91
      lines_per_thread = csv.length/threads.to_i + 1
92
      splits = []
93

    
94
      threads.to_i.times do |current_thread|
95
        start_index = ((current_thread) * lines_per_thread).to_i
96
        finish_index = ((current_thread + 1) * lines_per_thread).to_i
97
        lines = csv[start_index...finish_index].clone
98
        splits << Thread.new do
99
          lines.each do |line|
100
            if line[NAME][0] != '#'
101
              yield line
102
            end
103
          end
104
        end
105
      end
106

    
107
      splits.each do |thread|
108
        thread.join
109
      end
110
    end
111

    
112
    def foreman_organization(options={})
113
      @organizations ||= {}
114

    
115
      if options[:name]
116
        return nil if options[:name].nil? || options[:name].empty?
117
        options[:id] = @organizations[options[:name]]
118
        if !options[:id]
119
          organization = @f_organization_api.index({'search' => "name=\"#{options[:name]}\""}, HEADERS)[0]
120
          raise RuntimeError.new("Organization '#{options[:name]}' not found") if !organization || organization.empty?
121
          options[:id] = organization[0]['id']
122
          @organizations[options[:name]] = options[:id]
123
        end
124
        result = options[:id]
125
      else
126
        return nil if options[:id].nil?
127
        options[:name] = @organizations.key(options[:id])
128
        if !options[:name]
129
          organization = @f_organization_api.show({'id' => options[:id]}, HEADERS)[0]
130
          raise RuntimeError.new("Organization 'id=#{options[:id]}' not found") if !organization || organization.empty?
131
          options[:name] = organization['name']
132
          @organizations[options[:name]] = options[:id]
133
        end
134
        result = options[:name]
135
      end
136

    
137
      result
138
    end
139

    
140
    def foreman_environment(options={})
141
      @environments ||= {}
142

    
143
      if options[:name]
144
        return nil if options[:name].nil? || options[:name].empty?
145
        options[:id] = @environments[options[:name]]
146
        if !options[:id]
147
          environment = @f_environment_api.index({'search' => "name=\"#{options[:name]}\""}, HEADERS)[0]
148
          raise RuntimeError.new("Puppet environment '#{options[:name]}' not found") if !environment || environment.empty?
149
          options[:id] = environment[0]['id']
150
          @environments[options[:name]] = options[:id]
151
        end
152
        result = options[:id]
153
      else
154
        return nil if options[:id].nil?
155
        options[:name] = @environments.key(options[:id])
156
        if !options[:name]
157
          environment = @f_environment_api.show({'id' => options[:id]}, HEADERS)[0]
158
          raise RuntimeError.new("Puppet environment '#{options[:name]}' not found") if !environment || environment.empty?
159
          options[:name] = environment['name']
160
          @environments[options[:name]] = options[:id]
161
        end
162
        result = options[:name]
163
      end
164

    
165
      result
166
    end
167

    
168
    def foreman_operatingsystem(options={})
169
      @operatingsystems ||= {}
170

    
171
      if options[:name]
172
        return nil if options[:name].nil? || options[:name].empty?
173
        options[:id] = @operatingsystems[options[:name]]
174
        if !options[:id]
175
          (osname, major, minor) = split_os_name(options[:name])
176
          search = "name=\"#{osname}\" and major=\"#{major}\" and minor=\"#{minor}\""
177
          operatingsystems = @f_operatingsystem_api.index({'search' => search}, HEADERS)[0]
178
          operatingsystem = operatingsystems[0]
179
          raise RuntimeError.new("Operating system '#{options[:name]}' not found") if !operatingsystem || operatingsystem.empty?
180
          options[:id] = operatingsystem['id']
181
          @operatingsystems[options[:name]] = options[:id]
182
        end
183
        result = options[:id]
184
      else
185
        return nil if options[:id].nil?
186
        options[:name] = @operatingsystems.key(options[:id])
187
        if !options[:name]
188
          operatingsystem = @f_operatingsystem_api.show({'id' => options[:id]}, HEADERS)[0]
189
          raise RuntimeError.new("Operating system 'id=#{options[:id]}' not found") if !operatingsystem || operatingsystem.empty?
190
          options[:name] = build_os_name(operatingsystem['name'],
191
                                         operatingsystem['major'],
192
                                         operatingsystem['minor'])
193
          @operatingsystems[options[:name]] = options[:id]
194
        end
195
        result = options[:name]
196
      end
197

    
198
      result
199
    end
200

    
201
    def foreman_architecture(options={})
202
      @architectures ||= {}
203

    
204
      if options[:name]
205
        return nil if options[:name].nil? || options[:name].empty?
206
        options[:id] = @architectures[options[:name]]
207
        if !options[:id]
208
          architecture = @f_architecture_api.index({'search' => "name=\"#{options[:name]}\""}, HEADERS)[0]
209
          raise RuntimeError.new("Architecture '#{options[:name]}' not found") if !architecture || architecture.empty?
210
          options[:id] = architecture[0]['id']
211
          @architectures[options[:name]] = options[:id]
212
        end
213
        result = options[:id]
214
      else
215
        return nil if options[:id].nil?
216
        options[:name] = @architectures.key(options[:id])
217
        if !options[:name]
218
          architecture = @f_architecture_api.show({'id' => options[:id]}, HEADERS)[0]
219
          raise RuntimeError.new("Architecture 'id=#{options[:id]}' not found") if !architecture || architecture.empty?
220
          options[:name] = architecture['name']
221
          @architectures[options[:name]] = options[:id]
222
        end
223
        result = options[:name]
224
      end
225

    
226
      result
227
    end
228

    
229
    def foreman_domain(options={})
230
      @domains ||= {}
231

    
232
      if options[:name]
233
        return nil if options[:name].nil? || options[:name].empty?
234
        options[:id] = @domains[options[:name]]
235
        if !options[:id]
236
          domain = @f_domain_api.index({'search' => "name=\"#{options[:name]}\""}, HEADERS)[0]
237
          raise RuntimeError.new("Domain '#{options[:name]}' not found") if !domain || domain.empty?
238
          options[:id] = domain[0]['id']
239
          @domains[options[:name]] = options[:id]
240
        end
241
        result = options[:id]
242
      else
243
        return nil if options[:id].nil?
244
        options[:name] = @domains.key(options[:id])
245
        if !options[:name]
246
          domain = @f_domain_api.show({'id' => options[:id]}, HEADERS)[0]
247
          raise RuntimeError.new("Domain 'id=#{options[:id]}' not found") if !domain || domain.empty?
248
          options[:name] = domain['name']
249
          @domains[options[:name]] = options[:id]
250
        end
251
        result = options[:name]
252
      end
253

    
254
      result
255
    end
256

    
257
    def foreman_partitiontable(options={})
258
      @ptables ||= {}
259

    
260
      if options[:name]
261
        return nil if options[:name].nil? || options[:name].empty?
262
        options[:id] = @ptables[options[:name]]
263
        if !options[:id]
264
          ptable = @f_partitiontable_api.index({'search' => "name=\"#{options[:name]}\""}, HEADERS)[0]
265
          raise RuntimeError.new("Partition table '#{options[:name]}' not found") if !ptable || ptable.empty?
266
          options[:id] = ptable[0]['id']
267
          @ptables[options[:name]] = options[:id]
268
        end
269
        result = options[:id]
270
      elsif options[:id]
271
        return nil if options[:id].nil?
272
        options[:name] = @ptables.key(options[:id])
273
        if !options[:name]
274
          ptable = @f_partitiontable_api.show({'id' => options[:id]}, HEADERS)[0]
275
          options[:name] = ptable['name']
276
          @ptables[options[:name]] = options[:id]
277
        end
278
        result = options[:name]
279
      elsif !options[:name] && !options[:id]
280
        result = ''
281
      end
282

    
283
      result
284
    end
285

    
286
    def build_os_name(name, major, minor)
287
      name += " #{major}" if major && major != ""
288
      name += ".#{minor}" if minor && minor != ""
289
      name
290
    end
291

    
292
    def split_os_name(name)
293
      (name, major, minor) = name.split(' ').collect {|s| s.split('.')}.flatten
294
      [name, major || "", minor || ""]
295
    end
296
  end
297
end