kitchen-google 0.3.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 +7 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +11 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +76 -0
- data/Gemfile +4 -0
- data/LICENSE +15 -0
- data/README.md +192 -0
- data/Rakefile +8 -0
- data/kitchen-google.gemspec +26 -0
- data/lib/kitchen/driver/gce.rb +170 -0
- data/spec/kitchen/driver/gce_spec.rb +398 -0
- data/spec/spec_helper.rb +21 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4085522e906870ad6ced21e1324fd139ffb2f454
|
4
|
+
data.tar.gz: e0337e83aa1ae41006264dfe93c0ddd2739f63f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b0b0e34c10fa46f788a8e36a11d637a2fe6d5e6729f7c023481a5fae135d4df1eab74ee7cf2c9a877bda863ceb3e46a9df27734ebb4857acb60aaa4669ef7c2a
|
7
|
+
data.tar.gz: a683597a6f9cd2eac0d90cf34bd2b7e4ab7c6612558781c52a78ed646c778b353b513603f9d9b215eb5534a7a6f810d248a27c6e2ca1f790b9953dc3355e5c08
|
data/.rubocop.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2014-09-20 08:00:47 -0700 using RuboCop version 0.26.0.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 1
|
9
|
+
# Configuration parameters: CountComments.
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Max: 102
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
## 0.3.0 / 2016-01-23
|
2
|
+
|
3
|
+
### New Features
|
4
|
+
|
5
|
+
* #14: Support service_accounts option in Fog
|
6
|
+
* #22: Add JSON credential file and Preemptible VM support
|
7
|
+
|
8
|
+
### Improvements
|
9
|
+
|
10
|
+
* Move to test-kitchen GitHub org
|
11
|
+
* Fixes to tests
|
12
|
+
|
13
|
+
## 0.2.0 / 2014-09-20
|
14
|
+
|
15
|
+
### Improvements
|
16
|
+
|
17
|
+
* #10: Deprecate "area" in configuration for "region"
|
18
|
+
* #11: Fix name length, via @pdunnavant
|
19
|
+
* #12: Generate instance names that are valid for GCE
|
20
|
+
|
21
|
+
## 0.1.2 / 2014-04-16
|
22
|
+
|
23
|
+
### New Features
|
24
|
+
|
25
|
+
* Add documentation for new asia-east1 region.
|
26
|
+
|
27
|
+
### Improvements
|
28
|
+
|
29
|
+
* #9: Dependency updates: Remove faraday version constraint; require newer
|
30
|
+
ridley gem.
|
31
|
+
|
32
|
+
## 0.1.0 / 2014-03-29
|
33
|
+
|
34
|
+
### New Features
|
35
|
+
|
36
|
+
* PR #7: Add support for specifying SSH keys in public_key_path, via @someara
|
37
|
+
* Add support for setting username
|
38
|
+
* Support GCE v1 API, including persistent disks.
|
39
|
+
|
40
|
+
### Improvements
|
41
|
+
|
42
|
+
* Add rspec tests and Travis support.
|
43
|
+
|
44
|
+
## 0.0.6 / 2014-02-23:
|
45
|
+
|
46
|
+
* Require Ruby 1.9 or greater.
|
47
|
+
|
48
|
+
### Improvements
|
49
|
+
|
50
|
+
* Add support for specifying GCE network and tags.
|
51
|
+
|
52
|
+
### Bug fixes
|
53
|
+
|
54
|
+
* Temporarily pin Fog version to 1.19.0 until 1.20.0 support is added.
|
55
|
+
* Require Faraday Gem version to be ~> 0.8.9; 0.9.0 breaks test-kitchen.
|
56
|
+
|
57
|
+
## 0.0.4 / 2013-12-28
|
58
|
+
|
59
|
+
### Bug fixes
|
60
|
+
|
61
|
+
* In GCE, instance names must be unique; derive by default from
|
62
|
+
`<suite>-<platform>` and a UUID.
|
63
|
+
* Fix bug where running `kitchen create` multiple times would create
|
64
|
+
duplicate instances.
|
65
|
+
* Require version of Fog with exponential backoff in GCE API queries.
|
66
|
+
|
67
|
+
### Improvements
|
68
|
+
|
69
|
+
* README formatting and clarity fixes.
|
70
|
+
* Add concept of an "area" (us, europe, any) to automatically select
|
71
|
+
an availability zone from those that are up within the requested
|
72
|
+
area for each instance.
|
73
|
+
|
74
|
+
## 0.0.1 / 2013-10-20
|
75
|
+
|
76
|
+
### Initial release
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Author:: Andrew Leonard (<andy@hurricane-ridge.com>)
|
2
|
+
|
3
|
+
Copyright (C) 2013-2014, Andrew Leonard
|
4
|
+
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
you may not use this file except in compliance with the License.
|
7
|
+
You may obtain a copy of the License at
|
8
|
+
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
See the License for the specific language governing permissions and
|
15
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
# Kitchen::Gce - A Test Kitchen Driver for Google Compute Engine
|
2
|
+
|
3
|
+
[](https://travis-ci.org/test-kitchen/kitchen-google)
|
4
|
+
[](https://codeclimate.com/github/test-kitchen/kitchen-google)
|
5
|
+
|
6
|
+
This is a [Test Kitchen](https://github.com/opscode/test-kitchen/)
|
7
|
+
driver for Google Compute Engine. While similar to EC2 and other IaaS
|
8
|
+
providers, GCE has a couple of advantages for Chef cookbook testing:
|
9
|
+
|
10
|
+
* (Subjectively) faster instance launch times; and
|
11
|
+
* Sub-hour billing.
|
12
|
+
|
13
|
+
## Requirements
|
14
|
+
|
15
|
+
Ruby 1.9 or greater.
|
16
|
+
|
17
|
+
A [Google Cloud Platform](https://cloud.google.com) account is
|
18
|
+
required. If you do not already have an appropriate "project" in
|
19
|
+
which to run your test-kitchen instances, create one, noting the
|
20
|
+
"project id". Then, within the [Google API
|
21
|
+
Console](https://code.google.com/apis/console/), create a "service
|
22
|
+
account" for the project under the "API Access" tab. Save the key
|
23
|
+
file, and note the email address associated with the service account
|
24
|
+
(e.g. 123456789012@developer.gserviceaccount.com - not the project
|
25
|
+
owner's email address).
|
26
|
+
|
27
|
+
If you are not using the `public_key_path` setting (see below) and
|
28
|
+
have not [set up SSH keys for your GCE
|
29
|
+
environment](https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys),
|
30
|
+
you must also do that prior to using kitchen-gce. Also, you will
|
31
|
+
likely want to add your SSH keys to ssh-agent prior to converging any
|
32
|
+
instances.
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
|
36
|
+
Assuming you are using Bundler, ensure the Gemfile within your Chef
|
37
|
+
cookbook contains at least the following:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
source 'https://rubygems.org'
|
41
|
+
|
42
|
+
gem 'berkshelf'
|
43
|
+
|
44
|
+
group :integration do
|
45
|
+
gem 'kitchen-gce'
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
Then, execute `bundle install`.
|
50
|
+
|
51
|
+
## Configuration
|
52
|
+
|
53
|
+
### `area`
|
54
|
+
|
55
|
+
Deprecated - use equivalent [`region`](#region) instead. If both `area` and
|
56
|
+
`region` are set, the value of `region` will be used.
|
57
|
+
|
58
|
+
### `autodelete_disk`
|
59
|
+
|
60
|
+
Boolean specifying whether or not to automatically delete boot disk
|
61
|
+
for test instance. Default: `true`
|
62
|
+
|
63
|
+
### `disk_size`
|
64
|
+
|
65
|
+
Size, in gigabytes, of boot disk. Default: `10`.
|
66
|
+
|
67
|
+
### `google_client_email`
|
68
|
+
|
69
|
+
**Required** Email address associated with your GCE service account.
|
70
|
+
(N.B. - this is not the same as the Google Cloud Platform user's email
|
71
|
+
account; should be in the form
|
72
|
+
"123456789012@developer.gserviceaccount.com".)
|
73
|
+
|
74
|
+
### `google_key_location`
|
75
|
+
|
76
|
+
**Required** Path to GCE service account key file.
|
77
|
+
|
78
|
+
### `google_project`
|
79
|
+
|
80
|
+
**Required** Project ID of the GCE project into which test-kitchen
|
81
|
+
instances will be launched.
|
82
|
+
|
83
|
+
### `image_name`
|
84
|
+
|
85
|
+
**Required** Operating system image to deploy.
|
86
|
+
|
87
|
+
### `inst_name`
|
88
|
+
|
89
|
+
Name to give to instance; unlike EC2's "Name" tag, this is used as an
|
90
|
+
instance identifier and must be unique. If none is specified, a unique
|
91
|
+
name will be auto-generated; note that auto-generated names must be
|
92
|
+
used if there is more than one test suite. Default:
|
93
|
+
`<suite>-<platform>-<UUID>`
|
94
|
+
|
95
|
+
### `machine_type`
|
96
|
+
|
97
|
+
GCE instance type (size) to launch; default: `n1-standard-1`
|
98
|
+
|
99
|
+
### `network`
|
100
|
+
|
101
|
+
GCE network that instance will be attached to; default: `default`
|
102
|
+
|
103
|
+
### `preemptible`
|
104
|
+
|
105
|
+
If set to `true`, GCE instance will be brought up as a [preemptible](https://cloud.google.com/compute/docs/instances/preemptible) virtual machine,
|
106
|
+
that runs at a much lower price than normal instances. However, Compute
|
107
|
+
Engine might terminate (preempt) these instances if it requires access
|
108
|
+
to those resources for other tasks; default: `false`
|
109
|
+
|
110
|
+
### `public_key_path`
|
111
|
+
|
112
|
+
Path to the public half of the ssh key that will be deployed to
|
113
|
+
`~username/.ssh/authorized_keys`; see also [`username`](#username) below.
|
114
|
+
|
115
|
+
### `region`
|
116
|
+
|
117
|
+
Region in which to launch instances. `region` is defined as the part
|
118
|
+
prior to the second hyphen in an availability zone's name; e.g. in
|
119
|
+
`us-central1-b`, the region is `us-central1`. Specifying region but
|
120
|
+
not `zone_name` allows kitchen-gce to avoid launching instances into a
|
121
|
+
zone that is down for maintenance. If `any` is specified, kitchen-gce
|
122
|
+
will select a zone from all regions. Default: `us-central1` (lowest
|
123
|
+
cost region); valid values: `any`, `asia-east1`, `europe-west1`,
|
124
|
+
`us-central1`
|
125
|
+
|
126
|
+
### `tags`
|
127
|
+
|
128
|
+
Array of tags to associate with instance; default: `[]`
|
129
|
+
|
130
|
+
### `username`
|
131
|
+
|
132
|
+
Username test-kitchen will log into instance as; default: `ENV['USER']`
|
133
|
+
|
134
|
+
### `zone_name`
|
135
|
+
|
136
|
+
Location into which instances will be launched. If not specified, a
|
137
|
+
zone is chosen from available zones within the [`region`](#region).
|
138
|
+
|
139
|
+
## Example
|
140
|
+
|
141
|
+
An example `.kitchen.yml` file using kitchen-gce might look something
|
142
|
+
like this:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
---
|
146
|
+
driver_plugin: gce
|
147
|
+
driver_config:
|
148
|
+
google_client_email: "123456789012@developer.gserviceaccount.com"
|
149
|
+
google_key_location: "<%= ENV['HOME']%>/gce/1234567890abcdef1234567890abcdef12345678-privatekey.p12"
|
150
|
+
google_project: "alpha-bravo-123"
|
151
|
+
network: "kitchenci"
|
152
|
+
region: any
|
153
|
+
|
154
|
+
platforms:
|
155
|
+
- name: debian-7
|
156
|
+
driver_config:
|
157
|
+
image_name: debian-7-wheezy-v20151104
|
158
|
+
require_chef_omnibus: true
|
159
|
+
public_key_path: '/home/alice/.ssh/google_compute_engine.pub'
|
160
|
+
tags: ["somerole"]
|
161
|
+
|
162
|
+
suites:
|
163
|
+
- name: default
|
164
|
+
run_list: ["recipe[somecookbook]"]
|
165
|
+
attributes: {}
|
166
|
+
```
|
167
|
+
|
168
|
+
## Development
|
169
|
+
|
170
|
+
Source is hosted on [GitHub](https://github.com/anl/kitchen-gce).
|
171
|
+
|
172
|
+
* Pull requests are welcome, using topic branches if possible:
|
173
|
+
|
174
|
+
1. Fork the repo.
|
175
|
+
2. Create a feature branch, commit changes to it and push them.
|
176
|
+
3. Submit a pull request.
|
177
|
+
|
178
|
+
* Report issues or submit feature requests on [GitHub](https://github.com/anl/kitchen-gce/issues)
|
179
|
+
|
180
|
+
## Author, Acknowledgements, Etc.
|
181
|
+
|
182
|
+
Created and maintained by [Andrew Leonard](http://andyleonard.com)
|
183
|
+
([andy@hurricane-ridge.com](mailto:andy@hurricane-ridge.com)).
|
184
|
+
|
185
|
+
The initial release drew heavily on the
|
186
|
+
[kitchen-ec2](https://github.com/opscode/kitchen-ec2/) gem for both
|
187
|
+
inspiration and implementation details. Any bugs, however, are solely
|
188
|
+
the author's own doing.
|
189
|
+
|
190
|
+
## License
|
191
|
+
|
192
|
+
Licensed under Apache 2.0.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = 'kitchen-google'
|
4
|
+
s.version = '0.3.0'
|
5
|
+
s.date = '2016-01-23'
|
6
|
+
s.summary = 'Kitchen::Driver::Gce'
|
7
|
+
s.description = 'A Test-Kitchen driver for Google Compute Engine'
|
8
|
+
s.authors = ['Andrew Leonard']
|
9
|
+
s.email = 'andy@hurricane-ridge.com'
|
10
|
+
s.files = `git ls-files`.split($/) # rubocop:disable SpecialGlobalVars
|
11
|
+
s.homepage = 'https://github.com/test-kitchen/kitchen-google'
|
12
|
+
s.license = 'Apache 2.0'
|
13
|
+
|
14
|
+
s.add_dependency 'fog', '>= 1.31.0'
|
15
|
+
s.add_dependency 'google-api-client'
|
16
|
+
s.add_dependency 'ridley', '>= 3.0.0' # See GH issue RiotGames/ridley#239
|
17
|
+
s.add_dependency 'test-kitchen'
|
18
|
+
|
19
|
+
s.add_development_dependency 'bundler'
|
20
|
+
s.add_development_dependency 'pry'
|
21
|
+
s.add_development_dependency 'rake'
|
22
|
+
s.add_development_dependency 'rspec'
|
23
|
+
s.add_development_dependency 'rubocop'
|
24
|
+
|
25
|
+
s.required_ruby_version = '>= 1.9'
|
26
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Andrew Leonard (<andy@hurricane-ridge.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013-2014, Andrew Leonard
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'fog'
|
20
|
+
require 'securerandom'
|
21
|
+
|
22
|
+
require 'kitchen'
|
23
|
+
|
24
|
+
module Kitchen
|
25
|
+
module Driver
|
26
|
+
# Google Compute Engine driver for Test Kitchen
|
27
|
+
#
|
28
|
+
# @author Andrew Leonard <andy@hurricane-ridge.com>
|
29
|
+
class Gce < Kitchen::Driver::SSHBase
|
30
|
+
default_config :area, 'us-central1'
|
31
|
+
default_config :autodelete_disk, true
|
32
|
+
default_config :disk_size, 10
|
33
|
+
default_config :machine_type, 'n1-standard-1'
|
34
|
+
default_config :network, 'default'
|
35
|
+
default_config :inst_name, nil
|
36
|
+
default_config :service_accounts, nil
|
37
|
+
default_config :tags, []
|
38
|
+
default_config :username, ENV['USER']
|
39
|
+
default_config :zone_name, nil
|
40
|
+
default_config :google_key_location, nil
|
41
|
+
default_config :google_json_key_location, nil
|
42
|
+
default_config :preemptible, false
|
43
|
+
default_config :auto_restart, false
|
44
|
+
|
45
|
+
required_config :google_client_email
|
46
|
+
required_config :google_project
|
47
|
+
required_config :image_name
|
48
|
+
|
49
|
+
def create(state)
|
50
|
+
return if state[:server_id]
|
51
|
+
|
52
|
+
instance = create_instance
|
53
|
+
state[:server_id] = instance.identity
|
54
|
+
|
55
|
+
info("GCE instance <#{state[:server_id]}> created.")
|
56
|
+
|
57
|
+
wait_for_up_instance(instance, state)
|
58
|
+
|
59
|
+
rescue Fog::Errors::Error, Excon::Errors::Error => ex
|
60
|
+
raise ActionFailed, ex.message
|
61
|
+
end
|
62
|
+
|
63
|
+
def destroy(state)
|
64
|
+
return if state[:server_id].nil?
|
65
|
+
|
66
|
+
instance = connection.servers.get(state[:server_id])
|
67
|
+
instance.destroy unless instance.nil?
|
68
|
+
info("GCE instance <#{state[:server_id]}> destroyed.")
|
69
|
+
state.delete(:server_id)
|
70
|
+
state.delete(:hostname)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def connection
|
76
|
+
options = {
|
77
|
+
provider: 'google',
|
78
|
+
google_client_email: config[:google_client_email],
|
79
|
+
google_project: config[:google_project]
|
80
|
+
}
|
81
|
+
|
82
|
+
[
|
83
|
+
:google_key_location,
|
84
|
+
:google_json_key_location
|
85
|
+
].each do |k|
|
86
|
+
options[k] = config[k] unless config[k].nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
Fog::Compute.new(options)
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_disk
|
93
|
+
disk = connection.disks.create(
|
94
|
+
name: config[:inst_name],
|
95
|
+
size_gb: config[:disk_size],
|
96
|
+
zone_name: config[:zone_name],
|
97
|
+
source_image: config[:image_name]
|
98
|
+
)
|
99
|
+
|
100
|
+
disk.wait_for { disk.ready? }
|
101
|
+
disk
|
102
|
+
end
|
103
|
+
|
104
|
+
def create_instance
|
105
|
+
config[:region] ||= config[:area]
|
106
|
+
|
107
|
+
config[:inst_name] ||= generate_inst_name
|
108
|
+
config[:zone_name] ||= select_zone
|
109
|
+
|
110
|
+
disk = create_disk
|
111
|
+
create_server(disk)
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_server(disk)
|
115
|
+
connection.servers.create(
|
116
|
+
name: config[:inst_name],
|
117
|
+
disks: [disk.get_as_boot_disk(true, config[:autodelete_disk])],
|
118
|
+
machine_type: config[:machine_type],
|
119
|
+
network: config[:network],
|
120
|
+
service_accounts: config[:service_accounts],
|
121
|
+
tags: config[:tags],
|
122
|
+
zone_name: config[:zone_name],
|
123
|
+
public_key_path: config[:public_key_path],
|
124
|
+
username: config[:username],
|
125
|
+
preemptible: config[:preemptible],
|
126
|
+
on_host_maintenance: config[:preemptible] ? 'TERMINATE': 'MIGRATE',
|
127
|
+
auto_restart: config[:auto_restart]
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
def generate_inst_name
|
132
|
+
# Inspired by generate_name from kitchen-rackspace
|
133
|
+
name = instance.name.downcase
|
134
|
+
name.gsub!(/([^-a-z0-9])/, '-')
|
135
|
+
name = 't' + name unless name =~ /^[a-z]/
|
136
|
+
base_name = name[0..25] # UUID is 36 chars, max name length 63
|
137
|
+
gen_name = "#{base_name}-#{SecureRandom.uuid}"
|
138
|
+
unless gen_name =~ /^[a-z]([-a-z0-9]*[a-z0-9])?$/
|
139
|
+
fail "Invalid generated instance name: #{gen_name}"
|
140
|
+
end
|
141
|
+
gen_name
|
142
|
+
end
|
143
|
+
|
144
|
+
def select_zone
|
145
|
+
if config[:region] == 'any'
|
146
|
+
zone_regexp = /^[a-z]+\-/
|
147
|
+
else
|
148
|
+
zone_regexp = /^#{config[:region]}\-/
|
149
|
+
end
|
150
|
+
zones = connection.zones.select do |z|
|
151
|
+
z.status == 'UP' && z.name.match(zone_regexp)
|
152
|
+
end
|
153
|
+
fail 'No up zones in region' unless zones.length >= 1
|
154
|
+
zones.sample.name
|
155
|
+
end
|
156
|
+
|
157
|
+
def wait_for_up_instance(instance, state)
|
158
|
+
instance.wait_for do
|
159
|
+
print '.'
|
160
|
+
ready?
|
161
|
+
end
|
162
|
+
print '(server ready)'
|
163
|
+
state[:hostname] = instance.public_ip_address ||
|
164
|
+
instance.private_ip_address
|
165
|
+
wait_for_sshd(state[:hostname], config[:username])
|
166
|
+
puts '(ssh ready)'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,398 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Andrew Leonard (<andy@hurricane-ridge.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013-2014, Andrew Leonard
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative '../../spec_helper.rb'
|
20
|
+
|
21
|
+
require 'resolv'
|
22
|
+
|
23
|
+
describe Kitchen::Driver::Gce do
|
24
|
+
|
25
|
+
let(:config) do
|
26
|
+
{ google_client_email: '123456789012@developer.gserviceaccount.com',
|
27
|
+
google_project: 'alpha-bravo-123'
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:state) { Hash.new }
|
32
|
+
|
33
|
+
let(:logged_output) { StringIO.new }
|
34
|
+
let(:logger) { Logger.new(logged_output) }
|
35
|
+
|
36
|
+
let(:instance) do
|
37
|
+
double(
|
38
|
+
logger: logger,
|
39
|
+
name: 'default-distro-12'
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:driver) do
|
44
|
+
d = Kitchen::Driver::Gce.new(config)
|
45
|
+
allow(d).to receive(:instance) { instance }
|
46
|
+
allow(d).to receive(:wait_for_sshd) { true }
|
47
|
+
d
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:fog) do
|
51
|
+
Fog::Compute::Google::Mock.new({})
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:disk) do
|
55
|
+
fog.disks.create(
|
56
|
+
name: 'rspec-test-disk',
|
57
|
+
size_gb: 10,
|
58
|
+
zone_name: 'us-central1-b',
|
59
|
+
source_image: 'debian-7-wheezy-v20130816'
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
let(:server) do
|
64
|
+
fog.servers.create(
|
65
|
+
name: 'rspec-test-instance',
|
66
|
+
disks: [disk],
|
67
|
+
machine_type: 'n1-standard-1',
|
68
|
+
zone_name: 'us-central1-b'
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
before(:each) do
|
73
|
+
Fog.mock!
|
74
|
+
Fog::Mock.reset
|
75
|
+
Fog::Mock.delay = 0
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#initialize' do
|
79
|
+
context 'with default options' do
|
80
|
+
|
81
|
+
defaults = {
|
82
|
+
area: 'us-central1',
|
83
|
+
autodelete_disk: true,
|
84
|
+
disk_size: 10,
|
85
|
+
inst_name: nil,
|
86
|
+
machine_type: 'n1-standard-1',
|
87
|
+
network: 'default',
|
88
|
+
region: nil,
|
89
|
+
service_accounts: nil,
|
90
|
+
tags: [],
|
91
|
+
username: ENV['USER'],
|
92
|
+
zone_name: nil,
|
93
|
+
google_key_location: nil,
|
94
|
+
google_json_key_location: nil,
|
95
|
+
preemptible: false,
|
96
|
+
auto_restart: false
|
97
|
+
}
|
98
|
+
|
99
|
+
defaults.each do |k, v|
|
100
|
+
it "sets the correct default for #{k}" do
|
101
|
+
expect(driver[k]).to eq(v)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'with overriden options' do
|
107
|
+
overrides = {
|
108
|
+
area: 'europe-west',
|
109
|
+
autodelete_disk: false,
|
110
|
+
disk_size: 15,
|
111
|
+
inst_name: 'ci-instance',
|
112
|
+
machine_type: 'n1-highmem-8',
|
113
|
+
network: 'dev-net',
|
114
|
+
region: 'asia-east1',
|
115
|
+
service_accounts: %w(userdata.email compute.readonly),
|
116
|
+
tags: %w(qa integration),
|
117
|
+
username: 'root',
|
118
|
+
zone_name: 'europe-west1-a',
|
119
|
+
google_key_location: '/path/to/foo.p12',
|
120
|
+
google_json_key_location: '/path/to/bar.json',
|
121
|
+
preemptible: true,
|
122
|
+
auto_restart: false # because of preemptible, see kitchen-google/pull/22
|
123
|
+
}
|
124
|
+
|
125
|
+
let(:config) { overrides }
|
126
|
+
|
127
|
+
overrides.each do |k, v|
|
128
|
+
it "overrides the default value for #{k}" do
|
129
|
+
expect(driver[k]).to eq(v)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#connection' do
|
136
|
+
context 'with required variables set' do
|
137
|
+
it 'returns a Fog Compute object' do
|
138
|
+
expect(driver.send(:connection)).to be_a(Fog::Compute::Google::Mock)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'uses the v1 api version' do
|
142
|
+
conn = driver.send(:connection)
|
143
|
+
expect(conn.api_version).to eq('v1')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'without required variables set' do
|
148
|
+
let(:config) { Hash.new }
|
149
|
+
|
150
|
+
it 'raises an error' do
|
151
|
+
expect { driver.send(:connection) }.to raise_error(ArgumentError)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe '#create' do
|
157
|
+
context 'with an existing server' do
|
158
|
+
let(:state) do
|
159
|
+
s = Hash.new
|
160
|
+
s[:server_id] = 'default-distro-12345678'
|
161
|
+
s
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'returns if server_id already exists' do
|
165
|
+
expect(driver.create(state)).to equal nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when an instance is successfully created' do
|
170
|
+
|
171
|
+
let(:driver) do
|
172
|
+
d = Kitchen::Driver::Gce.new(config)
|
173
|
+
allow(d).to receive(:create_instance) { server }
|
174
|
+
allow(d).to receive(:wait_for_up_instance) { nil }
|
175
|
+
d
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'sets a value for server_id in the state hash' do
|
179
|
+
driver.send(:create, state)
|
180
|
+
expect(state[:server_id]).to eq('rspec-test-instance')
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'returns nil' do
|
184
|
+
expect(driver.send(:create, state)).to equal(nil)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '#create_disk' do
|
190
|
+
context 'with defaults and required options' do
|
191
|
+
it 'returns a Google Disk object' do
|
192
|
+
config[:image_name] = 'debian-7-wheezy-v20130816'
|
193
|
+
config[:inst_name] = 'rspec-disk'
|
194
|
+
config[:zone_name] = 'us-central1-a'
|
195
|
+
expect(driver.send(:create_disk)).to be_a(Fog::Compute::Google::Disk)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'without required options' do
|
200
|
+
it 'returns a Fog NotFound Error' do
|
201
|
+
expect { driver.send(:create_disk) }.to raise_error(
|
202
|
+
Fog::Errors::NotFound)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe '#create_instance' do
|
208
|
+
context 'with default options' do
|
209
|
+
it 'returns a Fog Compute Server object' do
|
210
|
+
expect(driver.send(:create_instance)).to be_a(
|
211
|
+
Fog::Compute::Google::Server)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'sets the region to the default "us-central1"' do
|
215
|
+
driver.send(:create_instance)
|
216
|
+
expect(config[:region]).to eq('us-central1')
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'area set, region unset' do
|
221
|
+
let(:config) do
|
222
|
+
{ area: 'europe-west1',
|
223
|
+
google_client_email: '123456789012@developer.gserviceaccount.com',
|
224
|
+
google_key_location: '/home/user/gce/123456-privatekey.p12',
|
225
|
+
google_project: 'alpha-bravo-123'
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'sets region to the area value' do
|
230
|
+
driver.send(:create_instance)
|
231
|
+
expect(config[:region]).to eq(config[:area])
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'area set, region set' do
|
236
|
+
let(:config) do
|
237
|
+
{ area: 'fugazi',
|
238
|
+
google_client_email: '123456789012@developer.gserviceaccount.com',
|
239
|
+
google_key_location: '/home/user/gce/123456-privatekey.p12',
|
240
|
+
google_project: 'alpha-bravo-123',
|
241
|
+
region: 'europe-west1'
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'sets the region independent of the area value' do
|
246
|
+
driver.send(:create_instance)
|
247
|
+
expect(config[:region]).to eq('europe-west1')
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe '#create_server' do
|
254
|
+
context 'with default options' do
|
255
|
+
it 'returns a Fog Compute Server object' do
|
256
|
+
expect(driver.send(:create_instance)).to be_a(
|
257
|
+
Fog::Compute::Google::Server)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe '#destroy' do
|
263
|
+
let(:state) do
|
264
|
+
s = Hash.new
|
265
|
+
s[:server_id] = 'rspec-test-instance'
|
266
|
+
s[:hostname] = '198.51.100.17'
|
267
|
+
s
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'returns if server_id does not exist' do
|
271
|
+
expect(driver.destroy({})).to equal nil
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'removes the server state information' do
|
275
|
+
driver.destroy(state)
|
276
|
+
expect(state[:hostname]).to equal(nil)
|
277
|
+
expect(state[:server_id]).to equal(nil)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe '#generate_inst_name' do
|
282
|
+
context 'with a name less than 28 characters' do
|
283
|
+
it 'concatenates the name and a UUID' do
|
284
|
+
expect(driver.send(:generate_inst_name)).to match(
|
285
|
+
/^default-distro-12-[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context 'with a name 27 characters or longer' do
|
290
|
+
let(:instance) do
|
291
|
+
double(name: 'a23456789012345678901234567')
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'shortens the base name and appends a UUID' do
|
295
|
+
expect(driver.send(:generate_inst_name).length).to eq 63
|
296
|
+
expect(driver.send(:generate_inst_name)).to match(
|
297
|
+
/^a2345678901234567890123456
|
298
|
+
-[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/x)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context 'with a "name" value containing an invalid leading character' do
|
303
|
+
let(:instance) do
|
304
|
+
double(name: '12345')
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'adds a leading "t"' do
|
308
|
+
expect(driver.send(:generate_inst_name)).to match(
|
309
|
+
/^t12345
|
310
|
+
-[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/x)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'with a "name" value containing uppercase letters' do
|
315
|
+
let(:instance) do
|
316
|
+
double(name: 'AbCdEf')
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'downcases the "name" characters in the instance name' do
|
320
|
+
expect(driver.send(:generate_inst_name)).to match(
|
321
|
+
/^abcdef
|
322
|
+
-[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/x)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context 'with a name value containing invalid characters' do
|
327
|
+
let(:instance) do
|
328
|
+
double(name: 'a!b@c#d$e%f^g&h*i(j)')
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'replaces the invalid characters with dashes' do
|
332
|
+
expect(driver.send(:generate_inst_name)).to match(
|
333
|
+
/^a-b-c-d-e-f-g-h-i-j-
|
334
|
+
-[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/x)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe '#select_zone' do
|
340
|
+
context 'when choosing from any region' do
|
341
|
+
let(:config) do
|
342
|
+
{ region: 'any',
|
343
|
+
google_client_email: '123456789012@developer.gserviceaccount.com',
|
344
|
+
google_key_location: '/home/user/gce/123456-privatekey.p12',
|
345
|
+
google_project: 'alpha-bravo-123'
|
346
|
+
}
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'chooses from all zones' do
|
350
|
+
expect(driver.send(:select_zone)).to satisfy do |zone|
|
351
|
+
%w(europe-west1-a us-central1-a us-central1-b
|
352
|
+
us-central2-a).include?(zone)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
context 'when choosing from the "europe-west1" region' do
|
358
|
+
let(:config) do
|
359
|
+
{ region: 'europe-west1',
|
360
|
+
google_client_email: '123456789012@developer.gserviceaccount.com',
|
361
|
+
google_key_location: '/home/user/gce/123456-privatekey.p12',
|
362
|
+
google_project: 'alpha-bravo-123'
|
363
|
+
}
|
364
|
+
end
|
365
|
+
|
366
|
+
it 'chooses a zone in europe-west1' do
|
367
|
+
expect(driver.send(:select_zone)).to satisfy do |zone|
|
368
|
+
%w(europe-west1-a).include?(zone)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
context 'when choosing from the default "us-central1" region' do
|
374
|
+
let(:config) do
|
375
|
+
{ region: 'us-central1',
|
376
|
+
google_client_email: '123456789012@developer.gserviceaccount.com',
|
377
|
+
google_key_location: '/home/user/gce/123456-privatekey.p12',
|
378
|
+
google_project: 'alpha-bravo-123'
|
379
|
+
}
|
380
|
+
end
|
381
|
+
|
382
|
+
it 'chooses a zone in us-central1' do
|
383
|
+
expect(driver.send(:select_zone)).to satisfy do |zone|
|
384
|
+
%w(us-central1-a us-central1-b us-central2-a).include?(zone)
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
describe '#wait_for_up_instance' do
|
392
|
+
it 'sets the hostname' do
|
393
|
+
driver.send(:wait_for_up_instance, server, state)
|
394
|
+
# Mock instance gives us a random IP each time:
|
395
|
+
expect(state[:hostname]).to match(Resolv::IPv4::Regex)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Andrew Leonard (<andy@hurricane-ridge.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013-2014, Andrew Leonard
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'rspec'
|
20
|
+
|
21
|
+
require_relative '../lib/kitchen/driver/gce'
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kitchen-google
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Leonard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fog
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.31.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.31.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: google-api-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ridley
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: test-kitchen
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: A Test-Kitchen driver for Google Compute Engine
|
140
|
+
email: andy@hurricane-ridge.com
|
141
|
+
executables: []
|
142
|
+
extensions: []
|
143
|
+
extra_rdoc_files: []
|
144
|
+
files:
|
145
|
+
- .gitignore
|
146
|
+
- .rubocop.yml
|
147
|
+
- .rubocop_todo.yml
|
148
|
+
- .travis.yml
|
149
|
+
- CHANGELOG.md
|
150
|
+
- Gemfile
|
151
|
+
- LICENSE
|
152
|
+
- README.md
|
153
|
+
- Rakefile
|
154
|
+
- kitchen-google.gemspec
|
155
|
+
- lib/kitchen/driver/gce.rb
|
156
|
+
- spec/kitchen/driver/gce_spec.rb
|
157
|
+
- spec/spec_helper.rb
|
158
|
+
homepage: https://github.com/test-kitchen/kitchen-google
|
159
|
+
licenses:
|
160
|
+
- Apache 2.0
|
161
|
+
metadata: {}
|
162
|
+
post_install_message:
|
163
|
+
rdoc_options: []
|
164
|
+
require_paths:
|
165
|
+
- lib
|
166
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - '>='
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '1.9'
|
171
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
requirements: []
|
177
|
+
rubyforge_project:
|
178
|
+
rubygems_version: 2.0.14
|
179
|
+
signing_key:
|
180
|
+
specification_version: 4
|
181
|
+
summary: Kitchen::Driver::Gce
|
182
|
+
test_files: []
|