kitchen-digital_ocean 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: fc1701a957915027c014f74ee178a5222744d634
4
+ data.tar.gz: c5355d1367f8c36c9144aa7239798cdec06f8f88
5
+ SHA512:
6
+ metadata.gz: 209df6a181b18ab1a2977ba447e7eab39700b13b74c3b28e15b500ee0346799d3b04005a07cc9bb04e2751b7d4f3cfa2c0ed9943940e709ccbd66068336d381b
7
+ data.tar.gz: 092cee75876360102fc19761d7f00b013271d7d7baa561b411c5069d920e4795bb8b0fee375dda022053a05c93d924fa9f1efde5cab78a9ba31b81f6b05f6f04
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .kitchen
19
+ *.sw?
20
+ *~
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kitchen-digitalocean.gemspec
4
+ gemspec
5
+
6
+ # vim: ai et ts=2 sts=2 sw=2 ft=ruby
data/LICENSE.txt ADDED
@@ -0,0 +1,17 @@
1
+ Author:: Greg Fitzgerald (<greg@gregf.org>)
2
+
3
+ Copyright (C) 2013, Greg Fitzgerald
4
+ Copyright (C) 2014, Will Farrington
5
+
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.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Kitchen::DigitalOcean
2
+
3
+ A Test Kitchen driver for Digital Ocean API v2.
4
+
5
+ Forked from the official [test-kitchen/kitchen-digitalocean driver](https://github.com/test-kitchen/kitchen-digitalocean).
6
+
7
+ ## Requirements
8
+
9
+ * Obviously, this gem depends on Test Kitchen.
10
+ * It also depends on `rest_client`, but that'll automatically be handled via RubyGems.
11
+ * You also need a Digital Ocean account.
12
+ * You need to define the following environment variables:
13
+ * `DIGITALOCEAN_API_TOKEN` -- your API token (requires read+write)
14
+ * `DIGITALOCEAN_SSH_KEYS` -- comma-separated list of SSH key IDs (get from Digital Ocean API)
15
+
16
+ ## Installation and Setup
17
+
18
+ 1. Use ChefDK.
19
+ 1. Be happy.
20
+
21
+ ```
22
+ chef gem install kitchen-digital_ocean
23
+ ```
24
+
25
+ In your `.kitchen.yml` or `.kitchen.local.yml`:
26
+
27
+ ``` yaml
28
+ ---
29
+ driver:
30
+ name: digitalocean
31
+
32
+ platforms:
33
+ - name: ubuntu-12.10
34
+ ```
35
+
36
+ ## Additional configuration options
37
+
38
+ * `username` -- user name to SSH with
39
+ * `port` -- SSH port to SSH into
40
+ * `private_networking` -- enable private networking on the drpolet
41
+ * `region` -- the region to provision the droplet in; you can use the short slugs (eg. `nyc2`)
42
+ * `size` -- the size to provision the droplet as; you can use the short slugs (eg. `2gb`)
43
+ * `image` -- the image to provision the droplet with; you can use the short slugs
44
+ * `server_name` -- you probably want to leave this alone
45
+ * `digitalocean_api_token` -- you can set this, but seriously use the environment variable above
46
+ * `digitalocean_ssh_keys` -- you can set this, but seriously use the environment variable above
47
+
48
+ For more details, see the [Digital Ocean API documentation](https://developers.digitalocean.com/).
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'kitchen-digital_ocean'
5
+ spec.version = '0.3.0'
6
+ spec.authors = ['Will Farrington', 'Greg Fitzgerald']
7
+ spec.email = ['wfarr@digitalocean.com']
8
+ spec.description = 'A Test Kitchen Driver for Digital Ocean using apiv2'
9
+ spec.summary = spec.description
10
+ spec.homepage = 'https://github.com/wfarr/kitchen-digital_ocean'
11
+ spec.license = 'Apache 2.0'
12
+
13
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
14
+ spec.executables = []
15
+ spec.test_files = []
16
+ spec.require_paths = ['lib']
17
+
18
+ spec.add_dependency 'test-kitchen', '~> 1.0'
19
+ spec.add_dependency 'rest_client'
20
+
21
+ spec.add_development_dependency 'rubocop'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'cane'
24
+ spec.add_development_dependency 'countloc'
25
+ spec.add_development_dependency 'rspec'
26
+ end
27
+
28
+ # vim: ai et ts=2 sts=2 sw=2 ft=ruby
@@ -0,0 +1,184 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Greg Fitzgerald (<greg@gregf.org>)
4
+ #
5
+ # Copyright (C) 2013, Greg Fitzgerald
6
+ # Copyright (C) 2014, Will Farrington
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require 'rest_client'
21
+ require 'json'
22
+ require 'kitchen'
23
+ require 'etc'
24
+ require 'socket'
25
+
26
+ module Kitchen
27
+ module Driver
28
+ # Digital Ocean driver for Kitchen.
29
+ #
30
+ # @author Greg Fitzgerald <greg@gregf.org>
31
+ class DigitalOcean < Kitchen::Driver::SSHBase
32
+ IMAGES = {
33
+ "ubuntu-12.04" => "ubuntu-12-04-x64",
34
+ "ubuntu-14.04" => "ubuntu-14-04-x64",
35
+ }
36
+
37
+ default_config :username, 'root'
38
+ default_config :port, '22'
39
+
40
+ default_config :private_networking, true
41
+
42
+ default_config :region, 'nyc2'
43
+ default_config :size, '2gb'
44
+
45
+ default_config :image do |driver|
46
+ driver.default_image
47
+ end
48
+
49
+ default_config :server_name do |driver|
50
+ driver.default_name
51
+ end
52
+
53
+ default_config :digitalocean_api_token do
54
+ ENV['DIGITALOCEAN_API_TOKEN']
55
+ end
56
+
57
+ default_config :ssh_keys do
58
+ ENV['DIGITALOCEAN_SSH_KEYS']
59
+ end
60
+
61
+ required_config :digitalocean_api_token
62
+ required_config :ssh_keys
63
+
64
+ def create(state)
65
+ droplet = create_droplet
66
+ state[:server_id] = droplet['id']
67
+
68
+ info("Digital Ocean instance <#{state[:server_id]}> created.")
69
+
70
+ while true
71
+ sleep 10
72
+ droplet = get_droplet(state[:server_id])
73
+
74
+ break if droplet \
75
+ && droplet['networks'] \
76
+ && droplet['networks']['v4'] \
77
+ && droplet['networks']['v4'].any? { |n| n['type'] == 'public' }
78
+ end
79
+
80
+ state[:hostname] = droplet['networks']['v4'].detect { |n| n['type'] == 'public' }['ip_address']
81
+
82
+ wait_for_sshd(state[:hostname]) ; print "(ssh ready)\n"
83
+
84
+ debug("digitalocean:create #{state[:hostname]}")
85
+ rescue RestClient::Exception => e
86
+ raise ActionFailed, e.message
87
+ end
88
+
89
+ def destroy(state)
90
+ return if state[:server_id].nil?
91
+
92
+ if get_droplet(state[:server_id])
93
+ destroy_droplet state[:server_id]
94
+ end
95
+
96
+ info("Digital Ocean instance <#{state[:server_id]}> destroyed.")
97
+
98
+ state.delete(:server_id)
99
+ state.delete(:hostname)
100
+ rescue RestClient::Exception => e
101
+ raise ActionFailed, e.message
102
+ end
103
+
104
+ def default_image
105
+ IMAGES.fetch(instance.platform.name) { 'ubuntu-14-04-x64' }
106
+ end
107
+
108
+ def default_name
109
+ # Generate what should be a unique server name
110
+ rand_str = Array.new(8) { rand(36).to_s(36) }.join
111
+ "#{instance.name}-"\
112
+ "#{Etc.getlogin.gsub('_', '-')}-"\
113
+ "#{rand_str}-"\
114
+ "#{Socket.gethostname}"
115
+ end
116
+
117
+ private
118
+
119
+ def get_droplet(id)
120
+ api_request(:get, "droplets/#{id}")['droplet']
121
+ rescue RestClient::Exception => e
122
+ nil
123
+ end
124
+
125
+ def create_droplet
126
+ debug_droplet_config
127
+
128
+ droplet = api_request :post, 'droplets', {
129
+ name: config[:server_name],
130
+ region: config[:region],
131
+ size: config[:size],
132
+ image: config[:image],
133
+ ssh_keys: config[:ssh_keys].split(','),
134
+ }
135
+
136
+ droplet['droplet']
137
+ end
138
+
139
+ def destroy_droplet(id)
140
+ api_request :delete, "droplets/#{id}"
141
+ end
142
+
143
+ def debug_droplet_config
144
+ debug("digitalocean_api_token #{config[:digitalocean_api_token]}")
145
+ debug("digitalocean:name #{config[:server_name]}")
146
+ debug("digitalocean:image_id #{config[:image_id]}")
147
+ debug("digitalocean:flavor_id #{config[:flavor_id]}")
148
+ debug("digitalocean:region_id #{config[:region_id]}")
149
+ debug("digitalocean:ssh_key_ids #{config[:ssh_key_ids]}")
150
+ debug("digitalocean:private_networking #{config[:private_networking]}")
151
+ end
152
+
153
+ def api_request(method, url, content=nil)
154
+ url = "https://api.digitalocean.com/v2/#{url}" unless url =~ /^http/
155
+ headers = {'Authorization' => "Bearer #{config[:digitalocean_api_token]}"}
156
+ if %w(get head delete).include? method.to_s
157
+ res = RestClient.send(method.to_sym, url, headers)
158
+ json = JSON.parse(res) unless res.empty?
159
+
160
+ if json
161
+ if json['links'] && json['links']['pages'] && json['links']['pages']['next']
162
+ json.deep_merge!(api_request(method, json['links']['pages']['next']))
163
+ else
164
+ json
165
+ end
166
+ else
167
+ ""
168
+ end
169
+ elsif %w(post put).include? method.to_s
170
+ begin
171
+ JSON.parse(RestClient.send(method.to_sym, url, content, headers.merge(:content_type => 'application/json')))
172
+ rescue RestClient::Exception => rce
173
+ raise rce
174
+ end
175
+ else
176
+ raise "What kind of HTTP method actually is #{method}"
177
+ end
178
+ end
179
+
180
+ end
181
+ end
182
+ end
183
+
184
+ # vim: ai et ts=2 sts=2 sw=2 ft=ruby
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-digital_ocean
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Will Farrington
8
+ - Greg Fitzgerald
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-07-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: test-kitchen
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rest_client
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rubocop
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: cane
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: countloc
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ description: A Test Kitchen Driver for Digital Ocean using apiv2
113
+ email:
114
+ - wfarr@digitalocean.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - kitchen-digital_ocean.gemspec
124
+ - lib/kitchen/driver/digital_ocean.rb
125
+ homepage: https://github.com/wfarr/kitchen-digital_ocean
126
+ licenses:
127
+ - Apache 2.0
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.2.1
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: A Test Kitchen Driver for Digital Ocean using apiv2
149
+ test_files: []
150
+ has_rdoc: