kitchen-softlayer 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a4968babda5beee11922c354ef309c24370736ca
4
+ data.tar.gz: 501dab415d0b3b622b9ec4ddeba644794c8b24af
5
+ SHA512:
6
+ metadata.gz: bfeb3f59a937cde441bc39c5760aee572b120fb7845ed4e521308230d7a599dac822808b9c0d9da6a1b8a65fc41ee35fc80dbd62ecfd9ba5dc093be728600bb2
7
+ data.tar.gz: 4c2394ecfb7a1cf5bc2456378274fbb6c85bedb411118e16b6dd1b99c31db81bd98805771e14ff645a481d58c99fe6993f4ff4de8a9d0ece293d385760c24b2a
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # ?.?.? / ????-??-??
2
+
3
+ # 0.1.0 / 2015-09-10
4
+
5
+ * Initial release
6
+
7
+ ### Bug Fixes
8
+
9
+ * PR [#99][] - ??????????
10
+
11
+ ### New Features
12
+
13
+ [#99]: https://github.com/neillturner/kitchen-softlayer/pull/99
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Author:: Neill Turner (<neillwturner.com>)
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,137 @@
1
+ [![Gem Version](https://badge.fury.io/rb/kitchen-softlayer.svg)](http://badge.fury.io/rb/kitchen-softlayer)
2
+ [![Gem Downloads](http://ruby-gem-downloads-badge.herokuapp.com/kitchen-softlayer?type=total&color=brightgreen)](https://rubygems.org/gems/kitchen-softlayer)
3
+ [![Build Status](https://travis-ci.org/neillturner/kitchen-softlayer.png)](https://travis-ci.org/neillturner/kitchen-softlayer)
4
+
5
+ # Kitchen::Softlayer
6
+
7
+ A Test Kitchen Driver for Softlayer
8
+
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'kitchen-softlayer'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install kitchen-softlayer
23
+
24
+ ## Usage
25
+
26
+ By default set the following environment variables to your softlayer credentials:
27
+
28
+ ```
29
+ softlayer_username
30
+ softlayer_api_key
31
+ softlayer_default_datacenter (optional)
32
+ softlayer_default_domain (optional)
33
+ ```
34
+
35
+ So you don't need to code these in the .kitchen.yml file which is much better from a security point
36
+ of view as the kitchen.yml file can be checked in to source control without containing key data.
37
+
38
+
39
+ An example of the driver options in your `.kitchen.yml` file:
40
+
41
+ ```yaml
42
+ driver:
43
+ name: softlayer
44
+ key_name: 'myuploadedsshkeylabel'
45
+ ssh_key: C:/mykeys/my_private_sshkey.pem
46
+ username: root
47
+ server_name: 'myserver-test'
48
+ hostname: 'MyProject-test01'
49
+ flavor_id: m1.tiny
50
+ # image_id: '3b235124-a190-40b5-9720-c020e61b99e1'
51
+ os_code: 'CENTOS_7_64'
52
+ domain: softlayer.com
53
+ private_network_only: true
54
+ cpu: 1,
55
+ ram: 1024,
56
+ datacenter: lon02
57
+ ```
58
+
59
+ ### os_code and image_id
60
+ you need to either specify softlayer's operating System Reference Code via parameter os_code
61
+ or an image_id.
62
+
63
+ ### private_network_only
64
+ By default this parameter is set to false so no public network with be created.
65
+ For test-kitchen to access the server via ssh it needs to be on the softlayer private VPN. See:
66
+
67
+ [Using SSL VPN](http://knowledgelayer.softlayer.com/procedure/using-ssl-vpn)
68
+
69
+ ### ssh_key
70
+ Currently the driver only supports using SSH keys to access servers. This requires that you upload an SSH Key in Softlayer see:
71
+
72
+ [SSH Keys](http://knowledgelayer.softlayer.com/procedure/ssh-keys-0)
73
+
74
+ in the kitchen.yml file specify the label of the ssh key as the parameter key_name
75
+ and specify the private key for the uploaded public key as parameter ssh_key.
76
+
77
+ The `image_ref` and `flavor_ref` options can be specified as an exact id,
78
+ an exact name, or as a regular expression matching the name of the image or flavor.
79
+
80
+ ### hostname
81
+
82
+ the driver checks for a server with the hostname and will use that server instead of creating another one.
83
+
84
+ ### disable_ssl_validation
85
+
86
+ the driver uses the fog-softlayer ruby client to communicate with softlayer.
87
+ If you get SSL certificate validation errors then the workaround is to set disable SSL cert validation to true
88
+ however it is better to set the environment variable 'SSL_CERT_FILE' to a valid certificate file.
89
+
90
+ # Softlayer Driver Options
91
+
92
+ key | default value | Notes
93
+ ----|---------------|--------
94
+ softlayer_username | ENV['softlayer_username']
95
+ softlayer_api_key | ENV['softlayer_api_key']
96
+ softlayer_default_datacenter | ENV['softlayer_default_datacenter']
97
+ softlayer_default_domain | ENV['softlayer_default_domain']
98
+ server_name | nil | Server Name
99
+ key_name | nil | the label of the uploaded key
100
+ ssh_key| nil | file location of private key
101
+ disable_ssl_validation | false | ssl validation for fg softlayer api
102
+ username | 'root' | server's administration user
103
+ password | nil | server's administration password
104
+ port | '22' | ssh port of servef
105
+ hostname| nil | hostname of server
106
+ domain | ENV['softlayer_default_domain'] | domain nane of server
107
+ fqdn | nil | fully qualified domain name
108
+ cpu | nil | no of cpus
109
+ ram | nil | memory size
110
+ disk | nil | disk size
111
+ flavor_id | nil | type of server i.e. m1.tiny
112
+ bare_metal | false | server to be created on bare metal (takes longer)
113
+ os_code | nil | softlayer's operating System Reference Code
114
+ image_id | nil | image id for server
115
+ ephemeral_storage | nil | storage
116
+ network_components | nil | network
117
+ ssh_timeout | 300 | timeout to ssh when server starting
118
+ account_id | nil | softlayer account id
119
+ datacenter | ENV['softlayer_default_datacenter'] | datacenter code
120
+ single_tenant | false | don't share server
121
+ global_identifier | nil | softlayer global id
122
+ hourly_billing_flag | true
123
+ tags | [] | tags for the server
124
+ private_network_only | true | if only a private network
125
+ user_data | nil | user data for server
126
+ uid | nil | softlayer global id
127
+ vlan | nil | numeric id of private_vlan for server
128
+ private_vlan | nil | numeric id of private_vlan for server
129
+
130
+ ## Contributing
131
+
132
+ 1. Fork it
133
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
134
+ 3. Run style checks and RSpec tests (`bundle exec rake`)
135
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
136
+ 5. Push to the branch (`git push origin my-new-feature`)
137
+ 6. Create new Pull Request
@@ -0,0 +1,24 @@
1
+ # Encoding: UTF-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'kitchen/driver/softlayer_version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'kitchen-softlayer'
9
+ spec.version = Kitchen::Driver::SOFTLAYER_VERSION
10
+ spec.authors = ['Neill Turner']
11
+ spec.email = ['neillwturner@gmail.com']
12
+ spec.description = 'A Test Kitchen Softlayer driver'
13
+ spec.summary = 'Test Kitchen Softlayer driver'
14
+ spec.homepage = 'https://github.com/test-kitchen/kitchen-softlayer'
15
+ spec.license = 'Apache'
16
+ candidates = Dir.glob('{lib}/**/*') + ['README.md', 'LICENSE.txt']
17
+ candidates += ['CHANGELOG.md', 'kitchen-softlayer.gemspec']
18
+ spec.files = candidates.sort
19
+ spec.require_paths = ['lib']
20
+ spec.required_ruby_version = '>= 1.9.3'
21
+ spec.add_dependency 'test-kitchen', '~> 1.4'
22
+ spec.add_dependency 'fog', '~> 1.18'
23
+ spec.add_dependency 'fog-softlayer', '~> 0.4'
24
+ end
@@ -0,0 +1,333 @@
1
+ # Encoding: utf-8
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'fog'
16
+ require 'kitchen'
17
+ require 'socket'
18
+ require 'fog/softlayer'
19
+
20
+ module Kitchen
21
+ module Driver
22
+ # Softlayer driver for Kitchen.
23
+ # rubocop:disable Metrics/LineLength
24
+ class Softlayer < Kitchen::Driver::SSHBase
25
+ default_config :server_name, nil
26
+ default_config :key_name, nil
27
+ required_config :key_name
28
+ default_config :ssh_key do
29
+ %w(id_rsa id_dsa).map do |k|
30
+ f = File.expand_path("~/.ssh/#{k}")
31
+ f if File.exist?(f)
32
+ end.compact.first
33
+ end
34
+
35
+ required_config :ssh_key
36
+ default_config :disable_ssl_validation, false
37
+ default_config :username, 'root'
38
+ default_config :password, nil
39
+ default_config :port, '22'
40
+ default_config :hostname, nil
41
+ default_config :domain, ENV['softlayer_default_domain']
42
+ default_config :fqdn, nil
43
+ default_config :cpu, nil
44
+ default_config :ram, nil
45
+ default_config :disk, nil
46
+ default_config :flavor_id, nil
47
+ default_config :bare_metal, false
48
+ default_config :os_code, nil
49
+ default_config :image_id, nil
50
+ default_config :ephemeral_storage, nil
51
+ # keypair found from keyname
52
+ # default_config :key_pairs, nil
53
+ default_config :network_components, nil
54
+ default_config :softlayer_username, ENV['softlayer_username']
55
+ default_config :softlayer_api_key, ENV['softlayer_api_key']
56
+ default_config :softlayer_default_datacenter, ENV['softlayer_default_datacenter']
57
+ default_config :softlayer_default_domain, ENV['softlayer_default_domain']
58
+ default_config :ssh_timeout, 300
59
+ default_config :account_id, nil
60
+ default_config :datacenter, ENV['softlayer_default_datacenter']
61
+ default_config :single_tenant, false
62
+ default_config :global_identifier, nil
63
+ default_config :hourly_billing_flag, true
64
+ default_config :tags, nil
65
+ default_config :private_network_only, true
66
+ default_config :user_data, nil
67
+ default_config :uid, nil
68
+ default_config :tags, []
69
+ default_config :vlan, nil
70
+ default_config :private_vlan, nil
71
+
72
+ def create(state)
73
+ config[:server_name] = default_name unless config[:server_name]
74
+ config[:disable_ssl_validation] && disable_ssl_validation
75
+ server = find_server(config[:hostname])
76
+ server = create_server unless server
77
+ state[:server_id] = server.id
78
+ info "Softlayer instance <#{state[:server_id]}> created."
79
+ server.wait_for do
80
+ print '.'
81
+ ready?
82
+ end
83
+ info "\n(server ready)"
84
+ tag_server(server)
85
+ state[:hostname] = get_ip(server)
86
+ setup_ssh(server, state)
87
+ wait_for_ssh_key_access(state)
88
+ rescue Fog::Errors::Error, Excon::Errors::Error => ex
89
+ raise ActionFailed, ex.message
90
+ end
91
+
92
+ def destroy(state)
93
+ return if state[:server_id].nil?
94
+
95
+ config[:disable_ssl_validation] && disable_ssl_validation
96
+ server = compute.servers.get(state[:server_id])
97
+ server.destroy unless server.nil?
98
+ info "Softlayer instance <#{state[:server_id]}> destroyed."
99
+ state.delete(:server_id)
100
+ state.delete(:hostname)
101
+ end
102
+
103
+ private
104
+
105
+ def wait_for_ssh_key_access(state)
106
+ new_state = build_ssh_args(state)
107
+ new_state[2][:number_of_password_prompts] = 0
108
+ info 'Checking ssh key authentication'
109
+
110
+ (config[:ssh_timeout].to_i).times do
111
+ ssh = Fog::SSH.new(*new_state)
112
+ begin
113
+ ssh.run([%(uname -a)])
114
+ rescue => e
115
+ info "Server not yet accepting SSH key: #{e.message}"
116
+ sleep 1
117
+ else
118
+ info 'SSH key authetication successful'
119
+ return
120
+ end
121
+ end
122
+ fail "#{config[:ssh_timeout]} seconds went by and we couldn't connect, somethings broken"
123
+ end
124
+
125
+ def compute
126
+ @compute_connection ||= Fog::Compute.new(
127
+ provider: :softlayer,
128
+ softlayer_username: config[:softlayer_username],
129
+ softlayer_api_key: config[:softlayer_api_key],
130
+ softlayer_default_datacenter: config[:softlayer_datacenter],
131
+ softlayer_default_domain: config[:softlayer_domain]
132
+ )
133
+ end
134
+
135
+ def network
136
+ @network_connection ||= Fog::Network.new(
137
+ provider: :softlayer,
138
+ softlayer_username: config[:softlayer_username],
139
+ softlayer_api_key: config[:softlayer_api_key]
140
+ )
141
+ end
142
+
143
+ def find_server(hostname)
144
+ s = nil
145
+ servers = compute.servers.all
146
+ servers.each do |server|
147
+ if server.name == hostname
148
+ s = server
149
+ info "Server with hostname #{hostname} already created"
150
+ end
151
+ end
152
+ s
153
+ end
154
+
155
+ def create_server
156
+ server_def = init_configuration
157
+ # TODO: figure out network options
158
+ # if config[:network_ref]
159
+ # networks = [].concat([config[:network_ref]])
160
+ # server_def[:nics] = networks.flatten.map do |net|
161
+ # { 'net_id' => find_network(net).id }
162
+ # end
163
+ # end
164
+ [
165
+ :username,
166
+ :password,
167
+ :port,
168
+ :domain,
169
+ :fqdn,
170
+ :cpu,
171
+ :ram,
172
+ :disk,
173
+ :flavor_id,
174
+ :bare_metal,
175
+ :os_code,
176
+ :image_id,
177
+ :ephemeral_storage,
178
+ :network_components,
179
+ :account_id,
180
+ :single_tenant,
181
+ :global_identifier,
182
+ :tags,
183
+ :user_data,
184
+ :uid,
185
+ :vlan,
186
+ :private_vlan
187
+ ].each do |c|
188
+ server_def[c] = optional_config(c) if config[c]
189
+ end
190
+ debug "server_def: #{server_def}"
191
+ compute.servers.create(server_def)
192
+ end
193
+
194
+ def init_configuration
195
+ {
196
+ name: config[:server_name],
197
+ key_pairs: [compute.key_pairs.by_label(config[:key_name])],
198
+ hostname: config[:hostname],
199
+ datacenter: config[:datacenter],
200
+ hourly_billing_flag: config[:hourly_billing_flag],
201
+ private_network_only: config[:private_network_only]
202
+ }
203
+ end
204
+
205
+ def optional_config(c)
206
+ case c
207
+ when :user_data
208
+ File.open(config[c]).read if File.exist?(config[c])
209
+ else
210
+ config[c]
211
+ end
212
+ end
213
+
214
+ # Generate what should be a unique server name up to 63 total chars
215
+ # Base name: 15
216
+ # Username: 15
217
+ # Hostname: 23
218
+ # Random string: 7
219
+ # Separators: 3
220
+ # ================
221
+ # Total: 63
222
+ def default_name
223
+ [
224
+ instance.name.gsub(/\W/, '')[0..14],
225
+ (Etc.getlogin || 'nologin').gsub(/\W/, '')[0..14],
226
+ Socket.gethostname.gsub(/\W/, '')[0..22],
227
+ Array.new(7) { rand(36).to_s(36) }.join
228
+ ].join('-')
229
+ end
230
+
231
+ # TODO: code has support for multiple ips but not used.
232
+
233
+ def get_public_private_ips(server)
234
+ pub = server.public_ip
235
+ priv = server.private_ip
236
+ [pub, priv]
237
+ end
238
+
239
+ def get_ip(server)
240
+ pub, priv = get_public_private_ips(server)
241
+ pub, priv = parse_ips(pub, priv)
242
+ pub[config[:public_ip_order].to_i] ||
243
+ priv[config[:private_ip_order].to_i] ||
244
+ fail(ActionFailed, 'Could not find an IP')
245
+ if config[:private_network_only]
246
+ return priv[0]
247
+ else
248
+ return pub[0]
249
+ end
250
+ end
251
+
252
+ def parse_ips(pub, priv)
253
+ pub = Array(pub)
254
+ priv = Array(priv)
255
+ if config[:use_ipv6]
256
+ [pub, priv].each { |n| n.select! { |i| IPAddr.new(i).ipv6? } }
257
+ else
258
+ [pub, priv].each { |n| n.select! { |i| IPAddr.new(i).ipv4? } }
259
+ end
260
+ [pub, priv]
261
+ end
262
+
263
+ def setup_ssh(server, state)
264
+ tcp_check(state)
265
+ info "Using Softlayer keypair <#{config[:key_name]}>"
266
+ info "Using private SSH key <#{config[:ssh_key]}>"
267
+ state[:ssh_key] = config[:ssh_key]
268
+ # we don't call this as key_name must be set.
269
+ do_ssh_setup(state, config, server) unless config[:key_name]
270
+ end
271
+
272
+ def tcp_check(state)
273
+ # allow driver config to bypass SSH tcp check -- because
274
+ # it doesn't respect ssh_config values that might be required
275
+ if config[:no_ssh_tcp_check]
276
+ sleep(config[:no_ssh_tcp_check_sleep])
277
+ else
278
+ debug("wait_for_sshd hostname: #{state[:hostname]},username: #{config[:username]},port: #{config[:port]}")
279
+ wait_for_sshd(state[:hostname],
280
+ config[:username],
281
+ port: config[:port])
282
+ end
283
+ info '(ssh ready)'
284
+ end
285
+
286
+ def disable_ssl_validation
287
+ require 'excon'
288
+ Excon.defaults[:ssl_verify_peer] = false
289
+ end
290
+
291
+ def tag_server(server)
292
+ server.add_tags(config[:tags])
293
+ end
294
+
295
+ # TODO: add these checks
296
+ # def find_image(image_ref)
297
+ # image = find_matching(compute.images, image_ref)
298
+ # fail(ActionFailed, 'Image not found') unless image
299
+ # debug "Selected image: #{image.id} #{image.name}"
300
+ # image
301
+ # end
302
+
303
+ # def find_flavor(flavor_ref)
304
+ # flavor = find_matching(compute.flavors, flavor_ref)
305
+ # fail(ActionFailed, 'Flavor not found') unless flavor
306
+ # debug "Selected flavor: #{flavor.id} #{flavor.name}"
307
+ # flavor
308
+ # end
309
+
310
+ # def find_network(network_ref)
311
+ # net = find_matching(network.networks.all, network_ref)
312
+ # fail(ActionFailed, 'Network not found') unless net
313
+ # debug "Selected net: #{net.id} #{net.name}"
314
+ # net
315
+ # end
316
+
317
+ # def find_matching(collection, name)
318
+ # name = name.to_s
319
+ # if name.start_with?('/') && name.end_with?('/')
320
+ # regex = Regexp.new(name[1...-1])
321
+ # # check for regex name match
322
+ # collection.each { |single| return single if regex =~ single.name }
323
+ # else
324
+ # # check for exact id match
325
+ # collection.each { |single| return single if single.id == name }
326
+ # # check for exact name match
327
+ # collection.each { |single| return single if single.name == name }
328
+ # end
329
+ # nil
330
+ # end
331
+ end
332
+ end
333
+ end
@@ -0,0 +1,20 @@
1
+ # Encoding: UTF-8
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Kitchen
16
+ # Version string for Softlayer Kitchen driver
17
+ module Driver
18
+ SOFTLAYER_VERSION = '0.0.1'
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-softlayer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Neill Turner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: test-kitchen
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fog
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.18'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.18'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fog-softlayer
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
55
+ description: A Test Kitchen Softlayer driver
56
+ email:
57
+ - neillwturner@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - CHANGELOG.md
63
+ - LICENSE.txt
64
+ - README.md
65
+ - kitchen-softlayer.gemspec
66
+ - lib/kitchen/driver/softlayer.rb
67
+ - lib/kitchen/driver/softlayer_version.rb
68
+ homepage: https://github.com/test-kitchen/kitchen-softlayer
69
+ licenses:
70
+ - Apache
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 1.9.3
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.2.2
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Test Kitchen Softlayer driver
92
+ test_files: []