fog-vsphere 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2802cab39cda0d34fbf317a0ef39e79b53a7ce20fd736e2f41ac86e0d95f494b
4
- data.tar.gz: d173548894fdfed4a4c517e1e6b30b513420b2bf59be77ce1147350ba695a15f
3
+ metadata.gz: d5281df844dc5370c7eeb4aa1b6d062edc780650cfa26143ef122a9f719b1305
4
+ data.tar.gz: ddd9c2dfe8393e74aa74267406f23638047f52ae426dcb98b30d0db64666e5d2
5
5
  SHA512:
6
- metadata.gz: 62ec056eb0f333a9a80eb1d4ec523cb2e5f8893d8b0cdd9f5243210a920b2acfeeaa74dd5fe00770b5eb77bd5a255167dde730b8f89b257e1d8891133803e1e6
7
- data.tar.gz: 4ac64f5bca359eb6e6290d137e1975644929f4eee39e0ad5f48d6c7fb2f58d8f6a235d557efe5bb26f1e0bfc98f88321a199b78bbf6b195aa92c3459e7b9bfd9
6
+ metadata.gz: cf18dc5cee08a4be3919c5473237ad83ba609d95868891dd7afb43d8d0aacd4d89ff05f211e3a89e25610aa3b5ee0da75f846fbbfdd7a3d1e3b9301d860f7586
7
+ data.tar.gz: 597988c88827a950b9ff4ab4363c344f72ebca5833cae3397358ddab8fae9f4f63813c8fa54826c3c2956e0469898165e582f4ef17406c22bd95d1b9c1fd34fd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## v2.4.0
2
+ * improve folder loading performance (#158)
3
+ * improve storage pod loading performance (#160)
4
+ * improve datastore loading performance (#159)
5
+ * prevent hard fail on undefined legacy networks (#157)
6
+ * add support to create vms on NSX-T networks (#153)
7
+ * set the server for fog volume objects (#152)
8
+ * add server guard to unit_number calculation (#152)
9
+
1
10
  ## v2.3.0
2
11
  * set volume unit_number when cloning a vm (#151)
3
12
  * add unclustered esxi hosts back to cluster selection (#149)
data/CONTRIBUTING.md CHANGED
@@ -1,18 +1,18 @@
1
- ## Getting Involved
1
+ # Getting Involved
2
2
 
3
3
  New contributors are always welcome, when it doubt please ask questions. We strive to be an open and welcoming community. Please be nice to one another.
4
4
 
5
- ### Coding
5
+ ## Coding
6
6
 
7
- * Pick a task:
8
- * Offer feedback on open [pull requests](https://github.com/fog/fog-vsphere/pulls).
9
- * Review open [issues](https://github.com/fog/fog-vsphere/issues) for things to help on.
10
- * [Create an issue](https://github.com/fog/fog-vsphere/issues/new) to start a discussion on additions or features.
11
- * Fork the project, add your changes and tests to cover them in a topic branch.
12
- * Commit your changes and rebase against `fog/fog-vsphere` to ensure everything is up to date.
13
- * [Submit a pull request](https://github.com/fog/fog-vsphere/compare/)
7
+ - Pick a task:
8
+ - Offer feedback on open [pull requests](https://github.com/fog/fog-vsphere/pulls).
9
+ - Review open [issues](https://github.com/fog/fog-vsphere/issues) for things to help on.
10
+ - [Create an issue](https://github.com/fog/fog-vsphere/issues/new) to start a discussion on additions or features.
11
+ - Fork the project, add your changes and tests to cover them in a topic branch.
12
+ - Commit your changes and rebase against `fog/fog-vsphere` to ensure everything is up to date.
13
+ - [Submit a pull request](https://github.com/fog/fog-vsphere/compare/)
14
14
 
15
- ### Non-Coding
15
+ ## Non-Coding
16
16
 
17
- * Offer feedback on open [issues](https://github.com/fog/fog-vsphere/issues).
18
- * Organize or volunteer at events.
17
+ - Offer feedback on open [issues](https://github.com/fog/fog-vsphere/issues).
18
+ - Organize or volunteer at events.
data/README.md CHANGED
@@ -1,11 +1,8 @@
1
1
  # Fog vSphere
2
+
2
3
  > VMware vSphere® provider for the Fog cloud services library
3
4
 
4
- [![Gem Version][gemfury-image]][gemfury-url]
5
- [![Build Status][travis-image]][travis-url]
6
- [![Dependency Status][gemnasium-image]][gemnasium-url]
7
- [![Test Coverage][coverage-image]][coverage-url]
8
- [![Code Climate][climate-image]][climate-url]
5
+ [![Gem Version][gemfury-image]][gemfury-url] [![Build Status][travis-image]][travis-url] [![Test Coverage][coverage-image]][coverage-url] [![Code Climate][climate-image]][climate-url]
9
6
 
10
7
  The VMware vSphere® provider allows you to use the abstractions of the Fog cloud services library to communicate with vSphere.
11
8
 
@@ -91,7 +88,5 @@ To contribute to this project, add an issue or pull request. For more info on wh
91
88
  [coverage-url]: https://codeclimate.com/github/fog/fog-vsphere/coverage
92
89
  [gemfury-image]: https://badge.fury.io/rb/fog-vsphere.svg
93
90
  [gemfury-url]: http://badge.fury.io/rb/fog-vsphere
94
- [gemnasium-image]: https://gemnasium.com/fog/fog-vsphere.svg
95
- [gemnasium-url]: https://gemnasium.com/fog/fog-vsphere
96
91
  [travis-image]: https://travis-ci.org/fog/fog-vsphere.svg?branch=master
97
92
  [travis-url]: https://travis-ci.org/fog/fog-vsphere
@@ -344,7 +344,14 @@ module Fog
344
344
 
345
345
  def initialize_volumes
346
346
  if attributes[:volumes] && attributes[:volumes].is_a?(Array)
347
- attributes[:volumes].map! { |vol| vol.is_a?(Hash) ? service.volumes.new({ server: self }.merge(vol)) : vol }
347
+ attributes[:volumes].map! do |vol|
348
+ if vol.is_a?(Hash)
349
+ service.volumes.new({ server: self }.merge(vol))
350
+ else
351
+ vol.server = self
352
+ vol
353
+ end
354
+ end
348
355
  end
349
356
  end
350
357
 
@@ -98,6 +98,7 @@ module Fog
98
98
  end
99
99
 
100
100
  def set_unit_number
101
+ requires :server
101
102
  # When adding volumes to vsphere, if our unit_number is 7 or higher, vsphere will increment the unit_number
102
103
  # This is due to SCSI ID 7 being reserved for the pvscsi controller
103
104
  # When referring to a volume that already added using a unit_id of 7 or higher, we must refer to the actual SCSI ID
@@ -31,7 +31,7 @@ module Fog
31
31
  get_raw_host(attributes[:host], attributes[:cluster], attributes[:datacenter])
32
32
  end
33
33
  # if any volume has a storage_pod set, we deploy the vm on a storage pod instead of the defined datastores
34
- pod = get_storage_pod(attributes)
34
+ pod = get_storage_pod_from_volumes(attributes)
35
35
  vm = if pod
36
36
  create_vm_on_storage_pod(pod, vm_cfg, vmFolder, resource_pool, attributes[:datacenter], host)
37
37
  else
@@ -73,7 +73,7 @@ module Fog
73
73
 
74
74
  # check if a storage pool is set on any of the volumes and return the first result found or nil
75
75
  # return early if vsphere revision is lower than 5 as this is not supported
76
- def get_storage_pod(attributes)
76
+ def get_storage_pod_from_volumes(attributes)
77
77
  return unless @vsphere_rev.to_f >= 5
78
78
  volume = attributes[:volumes].detect { |volume| !(volume.storage_pod.nil? || volume.storage_pod.empty?) }
79
79
  volume.storage_pod if volume
@@ -83,7 +83,7 @@ module Fog
83
83
  # by default we prefer to keep it at the same place the (first) vmdk is located
84
84
  # if we deploy the vm on a storage pool, we have to return an empty string
85
85
  def vm_path_name(attributes)
86
- return '' if get_storage_pod(attributes)
86
+ return '' if get_storage_pod_from_volumes(attributes)
87
87
  datastore = attributes[:volumes].first.datastore unless attributes[:volumes].empty?
88
88
  datastore ||= 'datastore1'
89
89
  "[#{datastore}]"
@@ -100,7 +100,7 @@ module Fog
100
100
  end
101
101
 
102
102
  if (disks = attributes[:volumes])
103
- devices << disks.map { |disk| create_disk(disk, :add, storage_pod: get_storage_pod(attributes)) }
103
+ devices << disks.map { |disk| create_disk(disk, :add, storage_pod: get_storage_pod_from_volumes(attributes)) }
104
104
  end
105
105
 
106
106
  if (cdroms = attributes[:cdroms])
@@ -171,6 +171,12 @@ module Fog
171
171
  switchUuid: raw_network.config.distributedVirtualSwitch.uuid
172
172
  )
173
173
  )
174
+ elsif raw_network.is_a? RbVmomi::VIM::OpaqueNetwork
175
+ RbVmomi::VIM.VirtualEthernetCardOpaqueNetworkBackingInfo(
176
+ opaqueNetworkType: raw_network.summary.opaqueNetworkType,
177
+ opaqueNetworkId: raw_network.summary.opaqueNetworkId
178
+ )
179
+
174
180
  else
175
181
  RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(deviceName: nic.network)
176
182
  end
@@ -10,8 +10,12 @@ module Fog
10
10
 
11
11
  protected
12
12
 
13
- def get_raw_cluster(name, datacenter_name)
14
- dc = find_raw_datacenter(datacenter_name)
13
+ def get_raw_cluster(name, datacenter_name_or_obj)
14
+ dc = if datacenter_name_or_obj.is_a?(String)
15
+ find_raw_datacenter(datacenter_name_or_obj)
16
+ else
17
+ datacenter_name_or_obj
18
+ end
15
19
  dc.find_compute_resource(name)
16
20
  end
17
21
  end
@@ -3,9 +3,9 @@ module Fog
3
3
  class Vsphere
4
4
  class Real
5
5
  def get_datastore(name, datacenter_name)
6
- datastore = get_raw_datastore(name, datacenter_name)
6
+ datastore = list_datastores(datacenter: datacenter_name).detect { |ds| ds[:name] == name }
7
7
  raise(Fog::Compute::Vsphere::NotFound) unless datastore
8
- datastore_attributes(datastore, datacenter_name)
8
+ datastore
9
9
  end
10
10
 
11
11
  protected
@@ -52,7 +52,7 @@ module Fog
52
52
  name: folder.name,
53
53
  parent: folder.parent.name,
54
54
  datacenter: datacenter_name,
55
- type: folder_type(folder),
55
+ type: folder_type(folder.childType),
56
56
  path: folder_path(folder)
57
57
  }
58
58
  end
@@ -61,8 +61,7 @@ module Fog
61
61
  '/' + folder.path.map(&:last).join('/')
62
62
  end
63
63
 
64
- def folder_type(folder)
65
- types = folder.childType
64
+ def folder_type(types)
66
65
  return :vm if types.include?('VirtualMachine')
67
66
  return :network if types.include?('Network')
68
67
  return :datastore if types.include?('Datastore')
@@ -3,9 +3,9 @@ module Fog
3
3
  class Vsphere
4
4
  class Real
5
5
  def get_storage_pod(name, datacenter_name)
6
- storage_pod = get_raw_storage_pod(name, datacenter_name)
6
+ storage_pod = list_storage_pods(datacenter: datacenter_name).detect { |pod| pod[:name] == name }
7
7
  raise(Fog::Compute::Vsphere::NotFound) unless storage_pod
8
- storage_pod_attributes(storage_pod, datacenter_name)
8
+ storage_pod
9
9
  end
10
10
 
11
11
  protected
@@ -13,6 +13,10 @@ module Fog
13
13
  def get_raw_storage_pod(name, datacenter_name)
14
14
  raw_storage_pods(datacenter_name).detect { |pod| pod.name == name }
15
15
  end
16
+
17
+ def raw_storage_pods(datacenter_name)
18
+ list_container_view(datacenter_name, 'StoragePod')
19
+ end
16
20
  end
17
21
 
18
22
  class Mock
@@ -7,32 +7,76 @@ module Fog
7
7
  cluster_name = filters.fetch(:cluster, nil)
8
8
  # default to show all datastores
9
9
  only_active = filters[:accessible] || false
10
- raw_datastores(datacenter_name, cluster_name).map do |datastore|
11
- next if only_active && !datastore.summary.accessible
12
- datastore_attributes(datastore, datacenter_name)
10
+
11
+ dc = find_raw_datacenter(datacenter_name)
12
+
13
+ datastores = if cluster_name
14
+ cluster = get_raw_cluster(cluster_name, dc)
15
+ property_collector_results(datastore_cluster_filter_spec(cluster))
16
+ else
17
+ property_collector_results(datastore_filter_spec(dc))
18
+ end
19
+
20
+ datastores.map do |datastore|
21
+ next if only_active && !datastore['summary.accessible']
22
+ map_attrs_to_hash(datastore, datastore_attribute_mapping).merge(
23
+ datacenter: datacenter_name,
24
+ id: managed_obj_id(datastore.obj)
25
+ )
13
26
  end.compact
14
27
  end
15
28
 
16
- def raw_datastores(datacenter_name, cluster = nil)
17
- if cluster.nil?
18
- find_raw_datacenter(datacenter_name).datastore
19
- else
20
- get_raw_cluster(cluster, datacenter_name).datastore
21
- end
29
+ protected
30
+
31
+ def datastore_filter_spec(obj)
32
+ RbVmomi::VIM.PropertyFilterSpec(
33
+ objectSet: [
34
+ obj: obj.datastoreFolder,
35
+ skip: true,
36
+ selectSet: [
37
+ folder_traversal_spec
38
+ ]
39
+ ],
40
+ propSet: datastore_filter_prop_set
41
+ )
22
42
  end
23
43
 
24
- protected
44
+ def datastore_cluster_filter_spec(obj)
45
+ RbVmomi::VIM.PropertyFilterSpec(
46
+ objectSet: [
47
+ obj: obj,
48
+ skip: true,
49
+ selectSet: [
50
+ compute_resource_datastore_traversal_spec
51
+ ]
52
+ ],
53
+ propSet: datastore_filter_prop_set
54
+ )
55
+ end
56
+
57
+ def datastore_filter_prop_set
58
+ [
59
+ { type: 'Datastore', pathSet: datastore_attribute_mapping.values }
60
+ ]
61
+ end
62
+
63
+ def compute_resource_datastore_traversal_spec
64
+ RbVmomi::VIM.TraversalSpec(
65
+ name: 'computeResourceDatastoreTraversalSpec',
66
+ type: 'ComputeResource',
67
+ path: 'datastore',
68
+ skip: false
69
+ )
70
+ end
25
71
 
26
- def datastore_attributes(datastore, datacenter)
72
+ def datastore_attribute_mapping
27
73
  {
28
- id: managed_obj_id(datastore),
29
- name: datastore.name,
30
- accessible: datastore.summary.accessible,
31
- type: datastore.summary.type,
32
- freespace: datastore.summary.freeSpace,
33
- capacity: datastore.summary.capacity,
34
- uncommitted: datastore.summary.uncommitted,
35
- datacenter: datacenter
74
+ name: 'summary.name',
75
+ accessible: 'summary.accessible',
76
+ type: 'summary.type',
77
+ freespace: 'summary.freeSpace',
78
+ capacity: 'summary.capacity',
79
+ uncommitted: 'summary.uncommitted'
36
80
  }
37
81
  end
38
82
  end
@@ -23,13 +23,130 @@ module Fog
23
23
  def list_folders(filters = {})
24
24
  path = filters[:path] || filters['path'] || ''
25
25
  datacenter_name = filters[:datacenter]
26
- get_raw_vmfolders(path, datacenter_name).map do |folder|
27
- folder_attributes(folder, datacenter_name)
26
+
27
+ # if we don't need to display folders for a specific path
28
+ # we can easily use a property collector to get the
29
+ # data in an efficient manner from vsphere
30
+ # otherwise we use a much slower implementation
31
+ unless path.nil? || path.empty?
32
+ return get_raw_vmfolders(path, datacenter_name).map do |folder|
33
+ folder_attributes(folder, datacenter_name)
34
+ end
28
35
  end
36
+
37
+ root_folder = connection.serviceContent.rootFolder
38
+
39
+ results = property_collector_results(folder_filter_spec(root_folder))
40
+
41
+ folder_inventory = generate_folder_inventory(results)
42
+
43
+ folders = results.select { |result| result.obj.is_a?(RbVmomi::VIM::Folder) && result['childType'].include?('VirtualMachine') }
44
+
45
+ folders.map do |folder|
46
+ folder_id = managed_obj_id(folder.obj)
47
+ parent_id = folder['parent']._ref if folder['parent']
48
+ path = lookup_folder_path(folder_inventory, folder_id)
49
+ next unless path.include?(datacenter_name) # skip folders from another datacenter
50
+ map_attrs_to_hash(folder, folder_attribute_mapping).merge(
51
+ datacenter: datacenter_name,
52
+ parent: lookup_folder_name(folder_inventory, parent_id),
53
+ path: path.join('/'),
54
+ type: folder_type(folder['childType']),
55
+ id: folder_id
56
+ )
57
+ end.compact
29
58
  end
30
59
 
31
60
  protected
32
61
 
62
+ def folder_filter_spec(root_folder)
63
+ RbVmomi::VIM.PropertyFilterSpec(
64
+ objectSet: [
65
+ obj: root_folder,
66
+ skip: false,
67
+ selectSet: [
68
+ dc_folder_traversal_spec,
69
+ datacenter_to_vm_folder_traversal_spec
70
+ ]
71
+ ],
72
+ propSet: [
73
+ { type: 'Folder', pathSet: folder_attribute_mapping.values + %w[parent childType] },
74
+ { type: 'Datacenter', pathSet: %w[name parent] }
75
+ ]
76
+ )
77
+ end
78
+
79
+ def dc_folder_traversal_spec
80
+ RbVmomi::VIM.TraversalSpec(
81
+ name: 'dcFolderTraversalSpec',
82
+ type: 'Folder',
83
+ path: 'childEntity',
84
+ skip: false,
85
+ selectSet: [
86
+ RbVmomi::VIM.SelectionSpec(name: 'dcFolderTraversalSpec'),
87
+ RbVmomi::VIM.SelectionSpec(name: 'DatacenterToVmFolderTraversalSpec')
88
+ ]
89
+ )
90
+ end
91
+
92
+ def datacenter_to_vm_folder_traversal_spec
93
+ RbVmomi::VIM.TraversalSpec(
94
+ name: 'DatacenterToVmFolderTraversalSpec',
95
+ type: 'Datacenter',
96
+ path: 'vmFolder',
97
+ skip: false,
98
+ selectSet: [
99
+ RbVmomi::VIM.SelectionSpec(name: 'dcFolderTraversalSpec')
100
+ ]
101
+ )
102
+ end
103
+
104
+ def lookup_folder_name(inventory, folder_id)
105
+ folder = inventory[folder_id]
106
+ return '' unless folder
107
+ folder[:name]
108
+ end
109
+
110
+ def lookup_folder_path(inventory, folder_id)
111
+ folder = inventory[folder_id]
112
+ return '' unless folder
113
+ folder[:path]
114
+ end
115
+
116
+ def set_folder_paths(folder_inventory) # rubocop:disable Naming/AccessorMethodName
117
+ folder_inventory.each do |ref, props|
118
+ props[:path] = ['', lookup_parent_folders(folder_inventory, ref).reverse].flatten
119
+ end
120
+ end
121
+
122
+ def lookup_parent_folders(folder_inventory, ref)
123
+ return [] unless folder_inventory[ref]
124
+ return [folder_inventory[ref][:name]] if folder_inventory[ref][:parent].nil?
125
+ [folder_inventory[ref][:name], lookup_parent_folders(folder_inventory, folder_inventory[ref][:parent])].flatten
126
+ end
127
+
128
+ def folder_attribute_mapping
129
+ {
130
+ name: 'name'
131
+ }
132
+ end
133
+
134
+ def generate_folder_inventory(folders)
135
+ folder_inventory = folders.each_with_object({}) do |folder, inventory|
136
+ parent = if folder['parent'].nil?
137
+ nil
138
+ else
139
+ folder['parent']._ref
140
+ end
141
+ inventory[folder.obj._ref] = {
142
+ name: folder['name'],
143
+ parent: parent
144
+ }
145
+ end
146
+ set_folder_paths(folder_inventory)
147
+ folder_inventory
148
+ end
149
+
33
150
  def get_raw_vmfolders(path, datacenter_name)
34
151
  folder = get_raw_vmfolder(path, datacenter_name)
35
152
  child_folders(folder).flatten.compact
@@ -4,26 +4,45 @@ module Fog
4
4
  class Real
5
5
  def list_storage_pods(filters = {})
6
6
  datacenter_name = filters[:datacenter]
7
- raw_storage_pods(datacenter_name).map do |storage_pod|
8
- storage_pod_attributes(storage_pod, datacenter_name)
9
- end.compact
10
- end
11
7
 
12
- private
8
+ dc = find_raw_datacenter(datacenter_name)
9
+
10
+ storage_pods = property_collector_results(storage_pod_filter_spec(dc))
13
11
 
14
- def raw_storage_pods(datacenter_name)
15
- list_container_view(datacenter_name, 'StoragePod')
12
+ storage_pods.map do |storage_pod|
13
+ map_attrs_to_hash(storage_pod, storage_pod_attribute_mapping).merge(
14
+ datacenter: datacenter_name,
15
+ id: managed_obj_id(storage_pod.obj)
16
+ )
17
+ end
16
18
  end
17
19
 
18
20
  protected
19
21
 
20
- def storage_pod_attributes(storage_pod, datacenter)
22
+ def storage_pod_filter_spec(obj)
23
+ RbVmomi::VIM.PropertyFilterSpec(
24
+ objectSet: [
25
+ obj: obj.datastoreFolder,
26
+ skip: true,
27
+ selectSet: [
28
+ folder_traversal_spec
29
+ ]
30
+ ],
31
+ propSet: storage_pod_filter_prop_set
32
+ )
33
+ end
34
+
35
+ def storage_pod_filter_prop_set
36
+ [
37
+ { type: 'StoragePod', pathSet: storage_pod_attribute_mapping.values }
38
+ ]
39
+ end
40
+
41
+ def storage_pod_attribute_mapping
21
42
  {
22
- id: managed_obj_id(storage_pod),
23
- name: storage_pod.name,
24
- freespace: storage_pod.summary.freeSpace,
25
- capacity: storage_pod.summary.capacity,
26
- datacenter: datacenter
43
+ name: 'name',
44
+ freespace: 'summary.freeSpace',
45
+ capacity: 'summary.capacity'
27
46
  }
28
47
  end
29
48
  end
@@ -61,11 +61,19 @@ module Fog
61
61
 
62
62
  private
63
63
 
64
+ # rubocop:disable Style/ConditionalAssignment
64
65
  def raw_to_hash(nic)
66
+ if nic.backing.respond_to?(:network)
67
+ network = nic.backing.network.name
68
+ elsif nic.backing.respond_to?(:port)
69
+ network = nic.backing.port.portgroupKey
70
+ else
71
+ network = nil
72
+ end
65
73
  {
66
74
  name: nic.deviceInfo.label,
67
75
  mac: nic.macAddress,
68
- network: nic.backing.respond_to?('network') ? nic.backing.network.name : nic.backing.port.portgroupKey,
76
+ network: network,
69
77
  status: nic.connectable.status,
70
78
  connected: nic.connectable.connected,
71
79
  summary: nic.deviceInfo.summary,
@@ -73,6 +81,7 @@ module Fog
73
81
  key: nic.key
74
82
  }
75
83
  end
84
+ # rubocop:enable Style/ConditionalAssignment
76
85
  end
77
86
 
78
87
  class Mock
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Vsphere
3
- VERSION = '2.3.0'.freeze
3
+ VERSION = '2.4.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-vsphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - J.R. Garcia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-09 00:00:00.000000000 Z
11
+ date: 2018-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog-core