bosh_aws_cpi 2.0.1 → 2.0.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: 8f1678fa3712efeb30ac293ada0fdb2183a3c043
4
- data.tar.gz: eb18fe472d0f6f7fe0e0bedca3c64de37c3b2a55
3
+ metadata.gz: f772026cd4993ec84c960766136602f1a3e0ecb8
4
+ data.tar.gz: fa5a32aed55a00e0c51ff304fbf7d33d22883427
5
5
  SHA512:
6
- metadata.gz: e0b8e1fbe36086aeaa4ac308ab30b5e2069c453b7722e5e2db1a0786e9fe4e608dc2cace7e4bc5ae82959f3fc245391954a54a356c5d42cc9237ccfc06fef368
7
- data.tar.gz: 34e7d8ce2a7a05c13f9d6093d2391674358fcac953a268fa00f903575dad2d198b8cabb77e2f460a75e2ff8bc5dd71c87bca2f4134f6fb91230860f7edf983e7
6
+ metadata.gz: ded5cb96c6cfae851201917d64530825fc6b97440648422f0b8f7763c11d58d555b2b476fa65942e4d4b7acc2f3894e5f27fcc745cc852de4d551f45d4c63c42
7
+ data.tar.gz: 2f84f8df96570ad6b5e9147263879c658c9011d30e882693f0441c4b803600e83605853366b495cdd05d5c8b6a87ee476a0aee9eb7869f034e7e40e5326cf5e8
data/README.md CHANGED
@@ -9,10 +9,6 @@ These options are passed to the AWS CPI when it is instantiated.
9
9
 
10
10
  ### AWS options
11
11
 
12
- * `access_key_id` (required)
13
- AWS IAM user access key
14
- * `secret_access_key` (required)
15
- AWS IAM secret access key
16
12
  * `default_key_name` (required)
17
13
  default AWS ssh key name to assign to created virtual machines
18
14
  * `default_security_groups` (required)
@@ -21,6 +17,14 @@ These options are passed to the AWS CPI when it is instantiated.
21
17
  local path to the ssh private key, must match `default_key_name`
22
18
  * `region` (required)
23
19
  EC2 region
