vagrant-vmware-esxi 1.3.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6c1b544be5e69be9aad5aa1d1eb7f7e47097f83
4
- data.tar.gz: 5cfd76a90f5f9a1a5fc8989b7a32b69b214a010d
3
+ metadata.gz: 75fa2ace89bcc2c6659e8631c3d411f51bf61805
4
+ data.tar.gz: '08d7be8b3342fcf22e379669760d6cf1e384bd6a'
5
5
  SHA512:
6
- metadata.gz: a288fc3eb3823e2763cf55d720889a87456cce474535a23233cfc0372f47aae956201df6de80fb0487fe0b09a7bbc3565704335909b96dc83a5b6861fffd3c9b
7
- data.tar.gz: 2dedd6fbc8d32a7b5c1d7f5d20b2214fbc27dfd2a4124552e685067a5429d1e493ed3064331a631c8781eab00e9f10a062b3fdd41945f18aad236bfa8954ce3d
6
+ metadata.gz: 33db21964f748b8379b336226cd710c85cbc9df4ba3be95d283743fa3ff7bc1513242868eee2d7665b4517765c57dd654aea3386ee83f6f6688c4371f57b0522
7
+ data.tar.gz: cadbb1dce75523116f6020cc931a637156e9cf0f61526d424fd2df73cd3a922c6b4cb079ac816ef48727ff883d772d22aca0c27e384b6a607a9290092b9cffa8
data/README.md CHANGED
@@ -139,10 +139,12 @@ Vagrant.configure("2") do |config|
139
139
 
140
140
  # HIGHLY RECOMMENDED! Virtual Network
141
141
  # You should specify a Virtual Network! If it's not specified, the
142
- # default is to use the first found.
143
- # You can specify up to 4 virtual networks using an array
144
- # format. Note that Vagrant only looks at the first
145
- # interface for a valid IP address.
142
+ # default is to use the first found. You can specify up to 4 virtual
143
+ # networks using an array format. Note that Vagrant only looks at the
144
+ # first interface for a valid IP address. BTW: This does not configure
145
+ # IP addresses. This specifies which ESXi virtual network to use for
146
+ # each network interface in your VM. For most OS's DHCP is the default,
147
+ # so, you will need a DHCP server for each virtual network.
146
148
  #esxi.virtual_network = "vmnet_example"
147
149
  #esxi.virtual_network = ["vmnet1","vmnet2","vmnet3","vmnet4"]
148
150
 
@@ -223,6 +225,7 @@ Known issues with vmware_esxi
223
225
 
224
226
  Version History
225
227
  ---------------
228
+ * 1.3.2 Fix, Don't timeout ssh connection when ovftool takes a long time to upload image.
226
229
  * 1.3.0 Add support to get esxi password from env, from a file or prompt.
227
230
  * 1.2.1 Encode special characters in password.
228
231
  * 1.2.0 Add support for up to 4 virtual networks.
@@ -90,9 +90,13 @@ Vagrant.configure("2") do |config|
90
90
  #esxi.esxi_hostport = 22
91
91
 
92
92
  # HIGHLY RECOMMENDED! Virtual Network
93
- # You should specify a Virtual Network!
94
- # The default is to use the first found!
95
- # You can specify up to 4 virtual networks using an array format.
93
+ # You should specify a Virtual Network! If it's not specified, the
94
+ # default is to use the first found. You can specify up to 4 virtual
95
+ # networks using an array format. Note that Vagrant only looks at the
96
+ # first interface for a valid IP address. BTW: This does not configure
97
+ # IP addresses. This specifies which ESXi virtual network to use for
98
+ # each network interface in your VM. For most OS's DHCP is the default,
99
+ # so, you will need a DHCP server for each virtual network.
96
100
  #esxi.virtual_network = "vmnet_example"
97
101
  #esxi.virtual_network = ["vmnet1","vmnet2","vmnet3","vmnet4"]
