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 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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *~
2
+ *#
3
+ .ruby-version
4
+ *.gem
5
+ Gemfile.lock
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
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+
8
+ before_install:
9
+ - gem update bundler
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
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify dependencies in gemspec:
4
+ gemspec
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
+ [![Build Status](https://travis-ci.org/test-kitchen/kitchen-google.png?branch=master)](https://travis-ci.org/test-kitchen/kitchen-google)
4
+ [![Code Climate](https://codeclimate.com/github/test-kitchen/kitchen-google.png)](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,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Run RSpec unit tests'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: [:spec]
@@ -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
@@ -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: []