20
+ * `credentials_source` (optional)
21
+ Where to get AWS credentials. This can be set to `static` for to use an `access_key_id` and `secret_access_key` or `env_or_profile` to get the credentials from environment variables or an EC2 instance profile. Defaults to `static` if not set
22
+ * `access_key_id` (optional, required when `credentials_source` is `static`)
23
+ AWS IAM user access key
24
+ * `secret_access_key` (optional, required when `credentials_source` is `static`)
25
+ AWS IAM secret access key
26
+ * `iam_instance_profile` (optional)
27
+ the [IAM Instance Profile](http://docs.aws.amazon.com/IAM/latest/UserGuide/roles-usingrole-instanceprofile.html) to use for the instance. This allows EC2 instances to use [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) when working with AWS APIs.
24
28
  * `ec2_endpoint` (optional)
25
29
  URL of the EC2 endpoint to connect to, defaults to the endpoint corresponding to the selected region,
26
30
  or `default_ec2_endpoint` if no region has been selected
@@ -57,6 +61,8 @@ These options are specified under `cloud_options` in the `resource_pools` sectio
57
61
  which [type of instance](http://aws.amazon.com/ec2/instance-types/) the VMs should belong to
58
62
  * `spot_bid_price` (optional)
59
63
  the [AWS spot instance](http://aws.amazon.com/ec2/purchasing-options/spot-instances/) bid price to use. When specified spot instances are started rather than on demand instances. _NB: this will dramatically slow down resource pool creation._
64
+ * `iam_instance_profile` (optional)
65
+ the [IAM Instance Profile](http://docs.aws.amazon.com/IAM/latest/UserGuide/roles-usingrole-instanceprofile.html) to use for the instance. This allows EC2 instances to use [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) when working with AWS APIs.
60
66
 
61
67
  ### Network options
62
68
 
@@ -25,13 +25,13 @@ module Bosh::AwsCloud
25
25
  def initialize(options)
26
26
  @options = options.dup.freeze
27
27
  validate_options
28
+ validate_credentials_source
28
29
 
29
30
  @logger = Bosh::Clouds::Config.logger
30
31
  aws_logger = @logger
31
32
 
32
33
  @aws_params = {
33
- access_key_id: aws_properties['access_key_id'],
34
- secret_access_key: aws_properties['secret_access_key'],
34
+ credentials_source: aws_properties['credentials_source'] || 'static',
35
35
  region: aws_properties['region'],
36
36
  ec2_endpoint: aws_properties['ec2_endpoint'] || default_ec2_endpoint,
37
37
  elb_endpoint: aws_properties['elb_endpoint'] || default_elb_endpoint,
@@ -50,6 +50,16 @@ module Bosh::AwsCloud
50
50
  @aws_params[k.to_sym] = aws_properties[k] unless aws_properties[k].nil?
51
51
  end
52
52
 
53
+ # credentials_source could be static (default) or env_or_profile
54
+ # static credentials must be included in aws_properties
55
+ # env_or_profile credentials will use the AWS DefaultCredentialsProvider
56
+ # to find AWS credentials in environment variables or EC2 instance profiles
57
+
58
+ if @aws_params[:credentials_source] == 'static'
59
+ @aws_params[:access_key_id] = aws_properties['access_key_id']
60
+ @aws_params[:secret_access_key] = aws_properties['secret_access_key']
61
+ end
62
+
53
63
  # AWS Ruby SDK is threadsafe but Ruby autoload isn't,
54
64
  # so we need to trigger eager autoload while constructing CPI
55
65
  AWS.eager_autoload!
@@ -57,13 +67,7 @@ module Bosh::AwsCloud
57
67
  initialize_aws
58
68
  initialize_registry
59
69
 
60
- aws_elb_params = {
61
- access_key_id: aws_properties['access_key_id'],
62
- secret_access_key: aws_properties['secret_access_key'],
63
- region: aws_properties['region']
64
- }
65
-
66
- elb = AWS::ELB.new(aws_elb_params)
70
+ elb = AWS::ELB.new(@aws_params)
67
71
 
68
72
  @instance_manager = InstanceManager.new(region, registry, elb, az_selector, @logger)
69
73
 
@@ -120,7 +124,7 @@ module Bosh::AwsCloud
120
124
  stemcell = StemcellFinder.find_by_region_and_id(region, stemcell_id)
121
125
 
122
126
  begin
123
- instance = @instance_manager.create(
127
+ instance, block_device_agent_info = @instance_manager.create(
124
128
  agent_id,
125
129
  stemcell.image_id,
126
130
  resource_pool,
@@ -139,6 +143,7 @@ module Bosh::AwsCloud
139
143
  network_spec,
140
144
  environment,
141
145
  stemcell.root_device_name,
146
+ block_device_agent_info
142
147
  )
143
148
  registry.update_settings(instance.id, registry_settings)
144
149
 
@@ -674,7 +679,6 @@ module Bosh::AwsCloud
674
679
  hash[attachment.volume.id] = device_name
675
680
  hash
676
681
  end
677
-
678
682
  if device_map[volume.id].nil?
679
683
  raise Bosh::Clouds::DiskNotAttached.new(true),
680
684
  "Disk `#{volume.id}' is not attached to instance `#{instance.id}'"
@@ -692,7 +696,7 @@ module Bosh::AwsCloud
692
696
  #
693
697
  def validate_options
694
698
  required_keys = {
695
- "aws" => ["access_key_id", "secret_access_key", "region", "default_key_name"],
699
+ "aws" => ["region", "default_key_name"],
696
700
  "registry" => ["endpoint", "user", "password"],
697
701
  }
698
702
 
@@ -709,6 +713,30 @@ module Bosh::AwsCloud
709
713
  raise ArgumentError, "missing configuration parameters > #{missing_keys.join(', ')}" unless missing_keys.empty?
710
714
  end
711
715
 
716
+ ##
717
+ # Checks AWS credentials settings to see if the CPI
718
+ # will be able to authenticate to AWS.
719
+ #
720
+ def validate_credentials_source
721
+ credentials_source = options['aws']['credentials_source'] || 'static'
722
+
723
+ if credentials_source != 'env_or_profile' && credentials_source != 'static'
724
+ raise ArgumentError, "Unknown credentials_source #{credentials_source}"
725
+ end
726
+
727
+ if credentials_source == 'static'
728
+ if options['aws']['access_key_id'].nil? || options['aws']['secret_access_key'].nil?
729
+ raise ArgumentError, "Must use access_key_id and secret_access_key with static credentials_source"
730
+ end
731
+ end
732
+
733
+ if credentials_source == 'env_or_profile'
734
+ if !options['aws']['access_key_id'].nil? || !options['aws']['secret_access_key'].nil?
735
+ raise ArgumentError, "Can't use access_key_id and secret_access_key with env_or_profile credentials_source"
736
+ end
737
+ end
738
+ end
739
+
712
740
  # Generates initial agent settings. These settings will be read by agent
713
741
  # from AWS registry (also a BOSH component) on a target instance. Disk
714
742
  # conventions for amazon are:
@@ -722,8 +750,11 @@ module Bosh::AwsCloud
722
750
  # @param [Hash] network_spec Agent network spec
723
751
  # @param [Hash] environment
724
752
  # @param [String] root_device_name root device, e.g. /dev/sda1
753
+ # @param [Hash] block_device_agent_info disk attachment information to merge into the disks section.
754
+ # keys are device type ("ephemeral", "raw_ephemeral") and values are array of strings representing the
755
+ # path to the block device. It is expected that "ephemeral" has exactly one value.
725
756
  # @return [Hash]
726
- def initial_agent_settings(agent_id, network_spec, environment, root_device_name)
757
+ def initial_agent_settings(agent_id, network_spec, environment, root_device_name, block_device_agent_info)
727
758
  settings = {
728
759
  "vm" => {
729
760
  "name" => "vm-#{SecureRandom.uuid}"
@@ -732,11 +763,13 @@ module Bosh::AwsCloud
732
763
  "networks" => agent_network_spec(network_spec),
733
764
  "disks" => {
734
765
  "system" => root_device_name,
735
- "ephemeral" => "/dev/sdb",
736
766
  "persistent" => {}
737
767
  }
738
768
  }
739
769
 
770
+ settings["disks"].merge!(block_device_agent_info)
771
+ settings["disks"]["ephemeral"] = settings["disks"]["ephemeral"][0]["path"]
772
+
740
773
  settings["env"] = environment if environment
741
774
  settings.merge(agent_properties)
742
775
  end
@@ -4,7 +4,12 @@ module Bosh::AwsCloud
4
4
 
5
5
  module Helpers
6
6
  def default_ephemeral_disk_mapping
7
- { '/dev/sdb' => 'ephemeral0' }
7
+ [
8
+ {
9
+ device_name: '/dev/sdb',
10
+ virtual_name: 'ephemeral0',
11
+ }
12
+ ]
8
13
  end
9
14
 
10
15
  def ebs_ephemeral_disk_mapping(volume_size_in_gb, volume_type)
@@ -5,60 +5,68 @@ module Bosh::AwsCloud
5
5
  class InstanceManager
6
6
  include Helpers
7
7
 
8
+ class DiskInfo
9
+ attr_reader :size, :count
10
+ def initialize(size, count)
11
+ @size = size
12
+ @count = count
13
+ end
14
+ end
15
+
8
16
  InstanceStorageMap = {
9
17
  # previous generation
10
- 'm1.small' => 160,
11
- 'm1.medium' => 410,
12
- 'm1.large' => 420,
13
- 'm1.xlarge' => 420,
18
+ 'm1.small' => DiskInfo.new(160, 1),
19
+ 'm1.medium' => DiskInfo.new(410, 1),
20
+ 'm1.large' => DiskInfo.new(420, 2),
21
+ 'm1.xlarge' => DiskInfo.new(420, 4),
14
22
 
15
- 'c1.medium' => 350,
16
- 'c1.xlarge' => 420,
23
+ 'c1.medium' => DiskInfo.new(350, 1),
24
+ 'c1.xlarge' => DiskInfo.new(420, 4),
17
25
 
18
- 'cc2.8xlarge' => 840,
26
+ 'cc2.8xlarge' => DiskInfo.new(840, 4),
19
27
 
20
- 'cg1.4xlarge' => 840,
28
+ 'cg1.4xlarge' => DiskInfo.new(840, 2),
21
29
 
22
- 'm2.xlarge' => 420,
23
- 'm2.2xlarge' => 850,
24
- 'm2.4xlarge' => 840,
30
+ 'm2.xlarge' => DiskInfo.new(420, 1),
31
+ 'm2.2xlarge' => DiskInfo.new(850, 1),
32
+ 'm2.4xlarge' => DiskInfo.new(840, 2),
25
33
 
26
- 'cr1.8xlarge' => 120,
34
+ 'cr1.8xlarge' => DiskInfo.new(120, 2),
27
35
 
28
- 'hi1.4xlarge' => 1024,
36
+ 'hi1.4xlarge' => DiskInfo.new(1024, 2),
29
37
 
30
- 'hs1.8xlarge' => 2000,
38
+ 'hs1.8xlarge' => DiskInfo.new(2000, 24),
31
39
 
32
40
  # current generation
33
- 'm3.medium' => 4,
34
- 'm3.large' => 32,
35
- 'm3.xlarge' => 40,
36
- 'm3.2xlarge' => 80,
37
-
38
- 'c3.large' => 16,
39
- 'c3.xlarge' => 40,
40
- 'c3.2xlarge' => 80,
41
- 'c3.4xlarge' => 160,
42
- 'c3.8xlarge' => 320,
43
-
44
- 'r3.large' => 32,
45
- 'r3.xlarge' => 80,
46
- 'r3.2xlarge' => 160,
47
- 'r3.4xlarge' => 320,
48
- 'r3.8xlarge' => 320,
49
-
50
- 'g2.2xlarge' => 60,
51
- 'g2.8xlarge' => 120,
52
-
53
- 'i2.xlarge' => 800,
54
- 'i2.2xlarge' => 800,
55
- 'i2.4xlarge' => 800,
56
- 'i2.8xlarge' => 800,
57
-
58
- 'd2.xlarge' => 2000,
59
- 'd2.2xlarge' => 2000,
60
- 'd2.4xlarge' => 2000,
61
- 'd2.8xlarge' => 2000
41
+ 'm3.medium' => DiskInfo.new(4, 1),
42
+ 'm3.large' => DiskInfo.new(32, 1),
43
+ 'm3.xlarge' => DiskInfo.new(40, 2),
44
+ 'm3.2xlarge' => DiskInfo.new(80, 2),
45
+
46
+ 'c3.large' => DiskInfo.new(16, 2),
47
+ 'c3.xlarge' => DiskInfo.new(40, 2),
48
+ 'c3.2xlarge' => DiskInfo.new(80, 2),
49
+ 'c3.4xlarge' => DiskInfo.new(160, 2),
50
+ 'c3.8xlarge' => DiskInfo.new(320, 2),
51
+
52
+ 'r3.large' => DiskInfo.new(32, 1),
53
+ 'r3.xlarge' => DiskInfo.new(80, 1),
54
+ 'r3.2xlarge' => DiskInfo.new(160, 1),
55
+ 'r3.4xlarge' => DiskInfo.new(320, 1),
56
+ 'r3.8xlarge' => DiskInfo.new(320, 2),
57
+
58
+ 'g2.2xlarge' => DiskInfo.new(60, 1),
59
+ 'g2.8xlarge' => DiskInfo.new(120, 2),
60
+
61
+ 'i2.xlarge' => DiskInfo.new(800, 1),
62
+ 'i2.2xlarge' => DiskInfo.new(800, 2),
63
+ 'i2.4xlarge' => DiskInfo.new(800, 4),
64
+ 'i2.8xlarge' => DiskInfo.new(800, 8),
65
+
66
+ 'd2.xlarge' => DiskInfo.new(2000, 3),
67
+ 'd2.2xlarge' => DiskInfo.new(2000, 6),
68
+ 'd2.4xlarge' => DiskInfo.new(2000, 12),
69
+ 'd2.8xlarge' => DiskInfo.new(2000, 24)
62
70
  }
63
71
 
64
72
  def initialize(region, registry, elb, az_selector, logger)
@@ -70,7 +78,7 @@ module Bosh::AwsCloud
70
78
  end
71
79
 
72
80
  def create(agent_id, stemcell_id, resource_pool, networks_spec, disk_locality, environment, options)
73
- instance_params = build_instance_params(stemcell_id, resource_pool, networks_spec, disk_locality, options)
81
+ instance_params, block_device_info = build_instance_params(stemcell_id, resource_pool, networks_spec, disk_locality, options)
74
82
 
75
83
  @logger.info("Creating new instance with: #{instance_params.inspect}")
76
84
 
@@ -93,7 +101,12 @@ module Bosh::AwsCloud
93
101
  raise
94
102
  end
95
103
 
96
- instance
104
+ block_device_agent_info = block_device_info
105
+ .group_by { |v| v[:bosh_type] }
106
+ .map { |type, devices| {type => devices.map { |device| {"path" => device[:device_name] }}}}
107
+ .inject({}) { |a, b| a.merge(b) }
108
+
109
+ return instance, block_device_agent_info
97
110
  end
98
111
 
99
112
  # @param [String] instance_id EC2 instance id
@@ -104,13 +117,13 @@ module Bosh::AwsCloud
104
117
  private
105
118
 
106
119
  def build_instance_params(stemcell_id, resource_pool, networks_spec, disk_locality, options)
120
+ virtualization_type = @region.images[stemcell_id].virtualization_type
121
+ block_device_info = block_device_mapping(virtualization_type, resource_pool)
122
+
107
123
  instance_params = {count: 1}
108
124
  instance_params[:image_id] = stemcell_id
109
125
  instance_params[:instance_type] = resource_pool["instance_type"]
110
-
111
- ephemeral_disk_options = resource_pool.fetch("ephemeral_disk", {})
112
- ephemeral_disk_options["instance_type"] = resource_pool["instance_type"]
113
- instance_params[:block_device_mappings] = block_device_mapping(ephemeral_disk_options)
126
+ instance_params[:block_device_mappings] = block_device_info.map { |entry| entry.reject{ |k| k == :bosh_type } }
114
127
  instance_params[:placement_group] = resource_pool["placement_group"] if resource_pool["placement_group"]
115
128
  instance_params[:dedicated_tenancy] = true if resource_pool["tenancy"] == "dedicated"
116
129
 
@@ -118,14 +131,15 @@ module Bosh::AwsCloud
118
131
  set_key_name_parameter(instance_params, resource_pool["key_name"], options["aws"]["default_key_name"])
119
132
  set_security_groups_parameter(instance_params, networks_spec, options["aws"]["default_security_groups"])
120
133
  set_vpc_parameters(instance_params, networks_spec)
121
-
134
+ set_iam_instance_profile_parameter(instance_params, resource_pool["iam_instance_profile"], options["aws"]["default_iam_instance_profile"])
122
135
  set_availability_zone_parameter(
123
136
  instance_params,
124
137
  (disk_locality || []).map { |volume_id| @region.volumes[volume_id].availability_zone.to_s },
125
138
  resource_pool["availability_zone"],
126
139
  (instance_params[:subnet].availability_zone_name if instance_params[:subnet])
127
140
  )
128
- instance_params
141
+
142
+ return instance_params, block_device_info
129
143
  end
130
144
 
131
145
  def create_aws_instance(instance_params, spot_bid_price)
@@ -149,15 +163,21 @@ module Bosh::AwsCloud
149
163
 
150
164
  def instance_create_wait_time; 30; end
151
165
 
152
- def block_device_mapping(ephemeral_disk_options)
166
+ def block_device_mapping(virtualization_type, resource_pool)
167
+ ephemeral_disk_options = resource_pool.fetch("ephemeral_disk", {})
168
+
153
169
  ephemeral_volume_size_in_mb = ephemeral_disk_options.fetch('size', 0)
154
170
  ephemeral_volume_size_in_gb = (ephemeral_volume_size_in_mb / 1024.0).ceil
155
171
  ephemeral_volume_type = ephemeral_disk_options.fetch('type', 'standard')
156
- instance_type = ephemeral_disk_options.fetch('instance_type', '')
172
+ instance_type = resource_pool.fetch('instance_type', '')
173
+ raw_instance_storage = resource_pool.fetch('raw_instance_storage', false)
157
174
 
158
- instance_storage_size_gb = InstanceManager::InstanceStorageMap[instance_type]
175
+ local_disk_info = InstanceManager::InstanceStorageMap[instance_type]
176
+ if raw_instance_storage && local_disk_info.nil?
177
+ raise Bosh::Clouds::CloudError, "raw_instance_storage requested for instance type #{instance_type} that does not have instance storage"
178
+ end
159
179
 
160
- if instance_storage_size_gb.nil? || instance_storage_size_gb < ephemeral_volume_size_in_gb
180
+ if raw_instance_storage || local_disk_info.nil? || local_disk_info.size < ephemeral_volume_size_in_gb
161
181
  @logger.debug('Use EBS storage to create the virtual machine')
162
182
 
163
183
  ephemeral_volume_size_in_gb = 10 if ephemeral_volume_size_in_gb == 0
@@ -167,9 +187,34 @@ module Bosh::AwsCloud
167
187
  block_device_mapping_param = default_ephemeral_disk_mapping
168
188
  end
169
189
 
190
+ block_device_mapping_param[0][:bosh_type] = 'ephemeral'
191
+
192
+ if raw_instance_storage
193
+ next_device = first_raw_ephemeral_device(virtualization_type)
194
+ for i in 0..local_disk_info.count - 1 do
195
+ block_device_mapping_param << {
196
+ virtual_name: "ephemeral#{i}",
197
+ device_name: next_device,
198
+ bosh_type: "raw_ephemeral",
199
+ }
200
+ next_device = next_device.next
201
+ end
202
+ end
203
+
170
204
  block_device_mapping_param
171
205
  end
172
206
 
207
+ def first_raw_ephemeral_device(virtualization_type)
208
+ case virtualization_type
209
+ when :hvm
210
+ '/dev/xvdba'
211
+ when :paravirtual
212
+ '/dev/sdc'
213
+ else
214
+ raise Bosh::Clouds::CloudError, "unknown virtualization type #{virtualization_type}"
215
+ end
216
+ end
217
+
173
218
  def set_key_name_parameter(instance_params, resource_pool_key_name, default_aws_key_name)
174
219
  key_name = resource_pool_key_name || default_aws_key_name
175
220
  instance_params[:key_name] = key_name unless key_name.nil?
@@ -213,6 +258,11 @@ module Bosh::AwsCloud
213
258
  instance_params[:user_data] = Yajl::Encoder.encode(user_data)
214
259
  end
215
260
 
261
+ def set_iam_instance_profile_parameter(instance_params, resource_pool_iam_instance_profile, default_aws_iam_instance_profile)
262
+ iam_instance_profile = resource_pool_iam_instance_profile || default_aws_iam_instance_profile
263
+ instance_params[:iam_instance_profile] = iam_instance_profile unless iam_instance_profile.nil?
264
+ end
265
+
216
266
  def validate_and_prepare_security_groups_parameter(instance_params, security_groups)
217
267
  return if security_groups.nil? || security_groups.empty?
218
268
 
@@ -120,10 +120,8 @@ module Bosh::AwsCloud
120
120
  params.merge!(
121
121
  :name => "BOSH-#{SecureRandom.uuid}",
122
122
  :architecture => architecture,
123
- :block_device_mappings => params[:block_device_mappings].merge(
124
- default_ephemeral_disk_mapping
125
- )
126
123
  )
124
+ merge_default_ephemeral_mapping_for_create_disk(params)
127
125
 
128
126
  params
129
127
  end
@@ -131,5 +129,12 @@ module Bosh::AwsCloud
131
129
  def logger
132
130
  Bosh::Clouds::Config.logger
133
131
  end
132
+
133
+ # adapts the format of the default ephemeral mapping used by create_vm so it
134
+ # works with the create AMI, and inserts it into the given hash
135
+ def merge_default_ephemeral_mapping_for_create_disk(params)
136
+ ephemeral_mapping = default_ephemeral_disk_mapping[0]
137
+ params[:block_device_mappings][ephemeral_mapping[:device_name]] = ephemeral_mapping[:virtual_name]
138
+ end
134
139
  end
135
140
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_aws_cpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-12 00:00:00.000000000 Z
11
+ date: 2015-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  version: '0'
148
148
  requirements: []
149
149
  rubyforge_project:
150
- rubygems_version: 2.2.2
150
+ rubygems_version: 2.2.5
151
151
  signing_key:
152
152
  specification_version: 4
153
153
  summary: BOSH AWS CPI