kitchen-digital_ocean 0.3.0

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: 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: