kitchen-softlayer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []