chef-provisioning-fog 0.16.0 → 0.17.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 +4 -4
- data/README.md +93 -13
- data/Rakefile +9 -0
- data/chef-provisioning-fog.gemspec +6 -3
- data/lib/chef/provider/fog_key_pair.rb +3 -2
- data/lib/chef/provisioning/fog_driver/driver.rb +27 -23
- data/lib/chef/provisioning/fog_driver/providers/google.rb +8 -0
- data/lib/chef/provisioning/fog_driver/providers/softlayer.rb +184 -6
- data/lib/chef/provisioning/fog_driver/version.rb +1 -1
- data/spec/unit/providers/softlayer.rb +24 -0
- metadata +49 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e48c5dfd96019788e8add883cf24a604e197e3d1
|
4
|
+
data.tar.gz: 5f6cdf09bb038c76620ed6492333e3a912ae3a6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2a4be0a7ea606d12f33aa5942fc2c313644fb58dbb564ca804505fc5df774b6d4269a148d69e9987b102bfab86dbe839210a439d1a4f96d5181c5d3f9c05c96
|
7
|
+
data.tar.gz: 5a4b1ec56cf012cd0b59d0d4c48c5391b08d08390f67574e47918e1c12b992186fad1929f86c57b8c0a0b7c9b1701da2231c95b984677495a282bcbdddcfb162
|
data/README.md
CHANGED
@@ -19,11 +19,11 @@ These are the primary documents to help learn about using Provisioning and creat
|
|
19
19
|
|
20
20
|
## chef-provisioning-fog Usage and Examples
|
21
21
|
|
22
|
-
**A note about key pairs** - The key name used in `fog_key_pair` must be the same as the filename of the local key to be used. If the key does not exist in one of `private_key_paths` (which you can set in knife.rb or in a client.rb) it will be created.
|
22
|
+
**A note about key pairs** - The key name used in `fog_key_pair` must be the same as the filename of the local key to be used. If the key does not exist in one of `private_key_paths` (which you can set in `knife.rb` or in a `client.rb`) it will be created.
|
23
23
|
|
24
24
|
### DigitalOcean
|
25
25
|
|
26
|
-
Update your knife.rb to contain your DigitalOcean API token and the driver
|
26
|
+
Update your `knife.rb` to contain your DigitalOcean API token and the driver:
|
27
27
|
|
28
28
|
```ruby
|
29
29
|
driver 'fog:DigitalOcean'
|
@@ -34,14 +34,16 @@ For a full example see [examples/digitalocean/simple.rb](examples/digitalocean/s
|
|
34
34
|
|
35
35
|
### OpenStack
|
36
36
|
|
37
|
-
You'll need to update your `knife.rb` to work
|
37
|
+
You'll need to update your `knife.rb` to work:
|
38
38
|
|
39
39
|
```ruby
|
40
40
|
driver 'fog:OpenStack'
|
41
|
-
driver_options :compute_options => {
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
41
|
+
driver_options :compute_options => {
|
42
|
+
:openstack_auth_url => 'http://YOUROPENSTACK-CLOUD:5000/v2.0/tokens',
|
43
|
+
:openstack_username => 'YOUR-USERNAME',
|
44
|
+
:openstack_api_key => 'YOUR-PASSWORD',
|
45
|
+
:openstack_tenant => 'YOUR-TENANT-ID-NAME'
|
46
|
+
}
|
45
47
|
```
|
46
48
|
|
47
49
|
For a full example see [examples/openstack/simple.rb](examples/openstack/simple.rb).
|
@@ -52,16 +54,92 @@ For this example, you must configure `knife.rb` with your credentials and a regi
|
|
52
54
|
|
53
55
|
You must configure some credentials and region in a `knife.rb` file like so:
|
54
56
|
```ruby
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
driver 'fog:Rackspace'
|
58
|
+
driver_options :compute_options => {
|
59
|
+
:rackspace_username => 'MY-RACKSPACE-USERr',
|
60
|
+
:rackspace_api_key => 'API-KEY-FOR-USER',
|
61
|
+
:rackspace_region => 'dfw' # could be 'org', 'iad', 'hkg', etc
|
62
|
+
}
|
61
63
|
```
|
62
64
|
|
63
65
|
For a full example see [examples/rackspace/simple.rb](examples/rackspace/simple.rb).
|
64
66
|
|
67
|
+
### Google Compute Engine
|
68
|
+
|
69
|
+
You'll need to update your `knife.rb` to work:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
driver 'fog:Google'
|
73
|
+
driver_options :compute_options => { :provider => 'google',
|
74
|
+
:google_project => 'YOUR-PROJECT-ID', # the name will work here
|
75
|
+
:google_client_email => 'YOUR-SERVICE-ACCOUNT-EMAIL',
|
76
|
+
:google_key_location => 'YOUR-SERVICE-P12-KEY-FILE-FULL-PATH.p12'
|
77
|
+
}
|
78
|
+
|
79
|
+
```
|
80
|
+
|
81
|
+
In order to get the `YOUR-SERVICE-P12-KEY-FILE.p12` you need to set up a Service
|
82
|
+
account. This is located at `Home > Permissions > Service Accounts` and you'll
|
83
|
+
need to create a new one to get a new key. After that place it some place such
|
84
|
+
as `~/.chef/` so chef-provisioning-fog can find it. Your `google_client_email`
|
85
|
+
would be something like: `<UNIQUE_NAME>@<PROJECT>.iam.gserviceaccount.com`.
|
86
|
+
|
87
|
+
For a full simple example see [examples/google/simple.rb](examples/google/simple.rb).
|
88
|
+
|
89
|
+
For an example that shows a different `:disk_type` see
|
90
|
+
[examples/google/simple_different_disk.rb](examples/google/simple_different_disk.rb).
|
91
|
+
|
92
|
+
### Joyent
|
93
|
+
|
94
|
+
You'll need to update your `knife.rb` to work:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
driver 'fog:Joyent'
|
98
|
+
driver_options :compute_options => { :joyent_username => 'YOUR-JOYENT-LOGIN',
|
99
|
+
:joyent_password => 'YOUR-JOYENT-PASSWORD',
|
100
|
+
:joyent_keyname => 'THE-SSH-KEY-YOUVE-UPLOADED',
|
101
|
+
:joyent_version => '7.3.0', # if you are using the joyent public cloud
|
102
|
+
:joyent_keyfile => 'YOUR-PRIVATE-SSH-KEY-LOCATION' # Such as '/Users/jasghar/.ssh/id_rsa'
|
103
|
+
}
|
104
|
+
```
|
105
|
+
|
106
|
+
Tested this with the [Joyent Public Cloud](https://docs.joyent.com/public-cloud). For the package names, use the
|
107
|
+
GUI to find the name(s) that you want to use. This is also required to figure out the Image UUID, there doesn't seem to be an
|
108
|
+
effective way of doing this without the GUI.
|
109
|
+
|
110
|
+
For a more in-depth usage of this driver to use with either Private or Public Joyent cloud, checkout [this blog post][joyent_howto] by mhicks from [#smartos][freenode_smartos] on freenode.
|
111
|
+
|
112
|
+
For a infrastructure container example see [examples/joyent/infrastructure.rb](examples/joyent/infrastructure.rb).
|
113
|
+
|
114
|
+
### IBM SoftLayer
|
115
|
+
|
116
|
+
You'll need to update your `knife.rb` to work with this also:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
driver 'fog:SoftLayer'
|
120
|
+
driver_options :compute_options => { :provider => 'softlayer',
|
121
|
+
:softlayer_username => 'username',
|
122
|
+
:softlayer_api_key => 'api_key',
|
123
|
+
:softlayer_default_domain => 'example.com',
|
124
|
+
}
|
125
|
+
|
126
|
+
```
|
127
|
+
|
128
|
+
Once you or your administrator has created a SoftLayer account you can manage
|
129
|
+
your API key at https://control.softlayer.com/account/users
|
130
|
+
|
131
|
+
`:bootstrap_options => {:key_name => 'label'}` is looked up by_label; make sure
|
132
|
+
you have a public key created on control portal at
|
133
|
+
https://control.softlayer.com/devices/sshkeys with a matching label.
|
134
|
+
|
135
|
+
NOTE: the SoftLayer driver injects a custom post provisioning script that
|
136
|
+
ensures some packages needed by chef-provisioning-fog to install chef are
|
137
|
+
present (e.g. sudo). The injected script will call your :postInstallScriptUri
|
138
|
+
if you define one. The driver will wait until the injected script is done. The
|
139
|
+
driver and script communicate using userMetadata so you cannot use metadata.
|
140
|
+
|
141
|
+
For a full example see [examples/softlayer/simple.rb](examples/softlayer/simple.rb).
|
142
|
+
|
65
143
|
### Cleaning up
|
66
144
|
|
67
145
|
```ruby
|
@@ -177,3 +255,5 @@ with_machine_options({
|
|
177
255
|
[gem]: https://rubygems.org/gems/chef-provisioning-fog
|
178
256
|
[travis]: https://travis-ci.org/chef/chef-provisioning-fog
|
179
257
|
[gemnasium]: https://gemnasium.com/chef/chef-provisioning-fog
|
258
|
+
[joyent_howto]: https://numericillustration.wordpress.com/2015/12/04/using-chef-provisioner-with-the-joyent-smart-data-center/
|
259
|
+
[freenode_smartos]: http://webchat.freenode.net/?randomnick=1&channels=smartos&prompt=1
|
data/Rakefile
CHANGED
@@ -4,3 +4,12 @@ require 'bundler/gem_tasks'
|
|
4
4
|
task :spec do
|
5
5
|
require File.expand_path('spec/run')
|
6
6
|
end
|
7
|
+
|
8
|
+
require "github_changelog_generator/task"
|
9
|
+
|
10
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
11
|
+
config.future_release = Chef::Provisioning::FogDriver::VERSION
|
12
|
+
config.enhancement_labels = "enhancement,Enhancement,New Feature".split(",")
|
13
|
+
config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",")
|
14
|
+
config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question".split(",")
|
15
|
+
end
|
@@ -8,16 +8,19 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.extra_rdoc_files = ['README.md', 'LICENSE' ]
|
9
9
|
s.summary = 'Driver for creating Fog instances in Chef Provisioning.'
|
10
10
|
s.description = s.summary
|
11
|
-
s.authors = ['John Keiser', "Chris McClimans", "Taylor Carpenter", "Wavell Watson"]
|
12
|
-
s.email = ['jkeiser@getchef.com', 'hh@vulk.co', 't@vulk.co', 'w@vulk.co']
|
11
|
+
s.authors = ['John Keiser', "Chris McClimans", "Taylor Carpenter", "Wavell Watson", "JJ Asghar"]
|
12
|
+
s.email = ['jkeiser@getchef.com', 'hh@vulk.co', 't@vulk.co', 'w@vulk.co','jj@chef.io']
|
13
13
|
s.homepage = 'https://github.com/opscode/chef-provisioning-fog'
|
14
14
|
|
15
15
|
s.add_dependency 'chef-provisioning', '~> 1.0'
|
16
|
-
s.add_dependency 'fog', '>= 1.
|
16
|
+
s.add_dependency 'fog', '>= 1.38.0'
|
17
|
+
s.add_dependency 'google-api-client', "~> 0.8.0"
|
18
|
+
s.add_dependency 'fog-softlayer' , '~> 1.1.0'
|
17
19
|
s.add_dependency 'retryable'
|
18
20
|
|
19
21
|
s.add_development_dependency 'rspec'
|
20
22
|
s.add_development_dependency 'rake'
|
23
|
+
s.add_development_dependency 'github_changelog_generator'
|
21
24
|
|
22
25
|
s.bindir = "bin"
|
23
26
|
s.executables = %w( )
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require 'chef/provider/lwrp_base'
|
2
3
|
require 'chef/provisioning/fog_driver/driver'
|
3
4
|
|
@@ -213,9 +214,9 @@ class Chef::Provider::FogKeyPair < Chef::Provider::LWRPBase
|
|
213
214
|
@current_resource = Chef::Resource::FogKeyPair.new(new_resource.name, run_context)
|
214
215
|
case new_driver.provider
|
215
216
|
when 'DigitalOcean'
|
216
|
-
current_key_pair = compute.ssh_keys.select { |key| key
|
217
|
+
current_key_pair = compute.list_ssh_keys.body['ssh_keys'].select { |key| key['name'] == new_resource.name }.first
|
217
218
|
if current_key_pair
|
218
|
-
@current_id = current_key_pair
|
219
|
+
@current_id = current_key_pair['id']
|
219
220
|
@current_fingerprint = current_key_pair ? compute.ssh_keys.get(@current_id).public_key : nil
|
220
221
|
else
|
221
222
|
current_resource.action :delete
|
@@ -297,7 +297,7 @@ module FogDriver
|
|
297
297
|
specs_and_options.each do |machine_spec, machine_options|
|
298
298
|
server = specs_and_servers[machine_spec]
|
299
299
|
if server
|
300
|
-
if %w(terminated archive).include?(server.
|
300
|
+
if %w(terminated archive DELETED).include?(server.state) # Can't come back from that
|
301
301
|
Chef::Log.warn "Machine #{machine_spec.name} (#{server.id} on #{driver_url}) is terminated. Recreating ..."
|
302
302
|
else
|
303
303
|
yield machine_spec, server if block_given?
|
@@ -307,9 +307,30 @@ module FogDriver
|
|
307
307
|
Chef::Log.warn "Machine #{machine_spec.name} (#{machine_spec.reference['server_id']} on #{driver_url}) no longer exists. Recreating ..."
|
308
308
|
end
|
309
309
|
|
310
|
+
machine_spec.reference ||= {}
|
311
|
+
machine_spec.reference.update(
|
312
|
+
'driver_url' => driver_url,
|
313
|
+
'driver_version' => FogDriver::VERSION,
|
314
|
+
'creator' => creator,
|
315
|
+
'allocated_at' => Time.now.to_i
|
316
|
+
)
|
317
|
+
|
310
318
|
bootstrap_options = bootstrap_options_for(action_handler, machine_spec, machine_options)
|
319
|
+
machine_spec.reference['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
|
311
320
|
by_bootstrap_options[bootstrap_options] ||= []
|
312
321
|
by_bootstrap_options[bootstrap_options] << machine_spec
|
322
|
+
|
323
|
+
# TODO 2.0 We no longer support `use_private_ip_for_ssh`, only `transport_address_location
|
324
|
+
if machine_options[:use_private_ip_for_ssh]
|
325
|
+
unless @transport_address_location_warned
|
326
|
+
Chef::Log.warn("The machine option ':use_private_ip_for_ssh' has been deprecated, use ':transport_address_location'")
|
327
|
+
@transport_address_location_warned = true
|
328
|
+
end
|
329
|
+
machine_options = Cheffish::MergedConfig.new(machine_options, {:transport_address_location => :private_ip})
|
330
|
+
end
|
331
|
+
%w(is_windows ssh_username sudo transport_address_location ssh_gateway).each do |key|
|
332
|
+
machine_spec.reference[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
|
333
|
+
end
|
313
334
|
end
|
314
335
|
|
315
336
|
# Create the servers in parallel
|
@@ -329,25 +350,8 @@ module FogDriver
|
|
329
350
|
# Assign each one to a machine spec
|
330
351
|
machine_spec = machine_specs.pop
|
331
352
|
machine_options = specs_and_options[machine_spec]
|
332
|
-
machine_spec.reference =
|
333
|
-
|
334
|
-
'driver_version' => FogDriver::VERSION,
|
335
|
-
'server_id' => server.id,
|
336
|
-
'creator' => creator,
|
337
|
-
'allocated_at' => Time.now.to_i
|
338
|
-
}
|
339
|
-
machine_spec.reference['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
|
340
|
-
# TODO 2.0 We no longer support `use_private_ip_for_ssh`, only `transport_address_location
|
341
|
-
if machine_options[:use_private_ip_for_ssh]
|
342
|
-
unless @transport_address_location_warned
|
343
|
-
Chef::Log.warn("The machine option ':use_private_ip_for_ssh' has been deprecated, use ':transport_address_location'")
|
344
|
-
@transport_address_location_warned = true
|
345
|
-
end
|
346
|
-
machine_options = Cheffish::MergedConfig.new(machine_options, {:transport_address_location => :private_ip})
|
347
|
-
end
|
348
|
-
%w(is_windows ssh_username sudo transport_address_location ssh_gateway).each do |key|
|
349
|
-
machine_spec.reference[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
|
350
|
-
end
|
353
|
+
machine_spec.reference['server_id'] = server.id
|
354
|
+
|
351
355
|
action_handler.performed_action "machine #{machine_spec.name} created as #{server.id} on #{driver_url}"
|
352
356
|
|
353
357
|
yield machine_spec, server if block_given?
|
@@ -371,13 +375,13 @@ module FogDriver
|
|
371
375
|
|
372
376
|
def start_server(action_handler, machine_spec, server)
|
373
377
|
# If it is stopping, wait for it to get out of "stopping" transition status before starting
|
374
|
-
if server.
|
378
|
+
if server.state == 'stopping'
|
375
379
|
action_handler.report_progress "wait for #{machine_spec.name} (#{server.id} on #{driver_url}) to finish stopping ..."
|
376
|
-
server.wait_for { server.
|
380
|
+
server.wait_for { server.state != 'stopping' }
|
377
381
|
action_handler.report_progress "#{machine_spec.name} is now stopped"
|
378
382
|
end
|
379
383
|
|
380
|
-
if server.
|
384
|
+
if server.state == 'stopped'
|
381
385
|
action_handler.perform_action "start machine #{machine_spec.name} (#{server.id} on #{driver_url})" do
|
382
386
|
server.start
|
383
387
|
machine_spec.reference['started_at'] = Time.now.to_i
|
@@ -35,6 +35,13 @@ class Chef
|
|
35
35
|
bootstrap_options[:zone_name] ||= 'europe-west1-b'
|
36
36
|
bootstrap_options[:name] ||= machine_spec.name
|
37
37
|
bootstrap_options[:disk_size] ||= 10
|
38
|
+
disk_type_prefix = "https://www.googleapis.com/compute/v1/projects/#{compute_options[:google_project]}/zones/#{bootstrap_options[:zone_name]}/diskTypes/"
|
39
|
+
standard_disk_type = disk_type_prefix + 'pd-standard'
|
40
|
+
if bootstrap_options[:disk_type].nil?
|
41
|
+
bootstrap_options[:disk_type] = standard_disk_type
|
42
|
+
else
|
43
|
+
bootstrap_options[:disk_type] = disk_type_prefix + bootstrap_options[:disk_type]
|
44
|
+
end
|
38
45
|
|
39
46
|
if bootstrap_options[:disks].nil?
|
40
47
|
# create the persistent boot disk
|
@@ -43,6 +50,7 @@ class Chef
|
|
43
50
|
:size_gb => bootstrap_options[:disk_size],
|
44
51
|
:zone_name => bootstrap_options[:zone_name],
|
45
52
|
:source_image => bootstrap_options[:image_name],
|
53
|
+
:type => bootstrap_options[:disk_type],
|
46
54
|
}
|
47
55
|
|
48
56
|
disk = compute.disks.create(disk_defaults)
|
@@ -1,3 +1,9 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'uri'
|
3
|
+
require 'fog/softlayer'
|
4
|
+
require 'fog/softlayer/models/compute/server'
|
5
|
+
|
6
|
+
# fog:SoftLayer:<datacenter>
|
1
7
|
class Chef
|
2
8
|
module Provisioning
|
3
9
|
module FogDriver
|
@@ -5,6 +11,8 @@ class Chef
|
|
5
11
|
class SoftLayer < FogDriver::Driver
|
6
12
|
Driver.register_provider_class('SoftLayer', FogDriver::Providers::SoftLayer)
|
7
13
|
|
14
|
+
POST_SCRIPT_DONE = 'post-script-done'
|
15
|
+
|
8
16
|
def creator
|
9
17
|
compute_options[:softlayer_username]
|
10
18
|
end
|
@@ -14,19 +22,189 @@ class Chef
|
|
14
22
|
new_compute_options[:provider] = provider
|
15
23
|
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
16
24
|
new_defaults = {
|
17
|
-
:driver_options => { :compute_options =>
|
25
|
+
:driver_options => { :compute_options => Fog.credentials },
|
18
26
|
:machine_options => { :bootstrap_options => {} }
|
19
27
|
}
|
20
28
|
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
29
|
+
id ||= ''
|
30
|
+
new_defaults[:machine_options][:bootstrap_options][:datacenter] = id if not id.empty?
|
31
|
+
|
32
|
+
[result, id]
|
33
|
+
end
|
21
34
|
|
22
|
-
|
35
|
+
def bootstrap_options_for(action_handler, machine_spec, machine_options)
|
36
|
+
# probably best to only ADD options here since super class looks
|
37
|
+
# for some values; for example, :key_name doesn't get saved to
|
38
|
+
# chef_provisioning.reference if you remove it here.
|
39
|
+
# Therefore, we remove things SoftLayer rejects in
|
40
|
+
# create_many_servers just before the actual fog create calls.
|
23
41
|
|
24
|
-
|
25
|
-
new_compute_options[:softlayer_api_key] ||= credential[:softlayer_api_key]
|
42
|
+
opts = super
|
26
43
|
|
27
|
-
|
44
|
+
if opts[:key_name]
|
45
|
+
key_label = opts[:key_name]
|
46
|
+
opts[:key_pairs] = [compute.key_pairs.by_label(key_label)] if key_label.is_a? String
|
47
|
+
end
|
28
48
|
|
29
|
-
|
49
|
+
opts
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_many_servers(num_servers, bootstrap_options, parallelizer)
|
53
|
+
# need to filter out options that SoftLayer doesn't accept
|
54
|
+
opts = bootstrap_options.dup
|
55
|
+
|
56
|
+
# options are passed directly to SoftLayer API and
|
57
|
+
# SoftLayer_Hardware_Server rejects requests with unrecognized
|
58
|
+
# options
|
59
|
+
opts.keep_if do |opt, val|
|
60
|
+
::Fog::Compute::Softlayer::Server.attributes.include?(opt)
|
61
|
+
end
|
62
|
+
# fog-softlayer defines :tags but SoftLayer_Hardware_Server rejects it...
|
63
|
+
#opts.delete :tags
|
64
|
+
|
65
|
+
# we hook in our own post-install script which uses userMetadata to
|
66
|
+
# tell us when post-install is complete. If the user supplies their
|
67
|
+
# own script it will be called by our hook before indicating
|
68
|
+
# completion in userData.
|
69
|
+
opts[:postInstallScriptUri] = 'https://dal05.objectstorage.service.networklayer.com/v1/AUTH_b1b23a05-1c03-4961-8b08-2339886e476f/dist/sl-post-hook.sh'
|
70
|
+
|
71
|
+
super(num_servers, opts, parallelizer)
|
72
|
+
end
|
73
|
+
|
74
|
+
def find_floating_ips(server, action_handler)
|
75
|
+
[]
|
76
|
+
end
|
77
|
+
|
78
|
+
def server_for(machine_spec)
|
79
|
+
if machine_spec.reference
|
80
|
+
id = machine_spec.reference['server_id']
|
81
|
+
if id and 0 != id
|
82
|
+
compute.servers.get(id)
|
83
|
+
else
|
84
|
+
sv = compute.servers.new(
|
85
|
+
:uid => machine_spec.reference['uid'],
|
86
|
+
:name => machine_spec.name,
|
87
|
+
:domain => machine_spec.reference['domain']
|
88
|
+
)
|
89
|
+
|
90
|
+
Chef::Log.info("waiting for server.id")
|
91
|
+
sv.wait_for_id
|
92
|
+
machine_spec.reference['server_id'] = sv.id
|
93
|
+
return sv
|
94
|
+
end
|
95
|
+
else
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def servers_for(machine_specs)
|
101
|
+
result = {}
|
102
|
+
machine_specs.each do |machine_spec|
|
103
|
+
result[machine_spec] = server_for(machine_spec)
|
104
|
+
end
|
105
|
+
|
106
|
+
result
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_servers(action_handler, specs_and_options, parallelizer, &block)
|
110
|
+
super do |machine_spec, server|
|
111
|
+
machine_spec.reference['uid'] = server.uid
|
112
|
+
machine_spec.reference['domain'] = server.domain
|
113
|
+
machine_spec.save(action_handler)
|
114
|
+
bootstrap_options = specs_and_options[machine_spec][:bootstrap_options]
|
115
|
+
create_timeout = bootstrap_options[:create_timeout] || 3600
|
116
|
+
wait_for_id(action_handler, server, create_timeout)
|
117
|
+
set_post_install_info(action_handler, server, bootstrap_options)
|
118
|
+
|
119
|
+
block.call(machine_spec, server) if block
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def request(server, path, **options)
|
124
|
+
service = server.bare_metal? ? :hardware_server : :virtual_guest
|
125
|
+
server.service.request(service, path, options)
|
126
|
+
end
|
127
|
+
|
128
|
+
def set_post_install_info(action_handler, server, bootstrap_options)
|
129
|
+
existing_user_data = request(server, server.id, :query => {:objectMask => 'userData'}).body['userData']
|
130
|
+
Chef::Log.info("userData from SLAPI is #{existing_user_data.inspect}")
|
131
|
+
if existing_user_data.is_a? Array
|
132
|
+
if existing_user_data.size < 1
|
133
|
+
existing_user_data = ''
|
134
|
+
else
|
135
|
+
existing_user_data = existing_user_data.first.fetch('value', '')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
Chef::Log.info("userData after processing is #{existing_user_data.inspect}")
|
139
|
+
# VSI userData is empty; bare metal userData will be an Array
|
140
|
+
if existing_user_data.empty?
|
141
|
+
action_handler.report_progress("Setting userData to detect post install status.")
|
142
|
+
sl_user = compute.instance_variable_get '@softlayer_username'
|
143
|
+
sl_key = compute.instance_variable_get '@softlayer_api_key'
|
144
|
+
service = server.bare_metal? ? 'Hardware_Server' : 'Virtual_Guest'
|
145
|
+
::Retryable.retryable(:tries => 60, :sleep => 5) do
|
146
|
+
update_url = URI::HTTPS.build(
|
147
|
+
:userinfo => "#{sl_user}:#{sl_key}",
|
148
|
+
:host => 'api.service.softlayer.com',
|
149
|
+
:path => "/rest/v3/SoftLayer_#{service}/#{server.id}/setUserMetadata",
|
150
|
+
).to_s
|
151
|
+
|
152
|
+
post_install_info = <<SHELL
|
153
|
+
##POST_INSTALL_INFO
|
154
|
+
POSTINST_UPDATE_URL='#{update_url}'
|
155
|
+
POSTINST_REQUESTED_URL='#{bootstrap_options[:postInstallScriptUri]}'
|
156
|
+
SHELL
|
157
|
+
|
158
|
+
encoded_info = Base64.strict_encode64(post_install_info)
|
159
|
+
Chef::Log.debug("encoded info: #{encoded_info.inspect}")
|
160
|
+
|
161
|
+
res = request(
|
162
|
+
server,
|
163
|
+
"#{server.id}/setUserMetadata",
|
164
|
+
:http_method => 'POST', :body => [
|
165
|
+
[
|
166
|
+
encoded_info
|
167
|
+
]
|
168
|
+
]
|
169
|
+
)
|
170
|
+
|
171
|
+
raise "Failed to setUserMetadata" unless TrueClass == res.body.class or res.body.first['value']
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def wait_for_id(action_handler, server, create_timeout)
|
177
|
+
return if 0 != server.id
|
178
|
+
|
179
|
+
# Cannot use Fog.wait_for because it requires server.id which is
|
180
|
+
# not initially available for bare metal.
|
181
|
+
server.wait_for_id(create_timeout) do |srv_info|
|
182
|
+
srv_id = srv_info ? srv_info['id'] : 'not set yet'
|
183
|
+
action_handler.report_progress "waiting for server.id on #{server.name} (#{server.uid}): #{srv_id} #{srv_info}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def wait_until_ready(action_handler, machine_spec, machine_options, server)
|
188
|
+
super
|
189
|
+
|
190
|
+
action_handler.report_progress "waiting for post-install script on #{server.name} to finish"
|
191
|
+
|
192
|
+
::Retryable.retryable(:tries => 600, :sleep => 2) do
|
193
|
+
action_handler.report_progress "checking post-install status on #{server.name}"
|
194
|
+
res = request(server, server.id, :query => 'objectMask=userData')
|
195
|
+
userData = res.body['userData']
|
196
|
+
value = userData.first['value']
|
197
|
+
|
198
|
+
raise "Waiting for post-install script" unless POST_SCRIPT_DONE == value
|
199
|
+
end
|
200
|
+
|
201
|
+
action_handler.report_progress "post-install done on #{server.name}"
|
202
|
+
end
|
203
|
+
|
204
|
+
def start_server(action_handler, machine_spec, server)
|
205
|
+
::Retryable.retryable(:tries => 10, :sleep => 2) do
|
206
|
+
super
|
207
|
+
end
|
30
208
|
end
|
31
209
|
end
|
32
210
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'chef/provisioning/fog_driver/providers/softlayer'
|
3
|
+
|
4
|
+
describe Chef::Provisioning::FogDriver::Providers::SoftLayer do
|
5
|
+
subject do
|
6
|
+
Chef::Provisioning::FogDriver::Driver.from_provider(
|
7
|
+
'SoftLayer',
|
8
|
+
driver_options: {
|
9
|
+
compute_options: {
|
10
|
+
softlayer_username: 'test_username', softlayer_api_key: 'test_api_key'}
|
11
|
+
}
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns the correct driver" do
|
16
|
+
expect(subject).to be_an_instance_of Chef::Provisioning::FogDriver::Providers::SoftLayer
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has a Fog backend" do
|
20
|
+
pending unless Fog.mock?
|
21
|
+
expect(subject.compute).to be_an_instance_of Fog::Compute::Softlayer::Mock
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-provisioning-fog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Keiser
|
8
8
|
- Chris McClimans
|
9
9
|
- Taylor Carpenter
|
10
10
|
- Wavell Watson
|
11
|
+
- JJ Asghar
|
11
12
|
autorequire:
|
12
13
|
bindir: bin
|
13
14
|
cert_chain: []
|
14
|
-
date: 2016-
|
15
|
+
date: 2016-03-28 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
16
17
|
- !ruby/object:Gem::Dependency
|
17
18
|
name: chef-provisioning
|
@@ -33,14 +34,42 @@ dependencies:
|
|
33
34
|
requirements:
|
34
35
|
- - ">="
|
35
36
|
- !ruby/object:Gem::Version
|
36
|
-
version: 1.
|
37
|
+
version: 1.38.0
|
37
38
|
type: :runtime
|
38
39
|
prerelease: false
|
39
40
|
version_requirements: !ruby/object:Gem::Requirement
|
40
41
|
requirements:
|
41
42
|
- - ">="
|
42
43
|
- !ruby/object:Gem::Version
|
43
|
-
version: 1.
|
44
|
+
version: 1.38.0
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: google-api-client
|
47
|
+
requirement: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - "~>"
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 0.8.0
|
52
|
+
type: :runtime
|
53
|
+
prerelease: false
|
54
|
+
version_requirements: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - "~>"
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 0.8.0
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: fog-softlayer
|
61
|
+
requirement: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - "~>"
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.1.0
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - "~>"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.1.0
|
44
73
|
- !ruby/object:Gem::Dependency
|
45
74
|
name: retryable
|
46
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -83,12 +112,27 @@ dependencies:
|
|
83
112
|
- - ">="
|
84
113
|
- !ruby/object:Gem::Version
|
85
114
|
version: '0'
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: github_changelog_generator
|
117
|
+
requirement: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
type: :development
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
86
129
|
description: Driver for creating Fog instances in Chef Provisioning.
|
87
130
|
email:
|
88
131
|
- jkeiser@getchef.com
|
89
132
|
- hh@vulk.co
|
90
133
|
- t@vulk.co
|
91
134
|
- w@vulk.co
|
135
|
+
- jj@chef.io
|
92
136
|
executables: []
|
93
137
|
extensions: []
|
94
138
|
extra_rdoc_files:
|
@@ -125,6 +169,7 @@ files:
|
|
125
169
|
- spec/unit/fog_driver_spec.rb
|
126
170
|
- spec/unit/providers/aws/credentials_spec.rb
|
127
171
|
- spec/unit/providers/rackspace_spec.rb
|
172
|
+
- spec/unit/providers/softlayer.rb
|
128
173
|
homepage: https://github.com/opscode/chef-provisioning-fog
|
129
174
|
licenses: []
|
130
175
|
metadata: {}
|