98
102
 
@@ -98,21 +98,21 @@ module VagrantPlugins
98
98
  end
99
99
 
100
100
  if availvolumes.include? desired_ds
101
- guestvm_dsname = desired_ds
101
+ @guestvm_dsname = desired_ds
102
102
  else
103
- guestvm_dsname = availvolumes.last
103
+ @guestvm_dsname = availvolumes.last
104
104
  end
105
105
 
106
- if (guestvm_dsname != desired_ds) &&
106
+ if (@guestvm_dsname != desired_ds) &&
107
107
  !config.vm_disk_store.nil?
108
108
  env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
109
109
  message: 'WARNING : '\
110
110
  "#{config.vm_disk_store} not "\
111
- "found, using #{guestvm_dsname}")
111
+ "found, using #{@guestvm_dsname}")
112
112
  end
113
113
 
114
114
  @logger.info('vagrant-vmware-esxi, createvm: '\
115
- "guestvm_dsname: #{guestvm_dsname}")
115
+ "@guestvm_dsname: #{@guestvm_dsname}")
116
116
 
117
117
  #
118
118
  # Figure out network
@@ -131,10 +131,10 @@ module VagrantPlugins
131
131
  "#{r.stderr}"
132
132
  end
133
133
 
134
- guestvm_network = []
134
+ @guestvm_network = []
135
135
  counter = 0
136
136
  if config.virtual_network.nil?
137
- guestvm_network[0] = availnetworks.first
137
+ @guestvm_network[0] = availnetworks.first
138
138
  env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
139
139
  message: 'WARNING : '\
140
140
  "config.virtual_network not "\
@@ -143,9 +143,9 @@ module VagrantPlugins
143
143
  networkID = 0
144
144
  for aVirtNet in Array(config.virtual_network) do
145
145
  if availnetworks.include? aVirtNet
146
- guestvm_network << aVirtNet
146
+ @guestvm_network << aVirtNet
147
147
  else
148
- guestvm_network << availnetworks.first
148
+ @guestvm_network << availnetworks.first
149
149
  env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
150
150
  message: 'WARNING : '\
151
151
  "#{aVirtNet} not "\
@@ -157,170 +157,182 @@ module VagrantPlugins
157
157
  end
158
158
  end
159
159
  end
160
+ end
160
161
 
161
- @logger.info('vagrant-vmware-esxi, createvm: '\
162
- "virtual_network: #{guestvm_network}")
162
+ @logger.info('vagrant-vmware-esxi, createvm: '\
163
+ "virtual_network: #{@guestvm_network}")
163
164
 
164
- # finalize some paramaters
165
- if (config.memsize.is_a? String) || (config.memsize.is_a? Integer)
166
- desired_memsize = config.memsize.to_s.to_i
167
- end
168
- if (config.numvcpus.is_a? String) || (config.numvcpus.is_a? Integer)
169
- desired_numvcpus = config.numvcpus.to_s.to_i
170
- end
165
+ # finalize some paramaters
166
+ if (config.memsize.is_a? String) || (config.memsize.is_a? Integer)
167
+ desired_memsize = config.memsize.to_s.to_i
168
+ end
169
+ if (config.numvcpus.is_a? String) || (config.numvcpus.is_a? Integer)
170
+ desired_numvcpus = config.numvcpus.to_s.to_i
171
+ end
171
172
 
