chef-provisioning-fog 0.20.0 → 0.21.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
  SHA1:
3
- metadata.gz: d393fe60b94489dca31ede225f1d5729510eb8e5
4
- data.tar.gz: 2c0ca50215ed95b55918657d64c67baecc6c2c1c
3
+ metadata.gz: db6ee7ec27d271fb3880b648dcaab0aa3dc6c3e3
4
+ data.tar.gz: 3562d4b915fae443ef15cbe7f48e9a1bf5d0af40
5
5
  SHA512:
6
- metadata.gz: 24a68b07d7ae4492f9b31898f2850f4abf824d6deb3ffac909f21e4e38b163b1cb3d4cc40d90a73f367b35df53cf27dc5fa53f64366d371bd72767f1eb9843a1
7
- data.tar.gz: 373dc190d606cb7e931bf662ed31ee1ca2df1a7ba09546dad836c8d559672303f241ae7f308b42920b2e284f8ce9d4cf66d1c70c8ef732e8c844c909b3e4f376
6
+ metadata.gz: 510f83a7ecc7ef0ab683e767fc0490039b2f812fe6827fbbf46cf85034d05663d974676ec6f8e4891413decb4409d12fc5d08649ba45c6dd8e659fe0c979cbea
7
+ data.tar.gz: 318681b378186a7219bae547ad29b96eaac2b2053a97f93a0a15fd38150388790eee279bfb91549c8542e4b455b024db5222346dd339cf096c3243ca9f373ed9
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ gemfile
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem "chef", git: "https://github.com/chef/chef" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.2.2") # until stable 12.14 is released (won't load new cheffish and such otherwise)
6
+ gem "chef"
7
7
  gem 'guard'
8
8
  gem 'guard-rspec'
9
9
  gem 'rb-readline'
data/README.md CHANGED
@@ -210,6 +210,24 @@ with_driver "fog:XenServer:<XEN-SERVER-IP/NAME>", compute_options: {
210
210
 
211
211
  For a full example see [examples/xenserver/simple.rb](examples/xenserver/simple.rb).
212
212
 
213
+ ### Scaleway
214
+
215
+ You should configure the driver with your credentials or :
216
+
217
+ ``` ruby
218
+ with_driver "fog:Scaleway:Your-Organisation-UUID:region", compute_options: {
219
+ scalewat_token: 'your-api-token',
220
+ }
221
+ ```
222
+
223
+ or just use the fog configuration (~/.fog):
224
+
225
+ ``` ruby
226
+ with_driver 'fog:Scaleway'
227
+ ```
228
+
229
+ For full examples, see [examples/scaleway](examples/scaleway).
230
+
213
231
  ### Cleaning up
214
232
 
215
233
  ```ruby
@@ -17,7 +17,9 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency 'google-api-client', "~> 0.8.0"
18
18
  s.add_dependency 'fog-softlayer' , '~> 1.1.0'
19
19
  s.add_dependency 'fog-digitalocean'
20
+ s.add_dependency 'fog-scaleway'
20
21
  s.add_dependency 'retryable'
22
+ s.add_dependency 'winrm-elevated'
21
23
 
22
24
  s.add_development_dependency 'rspec'
23
25
  s.add_development_dependency 'rake'
@@ -0,0 +1,53 @@
1
+ require 'chef/provider/lwrp_base'
2
+ require 'openssl'
3
+ require 'chef/provisioning/chef_provider_action_handler'
4
+ require 'chef/provisioning/chef_managed_entry_store'
5
+
6
+ class Chef
7
+ class Provider
8
+ class ScalewayVolume < Chef::Provider::LWRPBase
9
+ provides :scaleway_volume
10
+
11
+ def action_handler
12
+ @action_handler ||= Chef::Provisioning::ChefProviderActionHandler.new(self)
13
+ end
14
+
15
+ def load_current_resource
16
+ end
17
+
18
+ def whyrun_supported?
19
+ true
20
+ end
21
+
22
+ def volume_spec
23
+ @volume_spec ||= chef_managed_entry_store.get_or_new(:volume, new_resource.name)
24
+ end
25
+
26
+ # Get the driver specified in the resource
27
+ def new_driver
28
+ @new_driver ||= run_context.chef_provisioning.driver_for(new_resource.driver)
29
+ end
30
+
31
+ def chef_managed_entry_store
32
+ @chef_managed_entry_store ||= Provisioning.chef_managed_entry_store(new_resource.chef_server)
33
+ end
34
+
35
+
36
+ action :create do
37
+ unless volume_spec.reference && new_driver.volume_for(volume_spec)
38
+ new_driver.create_volume(action_handler, volume_spec,
39
+ new_resource.volume_options)
40
+ end
41
+ new_resource.id = volume_spec.reference['id']
42
+ end
43
+
44
+ action :destroy do
45
+ if volume_spec.reference && volume_spec.reference['id']
46
+ new_driver.destroy_volume(action_handler, volume_spec,
47
+ new_resource.volume_options)
48
+ volume_spec.delete(action_handler)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -277,6 +277,14 @@ module FogDriver
277
277
  end
278
278
  end
279
279
 
280
+ def create_volume(action_handler, volume_spec, volume_options)
281
+ raise "##create_volume not implemented in in #{self.class}"
282
+ end
283
+
284
+ def destroy_volume(action_handler, volume_spec, volume_options)
285
+ raise "##destroy_volume not implemented in in #{self.class}"
286
+ end
287
+
280
288
  protected
281
289
 
282
290
  def option_for(machine_options, key)
@@ -308,13 +316,13 @@ module FogDriver
308
316
  Chef::Log.warn "Machine #{machine_spec.name} (#{machine_spec.reference['server_id']} on #{driver_url}) no longer exists. Recreating ..."
309
317
  end
310
318
 
311
- machine_spec.reference ||= {}
312
- machine_spec.reference.update(
313
- 'driver_url' => driver_url,
314
- 'driver_version' => FogDriver::VERSION,
315
- 'creator' => creator,
316
- 'allocated_at' => Time.now.to_i
317
- )
319
+ machine_spec.reference ||= {}
320
+ machine_spec.reference.update(
321
+ 'driver_url' => driver_url,
322
+ 'driver_version' => FogDriver::VERSION,
323
+ 'creator' => creator,
324
+ 'allocated_at' => Time.now.to_i
325
+ )
318
326
 
319
327
  bootstrap_options = bootstrap_options_for(action_handler, machine_spec, machine_options)
320
328
  machine_spec.reference['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
@@ -368,6 +376,7 @@ module FogDriver
368
376
  def create_many_servers(num_servers, bootstrap_options, parallelizer)
369
377
  parallelizer.parallelize(1.upto(num_servers)) do |i|
370
378
  clean_bootstrap_options = Marshal.load(Marshal.dump(bootstrap_options)) # Prevent destructive operations on bootstrap_options.
379
+
371
380
  server = compute.servers.create(clean_bootstrap_options)
372
381
  yield server if block_given?
373
382
  server
@@ -483,7 +492,6 @@ module FogDriver
483
492
  end
484
493
  server.reload
485
494
  end
486
-
487
495
  end
488
496
  end
489
497
 
@@ -616,6 +624,10 @@ module FogDriver
616
624
  end
617
625
  end
618
626
 
627
+ def volume_for(volume_spec)
628
+ raise "Immplement me in #{self.class.name}"
629
+ end
630
+
619
631
  def convergence_strategy_for(machine_spec, machine_options)
620
632
  # Defaults
621
633
  if !machine_spec.reference
@@ -48,7 +48,7 @@ module FogDriver
48
48
  result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
49
49
 
50
50
  new_compute_options[:openstack_auth_url] = id if (id && id != '')
51
-
51
+
52
52
  credential = Fog.credentials.find_all{ |k,v|
53
53
  k.to_s.start_with?('openstack') }
54
54
  credential.each { |k,v|
@@ -0,0 +1,248 @@
1
+ # fog:OpenStack:https://identifyhost:portNumber/v2.0
2
+
3
+ require 'fog/scaleway'
4
+ require 'fog/scaleway/models/compute/server'
5
+
6
+ #
7
+ # We're monkeypatching here to avoid overriding too much of the base
8
+ # class. This monkey patch will be removed if we can merge those changes
9
+ # upstream
10
+ #
11
+ class Fog::Scaleway::Compute::Server
12
+ alias :start :poweron
13
+ alias :stop :poweroff
14
+
15
+ def disassociate_address(ip)
16
+ ip = ip.address if ip.respond_to? :address
17
+ if public_ip && public_ip.address == ip
18
+ public_ip.server = nil
19
+ public_ip.save
20
+ end
21
+ reload
22
+ end
23
+ end
24
+
25
+ class Chef
26
+ module Provisioning
27
+ module FogDriver
28
+ module Providers
29
+ class Scaleway < FogDriver::Driver
30
+ Driver.register_provider_class('Scaleway', FogDriver::Providers::Scaleway)
31
+
32
+ def creator
33
+ compute_options[:scaleway_organization]
34
+ end
35
+
36
+ def convergence_strategy_for(machine_spec, machine_options)
37
+ machine_options = Cheffish::MergedConfig.new(machine_options, {
38
+ :convergence_options => {:ohai_hints => {'scaleway' => {}}}
39
+ })
40
+ super(machine_spec, machine_options)
41
+ end
42
+
43
+ def bootstrap_options_for(action_handler, machine_spec, machine_options)
44
+ opts = super
45
+ opts[:tags] = opts[:tags].map { |key, value| [key, value].join('=') }
46
+
47
+ # Let's fetch the id of the volumes if the user didn't provide it
48
+ # Which probably means they were created in chef
49
+ if opts[:volumes]
50
+ managed_entry_store = machine_spec.managed_entry_store
51
+ volumes = Marshal.load(Marshal.dump(opts[:volumes]))
52
+
53
+ volumes.each do |index, volume|
54
+ unless volume[:id]
55
+ volume_spec = managed_entry_store.get(:volume, volume[:name])
56
+ unless volume_spec
57
+ raise "Volume #{volume[:name]} unknown, create it or provide its id"
58
+ end
59
+ volume[:id] = volume_spec.reference['id']
60
+ end
61
+ end
62
+ opts[:volumes] = volumes
63
+ end
64
+ opts
65
+ end
66
+
67
+ def destroy_machine(action_handler, machine_spec, machine_options)
68
+ server = server_for(machine_spec)
69
+ if server
70
+ action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.reference['server_id']} at #{driver_url})" do
71
+
72
+ # Scaleway's API fail if we try to stop/terminate an instance with
73
+ # certains states
74
+ if server.state == 'running'
75
+ server.stop
76
+ server.wait_for { server.state != 'running' }
77
+ end
78
+ ['stopping', 'starting'].each do |state|
79
+ server.wait_for { server.state != state } if server.state == state
80
+ end
81
+
82
+ if server.state == 'stopped'
83
+ server.destroy
84
+ else
85
+ Chef::log.fatal "Server is in an unknown state (#{server.state})"
86
+ end
87
+ machine_spec.reference = nil
88
+ end
89
+ end
90
+ strategy = ConvergenceStrategy::NoConverge.new(machine_options[:convergence_options], config)
91
+ strategy.cleanup_convergence(action_handler, machine_spec)
92
+ end
93
+
94
+ def stop_machine(action_handler, machine_spec, machine_options)
95
+ server = server_for(machine_spec)
96
+ if server and server.state == 'running'
97
+ action_handler.perform_action "stop machine #{machine_spec.name} (#{server.id} at #{driver_url})" do
98
+ server.poweroff(true)
99
+ server.wait_for { server.state == 'stopped' }
100
+ end
101
+ end
102
+ end
103
+
104
+ def self.compute_options_for(provider, id, config)
105
+ new_compute_options = {}
106
+ new_compute_options[:provider] = provider
107
+ if (id && id != '')
108
+ org, region = id.split(':')
109
+ new_compute_options[:scaleway_organization] = org
110
+ new_compute_options[:scaleway_region] = region || 'par1'
111
+ end
112
+ new_config = { :driver_options => { :compute_options => new_compute_options }}
113
+
114
+ new_default_compute_options = {}
115
+ new_defaults = {
116
+ :driver_options => { :compute_options => new_default_compute_options },
117
+ :machine_options => { :bootstrap_options => {} }
118
+ }
119
+
120
+ result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
121
+
122
+ credential = Fog.credentials
123
+ new_default_compute_options[:scaleway_organization] ||= credential[:scaleway_organization]
124
+ new_default_compute_options[:scaleway_token] ||= credential[:scaleway_token]
125
+
126
+ id = [result[:driver_options][:compute_options][:scaleway_organization],
127
+ result[:driver_options][:compute_options][:scaleway_region]].join(':')
128
+
129
+ [result, id]
130
+ end
131
+
132
+ def converge_floating_ips(action_handler, machine_spec, machine_options, server)
133
+ if server.dynamic_ip_required
134
+ Chef::Log.info "Dynamic IP allocation has been enabled, not converging IPs"
135
+ else
136
+ super
137
+ end
138
+ end
139
+
140
+ # Scaleway only has one global pool.
141
+ def attach_ip_from_pool(server, pool)
142
+ return server if server.public_ip
143
+
144
+ Chef::Log.info "Scaleway has only one IP pool, ignoring pool argument"
145
+ ip = server.service.ips.all.select { |ip| ip.address.nil? }.first
146
+ if ip
147
+ ip.server = server
148
+ ip.save
149
+ server.reload
150
+ else
151
+ # Allocate a new IP
152
+ ip = server.service.ips.create
153
+ ip.server = server
154
+ ip.save
155
+ server.reload
156
+ end
157
+ end
158
+
159
+ def attach_ip(server, floating_ip)
160
+ ip = server.service.ips.get(floating_ip)
161
+ if ip.nil?
162
+ raise RuntimeError, "Requested IP (#{floating_ip}) not found"
163
+ end
164
+ if ip.server and ip.server.identity != server.identity
165
+ raise RuntimeError, "Requested IP (#{floating_ip}) already attached"
166
+ end
167
+
168
+ if server.public_ip
169
+ old_ip = server.public_ip
170
+ Chef::Log.info "Server #{server.identity} already has IP #{old_ip.address}, removing it"
171
+ old_ip.server = nil
172
+ old_ip.save
173
+ end
174
+
175
+ ip.server = server
176
+ ip.save
177
+ server.reload
178
+ end
179
+
180
+ # Get the public IP if any
181
+ def find_floating_ips(server, action_handler)
182
+ public_ips = []
183
+ Retryable.retryable(RETRYABLE_OPTIONS) do |retries, _exception|
184
+ action_handler.report_progress "Querying for public IP attached to server #{server.id}, API attempt #{retries+1}/#{RETRYABLE_OPTIONS[:tries]} ..."
185
+ public_ips << server.public_ip.address if server.public_ip
186
+ end
187
+ public_ips
188
+ end
189
+
190
+
191
+ def create_volume(action_handler, volume_spec, volume_options)
192
+ # Prevent destructive operations on volume_options.
193
+ clean_volume_options = Marshal.load(Marshal.dump(volume_options))
194
+
195
+ volume_spec.reference ||= {}
196
+ volume_spec.reference.update(
197
+ 'driver_url' => driver_url,
198
+ 'driver_version' => FogDriver::VERSION,
199
+ 'creator' => creator,
200
+ 'allocated_at' => Time.now.to_i,
201
+ )
202
+
203
+ description = ["Creating volume #{volume_spec.name}"]
204
+ volume_options.each { |k, v| description << " #{k}: #{v.inspect}"}
205
+
206
+ action_handler.report_progress description
207
+ if action_handler.should_perform_actions
208
+ clean_volume_options['name'] = volume_spec.name
209
+
210
+ volume = compute.volumes.create(clean_volume_options)
211
+
212
+ volume_spec.reference.update(
213
+ 'id' => volume.id,
214
+ 'volume_type' => volume.volume_type,
215
+ 'size' => volume.size
216
+ )
217
+ volume_spec.save(action_handler)
218
+ action_handler.performed_action "volume #{volume_spec.name} created as #{volume.id} on #{driver_url}"
219
+ end
220
+ end
221
+
222
+ def destroy_volume(action_handler, volume_spec, volume_options)
223
+ volume = volume_for(volume_spec)
224
+
225
+ if volume && action_handler.should_perform_actions
226
+ begin
227
+ msg = "destroyed volume #{volume_spec.name} at #{driver_url}"
228
+ action_handler.perform_action msg do
229
+ volume.destroy
230
+ volume_spec.reference = nil
231
+ volume_spec.save(action_handler)
232
+ end
233
+ rescue Fog::Scaleway::Compute::InvalidRequestError => e
234
+ Chef::Log.error "Unable to destroy volume #{volume_spec.name} : #{e.message}"
235
+ end
236
+ end
237
+ end
238
+
239
+ def volume_for(volume_spec)
240
+ if volume_spec.reference
241
+ compute.volumes.get(volume_spec.reference['id'])
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
@@ -1,6 +1,8 @@
1
1
  require 'chef/provisioning/fog_driver/driver'
2
2
  require 'chef/resource/fog_key_pair'
3
3
  require 'chef/provider/fog_key_pair'
4
+ require 'chef/resource/scaleway_volume'
5
+ require 'chef/provider/scaleway_volume'
4
6
 
5
7
  class Chef
6
8
  module DSL
@@ -27,6 +29,10 @@ class Chef
27
29
  with_fog_driver('Vcair', driver_options, &block)
28
30
  end
29
31
 
32
+ def with_fog_scaleway_driver(driver_options = nil, &block)
33
+ with_fog_driver('Scaleway', driver_options, &block)
34
+ end
35
+
30
36
  end
31
37
  end
32
38
  end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module FogDriver
4
- VERSION = '0.20.0'
4
+ VERSION = '0.21.0'
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,32 @@
1
+ require 'chef/provisioning'
2
+
3
+ class Chef::Resource::ScalewayVolume < Chef::Resource::LWRPBase
4
+ self.resource_name = 'scaleway_volume'
5
+
6
+ def initialize(*args)
7
+ super
8
+ @driver = run_context.chef_provisioning.current_driver
9
+ @chef_server = run_context.cheffish.current_chef_server
10
+ end
11
+
12
+ actions :create, :destroy, :nothing
13
+ default_action :create
14
+
15
+ attribute :id
16
+ attribute :chef_server
17
+ attribute :driver
18
+ attribute :volume_options
19
+
20
+ def add_volume_options(options)
21
+ if @volume_options
22
+ @volume_options = Cheffish::MergedConfig.new(options, @volume_options)
23
+ else
24
+ @volume_options = options
25
+ end
26
+ end
27
+
28
+ # We are not interested in Chef's cloning behavior here.
29
+ def load_prior_resource(*args)
30
+ Chef::Log.debug("Overloading #{resource_name}.load_prior_resource with NOOP")
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'chef/provisioning/fog_driver/providers/scaleway'
3
+
4
+ describe Chef::Provisioning::FogDriver::Providers::Scaleway do
5
+ subject do
6
+ Chef::Provisioning::FogDriver::Driver.from_provider(
7
+ 'Scaleway', driver_options: { compute_options: {
8
+ scaleway_organization: 'org',
9
+ scaleway_token: 'key'}
10
+ }
11
+ )
12
+ end
13
+
14
+ it "returns the correct driver" do
15
+ expect(subject).to be_an_instance_of Chef::Provisioning::FogDriver::Providers::Scaleway
16
+ end
17
+
18
+ it "has a Fog backend" do
19
+ pending unless Fog.mock?
20
+ expect(subject.compute).to be_an_instance_of Fog::Scaleway::Compute::Mock
21
+ end
22
+
23
+ describe '#creator' do
24
+ it 'returns the organization' do
25
+ expect(subject.creator).to eq 'org'
26
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-provisioning-fog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-08-30 00:00:00.000000000 Z
15
+ date: 2017-03-03 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: chef-provisioning
@@ -90,6 +90,20 @@ dependencies:
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
92
  version: '0'
93
+ - !ruby/object:Gem::Dependency
94
+ name: fog-scaleway
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ type: :runtime
101
+ prerelease: false
102
+ version_requirements: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
93
107
  - !ruby/object:Gem::Dependency
94
108
  name: retryable
95
109
  requirement: !ruby/object:Gem::Requirement
@@ -104,6 +118,20 @@ dependencies:
104
118
  - - ">="
105
119
  - !ruby/object:Gem::Version
106
120
  version: '0'
121
+ - !ruby/object:Gem::Dependency
122
+ name: winrm-elevated
123
+ requirement: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ type: :runtime
129
+ prerelease: false
130
+ version_requirements: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
107
135
  - !ruby/object:Gem::Dependency
108
136
  name: rspec
109
137
  requirement: !ruby/object:Gem::Requirement
@@ -165,6 +193,7 @@ files:
165
193
  - Rakefile
166
194
  - chef-provisioning-fog.gemspec
167
195
  - lib/chef/provider/fog_key_pair.rb
196
+ - lib/chef/provider/scaleway_volume.rb
168
197
  - lib/chef/provisioning/driver_init/fog.rb
169
198
  - lib/chef/provisioning/fog_driver/driver.rb
170
199
  - lib/chef/provisioning/fog_driver/providers/aws.rb
@@ -175,12 +204,14 @@ files:
175
204
  - lib/chef/provisioning/fog_driver/providers/joyent.rb
176
205
  - lib/chef/provisioning/fog_driver/providers/openstack.rb
177
206
  - lib/chef/provisioning/fog_driver/providers/rackspace.rb
207
+ - lib/chef/provisioning/fog_driver/providers/scaleway.rb
178
208
  - lib/chef/provisioning/fog_driver/providers/softlayer.rb
179
209
  - lib/chef/provisioning/fog_driver/providers/vcair.rb
180
210
  - lib/chef/provisioning/fog_driver/providers/xenserver.rb
181
211
  - lib/chef/provisioning/fog_driver/recipe_dsl.rb
182
212
  - lib/chef/provisioning/fog_driver/version.rb
183
213
  - lib/chef/resource/fog_key_pair.rb
214
+ - lib/chef/resource/scaleway_volume.rb
184
215
  - spec/spec_helper.rb
185
216
  - spec/support/aws/config-file.csv
186
217
  - spec/support/aws/ini-file.ini
@@ -189,6 +220,7 @@ files:
189
220
  - spec/unit/fog_driver_spec.rb
190
221
  - spec/unit/providers/aws/credentials_spec.rb
191
222
  - spec/unit/providers/rackspace_spec.rb
223
+ - spec/unit/providers/scaleway_spec.rb
192
224
  - spec/unit/providers/softlayer.rb
193
225
  homepage: https://github.com/opscode/chef-provisioning-fog
194
226
  licenses: []