172
- #
173
- # Fix/clean up vmx file.
174
- #
175
- new_vmx_contents = ''
176
- File.readlines(vmx_file).each do |line|
177
-
178
- if line.match(/^displayname =/i)
179
- new_vmx_contents << "displayname = \"#{guestvm_vmname}\"\n"
180
- elsif line.match(/^memsize =/i) && (!desired_memsize.nil?)
181
- new_vmx_contents << "memsize = \"#{desired_memsize}\"\n"
182
- elsif line.match(/^numvcpus =/i) && (!desired_numvcpus.nil?)
183
- new_vmx_contents << "numvcpus = \"#{desired_numvcpus}\"\n"
184
- elsif line.match(/^ethernet[0-9].networkName =/i) ||
185
- line.match(/^ethernet[0-9].addressType =/i) ||
186
- line.match(/^ethernet[0-9].present =/i) ||
187
- line.match(/^ethernet[0-9].address =/i) ||
188
- line.match(/^ethernet[0-9].generatedAddress =/i) ||
189
- line.match(/^ethernet[0-9].generatedAddressOffset =/i)
190
- # Do nothing, delete these lines
191
- else
192
- new_vmx_contents << line
193
- end
173
+ #
174
+ # Fix/clean up vmx file.
175
+ #
176
+ new_vmx_contents = ''
177
+ File.readlines(vmx_file).each do |line|
178
+
179
+ if line.match(/^displayname =/i)
180
+ new_vmx_contents << "displayname = \"#{guestvm_vmname}\"\n"
181
+ elsif line.match(/^memsize =/i) && (!desired_memsize.nil?)
182
+ new_vmx_contents << "memsize = \"#{desired_memsize}\"\n"
183
+ elsif line.match(/^numvcpus =/i) && (!desired_numvcpus.nil?)
184
+ new_vmx_contents << "numvcpus = \"#{desired_numvcpus}\"\n"
185
+ elsif line.match(/^ethernet[0-9].networkName =/i) ||
186
+ line.match(/^ethernet[0-9].addressType =/i) ||
187
+ line.match(/^ethernet[0-9].present =/i) ||
188
+ line.match(/^ethernet[0-9].address =/i) ||
189
+ line.match(/^ethernet[0-9].generatedAddress =/i) ||
190
+ line.match(/^ethernet[0-9].generatedAddressOffset =/i)
191
+ # Do nothing, delete these lines
192
+ else
193
+ new_vmx_contents << line
194
194
  end
195
+ end
195
196
 
196
- # finalize vmx.
197
- unless new_vmx_contents =~ %r{^numvcpus =}i
198
- if desired_numvcpus.nil?
199
- new_vmx_contents << "numvcpus = \"1\"\n"
200
- else
201
- new_vmx_contents << "numvcpus = \"#{desired_numvcpus}\"\n"
202
- end
197
+ # finalize vmx.
198
+ unless new_vmx_contents =~ %r{^numvcpus =}i
199
+ if desired_numvcpus.nil?
200
+ new_vmx_contents << "numvcpus = \"1\"\n"
201
+ else
202
+ new_vmx_contents << "numvcpus = \"#{desired_numvcpus}\"\n"
203
203
  end
204
+ end
204
205
 
205
- # Append virt network options
206
- netOpts = ""
207
- networkID = 0
208
- for element in guestvm_network do
209
- if (config.debug =~ %r{true}i)
210
- puts "guestvm_network[#{networkID}]: #{element}"
211
- end
212
- new_vmx_contents << "ethernet#{networkID}.networkName = \"net#{networkID}\"\n"
213
- new_vmx_contents << "ethernet#{networkID}.present = \"TRUE\"\n"
214
- new_vmx_contents << "ethernet#{networkID}.addressType = \"generated\"\n"
215
- netOpts << " --net:\"net#{networkID}=#{element}\""
216
- networkID += 1
217
- if networkID >= 4
218
- break
219
- end
206
+ # Append virt network options
207
+ netOpts = ""
208
+ networkID = 0
209
+ for element in @guestvm_network do
210
+ if (config.debug =~ %r{true}i)
211
+ puts "@guestvm_network[#{networkID}]: #{element}"
212
+ end
213
+ new_vmx_contents << "ethernet#{networkID}.networkName = \"net#{networkID}\"\n"
214
+ new_vmx_contents << "ethernet#{networkID}.present = \"TRUE\"\n"
215
+ new_vmx_contents << "ethernet#{networkID}.addressType = \"generated\"\n"
216
+ netOpts << " --net:\"net#{networkID}=#{element}\""
217
+ networkID += 1
218
+ if networkID >= 4
219
+ break
220
220
  end
221
+ end
221
222
 
222
- # append custom_vmx_settings if exists
223
- if config.custom_vmx_settings.is_a? Array
224
- env[:machine].provider_config.custom_vmx_settings.each do |k, v|
225
- new_vmx_contents << "#{k} = \"#{v}\"\n"
226
- end
223
+ # append custom_vmx_settings if exists
224
+ if config.custom_vmx_settings.is_a? Array
225
+ env[:machine].provider_config.custom_vmx_settings.each do |k, v|
226
+ new_vmx_contents << "#{k} = \"#{v}\"\n"
227
227
  end
228
+ end
228
229
 
229
- # Write new vmx file
230
- filename_only = File.basename vmx_file, '.vmx'
231
- path_only = File.dirname vmx_file
232
- new_vmx_file = "#{path_only}/ZZZZ_#{guestvm_vmname}.vmx"
230
+ # Write new vmx file
231
+ filename_only = File.basename vmx_file, '.vmx'
232
+ path_only = File.dirname vmx_file
233
+ new_vmx_file = "#{path_only}/ZZZZ_#{guestvm_vmname}.vmx"
233
234
 
234
- File.open(new_vmx_file, 'w') { |file|
235
- file.write(new_vmx_contents)
236
- file.close
237
- }
235
+ File.open(new_vmx_file, 'w') { |file|
236
+ file.write(new_vmx_contents)
237
+ file.close
238
+ }
238
239
 
239
- #
240
- # Check if using a Resource Pool
241
- if config.resource_pool.is_a? String
242
- if config.resource_pool =~ %r{^\/}
243
- resource_pool = config.resource_pool
244
- else
245
- resource_pool = '/'
246
- resource_pool << config.resource_pool
247
- end
240
+ #
241
+ # Check if using a Resource Pool
242
+ if config.resource_pool.is_a? String
243
+ if config.resource_pool =~ %r{^\/}
244
+ resource_pool = config.resource_pool
248
245
  else
249
- resource_pool = ''
246
+ resource_pool = '/'
247
+ resource_pool << config.resource_pool
250
248
  end
249
+ else
250
+ resource_pool = ''
251
+ end
251
252
 
252
- if (config.allow_overwrite =~ %r{true}i) ||
253
- (config.allow_overwrite =~ %r{yes}i)
254
- overwrite_opts = '--overwrite --powerOffTarget'
255
- else
256
- overwrite_opts = nil
257
- end
253
+ if (config.allow_overwrite =~ %r{true}i) ||
254
+ (config.allow_overwrite =~ %r{yes}i)
255
+ overwrite_opts = '--overwrite --powerOffTarget'
256
+ else
257
+ overwrite_opts = nil
258
+ end
258
259
 
259
- #
260
- # Display build summary
261
- numvcpus = new_vmx_contents.match(/^numvcpus =.*/i)
262
- .to_s.gsub(/^numvcpus =/i, '').gsub(/\"/, '')
263
- memsize = new_vmx_contents.match(/^memsize =.*/i)
264
- .to_s.gsub(/^memsize =/i, '').gsub(/\"/, '')
265
- guestOS = new_vmx_contents.match(/^guestOS =.*/i)
266
- .to_s.gsub(/^guestOS =/i, '').gsub(/\"/, '')
267
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
268
- message: "ESXi host : #{config.esxi_hostname}")
269
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
270
- message: "VM Name : #{guestvm_vmname}")
271
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
272
- message: "CPUS :#{numvcpus}")
273
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
274
- message: "Memsize (MB) :#{memsize}")
275
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
276
- message: "Guest OS type :#{guestOS}")
277
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
278
- message: "Disk Store : #{guestvm_dsname}")
279
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
280
- message: "NetworkName : #{guestvm_network[0..3]}")
281
- unless overwrite_opts.nil?
282
- env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
283
- message: 'Allow Overwrite : True')
284
- end
260
+ #
261
+ # Display build summary
262
+ numvcpus = new_vmx_contents.match(/^numvcpus =.*/i)
263
+ .to_s.gsub(/^numvcpus =/i, '').gsub(/\"/, '')
264
+ memsize = new_vmx_contents.match(/^memsize =.*/i)
265
+ .to_s.gsub(/^memsize =/i, '').gsub(/\"/, '')
266
+ guestOS = new_vmx_contents.match(/^guestOS =.*/i)
267
+ .to_s.gsub(/^guestOS =/i, '').gsub(/\"/, '')
268
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
269
+ message: "ESXi host : #{config.esxi_hostname}")
270
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
271
+ message: "VM Name : #{guestvm_vmname}")
272
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
273
+ message: "CPUS :#{numvcpus}")
274
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
275
+ message: "Memsize (MB) :#{memsize}")
276
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
277
+ message: "Guest OS type :#{guestOS}")
278
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
279
+ message: "Disk Store : #{@guestvm_dsname}")
280
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
281
+ message: "NetworkName : #{@guestvm_network[0..3]}")
282
+ unless overwrite_opts.nil?
285
283
  env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
286
- message: "Resource Pool : #{resource_pool}")
284
+ message: 'Allow Overwrite : True')
285
+ end
286
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
287
+ message: "Resource Pool : #{resource_pool}")
287
288
 
288
- #
289
- # Using ovftool, import vmx in box folder, export to ESXi server
290
- #
291
- unless system 'ovftool --version'
292
- raise Errors::OVFToolError,
293
- message: 'ovftool not found or not in your path.'\
294
- " Please download and "\
295
- ' install from http://www.vmware.com.'
296
- end
297
- ovf_cmd = "ovftool --noSSLVerify #{overwrite_opts} "\
298
- "#{netOpts} -dm=thin --powerOn "\
299
- "-ds=\"#{guestvm_dsname}\" --name=\"#{guestvm_vmname}\" "\
300
- "\"#{new_vmx_file}\" vi://#{config.esxi_username}:"\
301
- "#{$encoded_esxi_password}@#{config.esxi_hostname}"\
302
- "#{resource_pool}"
303
-
304
- # Security bug if unremarked! Password will be exposed in log file.
305
- if (config.debug =~ %r{password}i)
306
- @logger.info("vagrant-vmware-esxi, createvm: ovf_cmd #{ovf_cmd}")
307
- puts "ovftool command: #{ovf_cmd}"
308
- end
309
- if (config.debug =~ %r{true}i)
310
- ovf_cmd_nopw = ovf_cmd.gsub(/#{$encoded_esxi_password}/, '******')
311
- puts "ovftool command: #{ovf_cmd_nopw}"
312
- end
313
- unless system "#{ovf_cmd}"
314
- raise Errors::OVFToolError, message: ''
315
- end
289
+ #
290
+ # Using ovftool, import vmx in box folder, export to ESXi server
291
+ #
292
+ unless system 'ovftool --version'
293
+ raise Errors::OVFToolError,
294
+ message: 'ovftool not found or not in your path.'\
295
+ " Please download and "\
296
+ ' install from http://www.vmware.com.'
297
+ end
298
+ ovf_cmd = "ovftool --noSSLVerify #{overwrite_opts} "\
299
+ "#{netOpts} -dm=thin --powerOn "\
300
+ "-ds=\"#{@guestvm_dsname}\" --name=\"#{guestvm_vmname}\" "\
301
+ "\"#{new_vmx_file}\" vi://#{config.esxi_username}:"\
302
+ "#{$encoded_esxi_password}@#{config.esxi_hostname}"\
303
+ "#{resource_pool}"
304
+
305
+ # Security bug if unremarked! Password will be exposed in log file.
306
+ if (config.debug =~ %r{password}i)
307
+ @logger.info("vagrant-vmware-esxi, createvm: ovf_cmd #{ovf_cmd}")
308
+ puts "ovftool command: #{ovf_cmd}"
309
+ end
310
+ if (config.debug =~ %r{true}i)
311
+ ovf_cmd_nopw = ovf_cmd.gsub(/#{$encoded_esxi_password}/, '******')
312
+ puts "ovftool command: #{ovf_cmd_nopw}"
313
+ end
314
+ unless system "#{ovf_cmd}"
315
+ raise Errors::OVFToolError, message: ''
316
+ end
316
317
 
317
- # VMX file is not needed any longer. Delete it
318
- if (config.debug =~ %r{true}i)
319
- puts "Keeping file: #{new_vmx_file}"
320
- else
321
- File.delete(new_vmx_file)
322
- end
318
+ # VMX file is not needed any longer. Delete it
319
+ if (config.debug =~ %r{true}i)
320
+ puts "Keeping file: #{new_vmx_file}"
321
+ else
322
+ File.delete(new_vmx_file)
323
+ end
323
324
 
325
+ #
326
+ # Re-open the network connection to get VMID
327
+ #
328
+ Net::SSH.start( config.esxi_hostname, config.esxi_username,
329
+ password: $esxi_password,
330
+ port: config.esxi_hostport,
331
+ keys: config.esxi_private_keys,
332
+ timeout: 10,
333
+ number_of_password_prompts: 0,
334
+ non_interactive: true
335
+ ) do |ssh|
324
336
  r = ssh.exec!(
325
337
  'vim-cmd vmsvc/getallvms |'\
326
338
  "grep \" #{guestvm_vmname} \"|awk '{print $1}'")
@@ -42,9 +42,11 @@ module VagrantPlugins
42
42
  password: $esxi_password,
43
43
  port: config.esxi_hostport,
44
44
  keys: config.esxi_private_keys,
45
- timeout: 60,
45
+ timeout: 10,
46
46
  number_of_password_prompts: 0,
47
- non_interactive: true
47
+ non_interactive: true,
48
+ keepalive: true,
49
+ keepalive_interval: 30
48
50
  ) do |ssh|
49
51
 
50
52
  r = ssh.exec!("vim-cmd vmsvc/power.on #{machine.id}")
@@ -38,9 +38,11 @@ module VagrantPlugins
38
38
  password: $esxi_password,
39
39
  port: config.esxi_hostport,
40
40
  keys: config.esxi_private_keys,
41
- timeout: 120,
41
+ timeout: 10,
42
42
  number_of_password_prompts: 0,
43
- non_interactive: true
43
+ non_interactive: true,
44
+ keepalive: true,
45
+ keepalive_interval: 30
44
46
  ) do |ssh|
45
47
 
46
48
  puts "machine id: #{machine.id} snapshot name: #{env[:snapshot_name]}"
@@ -41,9 +41,11 @@ module VagrantPlugins
41
41
  password: $esxi_password,
42
42
  port: config.esxi_hostport,
43
43
  keys: config.esxi_private_keys,
44
- timeout: 120,
44
+ timeout: 10,
45
45
  number_of_password_prompts: 0,
46
- non_interactive: true
46
+ non_interactive: true,
47
+ keepalive: true,
48
+ keepalive_interval: 30
47
49
  ) do |ssh|
48
50
 
49
51
  r = ssh.exec!("vim-cmd vmsvc/power.suspend #{machine.id}")
@@ -1,6 +1,6 @@
1
1
  # VERSION
2
2
  module VagrantPlugins
3
3
  module ESXi
4
- VERSION = '1.3.0'
4
+ VERSION = '1.3.2'
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-vmware-esxi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Senkerik