vagrant-chassis-digitalocean 1.0.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +6 -1
- data/README.md +95 -11
- data/lib/vagrant-chassis-digitalocean/actions/create.rb +16 -20
- data/lib/vagrant-chassis-digitalocean/actions/destroy.rb +1 -6
- data/lib/vagrant-chassis-digitalocean/actions/power_off.rb +6 -4
- data/lib/vagrant-chassis-digitalocean/actions/power_on.rb +4 -2
- data/lib/vagrant-chassis-digitalocean/actions/rebuild.rb +6 -5
- data/lib/vagrant-chassis-digitalocean/actions/reload.rb +4 -2
- data/lib/vagrant-chassis-digitalocean/actions/setup_key.rb +4 -4
- data/lib/vagrant-chassis-digitalocean/actions/setup_user.rb +1 -1
- data/lib/vagrant-chassis-digitalocean/actions/sync_folders.rb +12 -21
- data/lib/vagrant-chassis-digitalocean/config.rb +14 -12
- data/lib/vagrant-chassis-digitalocean/helpers/client.rb +42 -25
- data/lib/vagrant-chassis-digitalocean/helpers/result.rb +4 -4
- data/lib/vagrant-chassis-digitalocean/provider.rb +5 -3
- data/lib/vagrant-chassis-digitalocean/version.rb +1 -1
- data/locales/en.yml +2 -2
- data/test/Vagrantfile +4 -5
- data/test/test.sh +8 -8
- metadata +2 -2
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.
|
3
|
+
gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.6.3'
|
4
4
|
gem 'vagrant-omnibus'
|
5
5
|
gem 'rake'
|
6
|
+
|
7
|
+
group :plugins do
|
8
|
+
gem 'vagrant-digitalocean', :path => '.'
|
9
|
+
end
|
10
|
+
|
6
11
|
gemspec
|
data/README.md
CHANGED
@@ -4,19 +4,19 @@ Digital Ocean Vagrant Provider For Chassis
|
|
4
4
|
management of [Digital Ocean](https://www.digitalocean.com/) droplets
|
5
5
|
(instances) that setup WordPress using [Chassis](https://github.com/Chassis/Chassis/).
|
6
6
|
|
7
|
-
**NOTE:**
|
8
|
-
|
7
|
+
**NOTE:** The Chef provisioner is no longer supported by default (as of 0.2.0).
|
8
|
+
Please use the `vagrant-omnibus` plugin to install Chef on Vagrant-managed
|
9
|
+
machines. This plugin provides control over the specific version of Chef
|
10
|
+
to install.
|
9
11
|
|
10
12
|
Current features include:
|
11
13
|
- create and destroy droplets
|
12
14
|
- power on and off droplets
|
13
15
|
- rebuild a droplet
|
16
|
+
- provision a droplet with the shell or Chef provisioners
|
14
17
|
- setup a SSH public key for authentication
|
15
18
|
- create a new user account during droplet creation
|
16
19
|
|
17
|
-
The provider has been tested with Vagrant 1.1.5+ using Ubuntu 12.04 and
|
18
|
-
CentOS 6.3 guest operating systems.
|
19
|
-
|
20
20
|
Install
|
21
21
|
-------
|
22
22
|
Installation of the provider requires two steps:
|
@@ -37,7 +37,7 @@ Once the bundle is installed, add the following environment variable to your
|
|
37
37
|
`.bash_profile` script and `source` it:
|
38
38
|
|
39
39
|
```bash
|
40
|
-
export SSL_CERT_FILE=/usr/local/
|
40
|
+
export SSL_CERT_FILE=/usr/local/etc/openssl/cert.pem
|
41
41
|
```
|
42
42
|
|
43
43
|
Configure
|
@@ -46,13 +46,97 @@ Once the provider has been installed, you will need to configure your [Chassis](
|
|
46
46
|
to use it. You can use your we recommend adding your Digital Ocean details in your projects `config.yaml` or `config.local.yaml` file:
|
47
47
|
```bash
|
48
48
|
digitalocean:
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
token: 'YOUR TOKEN'
|
50
|
+
region: 'sgp1'
|
51
|
+
size: '512mbB'
|
52
|
+
image: 'Ubuntu 14.04 x64'
|
53
|
+
```
|
54
|
+
|
55
|
+
You must also add the following to your project `VagrantFile`
|
56
|
+
```
|
57
|
+
config.vm.provider :chassis_digitalocean do |provider, override|
|
58
|
+
override.ssh.private_key_path = '~/.ssh/id_rsa'
|
59
|
+
override.vm.box_url = 'https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digitalocean.box'
|
60
|
+
|
61
|
+
provider.token = CONF['digitalocean']['token']
|
62
|
+
provider.image = CONF['digitalocean']['image']
|
63
|
+
provider.region = CONF['digitalocean']['region']
|
64
|
+
provider.size = CONF['digitalocean']['size']
|
65
|
+
|
66
|
+
end
|
54
67
|
```
|
55
68
|
|
69
|
+
**Optionally,** you can remove exclude your .git folder from the rsync by including the following line after you've specified your
|
70
|
+
`config.vm.synced_folder`
|
71
|
+
|
72
|
+
```
|
73
|
+
rsync__exclude: ".git/"
|
74
|
+
```
|
75
|
+
|
76
|
+
Please note the following:
|
77
|
+
- You *must* specify the `override.ssh.private_key_path` to enable authentication
|
78
|
+
with the droplet. The provider will create a new Digital Ocean SSH key using
|
79
|
+
your public key which is assumed to be the `private_key_path` with a *.pub*
|
80
|
+
extension.
|
81
|
+
- You *must* specify your Digital Ocean Personal Access Token. This may be
|
82
|
+
found on the control panel within the *Apps & API* section.
|
83
|
+
|
84
|
+
**Supported Configuration Attributes**
|
85
|
+
|
86
|
+
The following attributes are available to further configure the provider:
|
87
|
+
- `provider.image` - A string representing the image to use when creating a
|
88
|
+
new droplet (e.g. `Debian 6.0 x64`). The available options may
|
89
|
+
be found on Digital Ocean's new droplet [form](https://cloud.digitalocean.com/droplets/new).
|
90
|
+
It defaults to `Ubuntu 14.04 x64`.
|
91
|
+
- `provider.ipv6` - A boolean flag indicating whether to enable IPv6
|
92
|
+
- `provider.region` - A string representing the region to create the new
|
93
|
+
droplet in. It defaults to `nyc2`.
|
94
|
+
- `provider.size` - A string representing the size to use when creating a
|
95
|
+
new droplet (e.g. `1gb`). It defaults to `512mb`.
|
96
|
+
- `provider.private_networking` - A boolean flag indicating whether to enable
|
97
|
+
a private network interface (if the region supports private networking). It
|
98
|
+
defaults to `false`.
|
99
|
+
- `provider.backups_enabled` - A boolean flag indicating whether to enable backups for
|
100
|
+
the droplet. It defaults to `false`.
|
101
|
+
- `provider.ssh_key_name` - A string representing the name to use when creating
|
102
|
+
a Digital Ocean SSH key for droplet authentication. It defaults to `Vagrant`.
|
103
|
+
- `provider.setup` - A boolean flag indicating whether to setup a new user
|
104
|
+
account and modify sudo to disable tty requirement. It defaults to `true`.
|
105
|
+
If you are using a tool like [packer](https://packer.io) to create
|
106
|
+
reusable snapshots with user accounts already provisioned, set to `false`.
|
107
|
+
|
108
|
+
The provider will create a new user account with the specified SSH key for
|
109
|
+
authorization if `config.ssh.username` is set and the `provider.setup`
|
110
|
+
attribute is `true`.
|
111
|
+
|
112
|
+
### provider.region slug
|
113
|
+
|
114
|
+
Each region has been specify with slug name.
|
115
|
+
Current Region-slug table is:
|
116
|
+
|
117
|
+
| slug | Region Name |
|
118
|
+
|:---- |:----------------|
|
119
|
+
| nyc1 | New York 1 |
|
120
|
+
| ams1 | Amsterdam 1 |
|
121
|
+
| sfo1 | San Francisco 1 |
|
122
|
+
| nyc2 | New York 2 |
|
123
|
+
| ams2 | Amsterdam 2 |
|
124
|
+
| sgp1 | Singapore 1 |
|
125
|
+
| lon1 | London 1 |
|
126
|
+
| nyc3 | New York 3 |
|
127
|
+
|
128
|
+
You can find latest region slug name using DigitalOcean API V2 call.
|
129
|
+
|
130
|
+
- example call.
|
131
|
+
|
132
|
+
```
|
133
|
+
curl -X GET "https://api.digitalocean.com/v2/regions" \
|
134
|
+
-H "Authorization: Bearer $DIGITAL_OCEAN_TOKEN" \
|
135
|
+
2>/dev/null | jq '.regions [] | .slug,.name'
|
136
|
+
```
|
137
|
+
|
138
|
+
More detail: [DigitalOcean API - Regions](https://developers.digitalocean.com/#regions)
|
139
|
+
|
56
140
|
Run
|
57
141
|
---
|
58
142
|
After creating your project's `Vagrantfile` with the required configuration
|
@@ -15,46 +15,42 @@ module VagrantPlugins
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def call(env)
|
18
|
-
ssh_key_id = env[:ssh_key_id]
|
19
|
-
|
20
|
-
size_id = @client
|
21
|
-
.request('/sizes')
|
22
|
-
.find_id(:sizes, :name => @machine.provider_config.size)
|
18
|
+
ssh_key_id = [env[:ssh_key_id]]
|
23
19
|
|
24
20
|
image_id = @client
|
25
|
-
.request('/images')
|
21
|
+
.request('/v2/images')
|
26
22
|
.find_id(:images, :name => @machine.provider_config.image)
|
27
23
|
|
28
|
-
region_id = @client
|
29
|
-
.request('/regions')
|
30
|
-
.find_id(:regions, :name => @machine.provider_config.region)
|
31
|
-
|
32
24
|
# submit new droplet request
|
33
|
-
result = @client.
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
25
|
+
result = @client.post('/v2/droplets', {
|
26
|
+
:size => @machine.provider_config.size,
|
27
|
+
:region => @machine.provider_config.region,
|
28
|
+
:image => image_id,
|
37
29
|
:name => @machine.config.vm.hostname || @machine.name,
|
38
|
-
:
|
30
|
+
:ssh_keys => ssh_key_id,
|
39
31
|
:private_networking => @machine.provider_config.private_networking,
|
40
|
-
:
|
32
|
+
:backups => @machine.provider_config.backups_enabled,
|
33
|
+
:ipv6 => @machine.provider_config.ipv6,
|
34
|
+
:user_data => @machine.provider_config.user_data
|
41
35
|
})
|
42
36
|
|
43
37
|
# wait for request to complete
|
44
38
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.creating')
|
45
|
-
@client.wait_for_event(env, result['
|
39
|
+
@client.wait_for_event(env, result['links']['actions'].first['id'])
|
46
40
|
|
47
41
|
# assign the machine id for reference in other commands
|
48
42
|
@machine.id = result['droplet']['id'].to_s
|
49
43
|
|
50
44
|
# refresh droplet state with provider and output ip address
|
51
45
|
droplet = Provider.droplet(@machine, :refresh => true)
|
46
|
+
public_network = droplet['networks']['v4'].find { |network| network['type'] == 'public' }
|
47
|
+
private_network = droplet['networks']['v4'].find { |network| network['type'] == 'private' }
|
52
48
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.droplet_ip', {
|
53
|
-
:ip =>
|
49
|
+
:ip => public_network['ip_address']
|
54
50
|
})
|
55
|
-
if
|
51
|
+
if private_network
|
56
52
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.droplet_private_ip', {
|
57
|
-
:ip =>
|
53
|
+
:ip => private_network['ip_address']
|
58
54
|
})
|
59
55
|
end
|
60
56
|
|
@@ -15,15 +15,10 @@ module VagrantPlugins
|
|
15
15
|
|
16
16
|
def call(env)
|
17
17
|
# submit destroy droplet request
|
18
|
-
|
18
|
+
@client.delete("/v2/droplets/#{@machine.id}")
|
19
19
|
|
20
20
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.destroying')
|
21
21
|
|
22
|
-
# wait for the destroy progress to start
|
23
|
-
@client.wait_for_event(env, result['event_id']) do |response|
|
24
|
-
break if response['event']['percentage'] != nil
|
25
|
-
end
|
26
|
-
|
27
22
|
# set the machine id to nil to cleanup local vagrant state
|
28
23
|
@machine.id = nil
|
29
24
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'vagrant-
|
2
|
-
|
1
|
+
require 'vagrant-digitalocean/helpers/client'
|
2
|
+
#TODO: --force
|
3
3
|
module VagrantPlugins
|
4
4
|
module DigitalOcean
|
5
5
|
module Actions
|
@@ -15,11 +15,13 @@ module VagrantPlugins
|
|
15
15
|
|
16
16
|
def call(env)
|
17
17
|
# submit power off droplet request
|
18
|
-
result = @client.
|
18
|
+
result = @client.post("/v2/droplets/#{@machine.id}/actions", {
|
19
|
+
:type => 'power_off'
|
20
|
+
})
|
19
21
|
|
20
22
|
# wait for request to complete
|
21
23
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.powering_off')
|
22
|
-
@client.wait_for_event(env, result['
|
24
|
+
@client.wait_for_event(env, result['action']['id'])
|
23
25
|
|
24
26
|
# refresh droplet state with provider
|
25
27
|
Provider.droplet(@machine, :refresh => true)
|
@@ -15,11 +15,13 @@ module VagrantPlugins
|
|
15
15
|
|
16
16
|
def call(env)
|
17
17
|
# submit power on droplet request
|
18
|
-
result = @client.
|
18
|
+
result = @client.post("/v2/droplets/#{@machine.id}/actions", {
|
19
|
+
:type => 'power_on'
|
20
|
+
})
|
19
21
|
|
20
22
|
# wait for request to complete
|
21
23
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.powering_on')
|
22
|
-
@client.wait_for_event(env, result['
|
24
|
+
@client.wait_for_event(env, result['action']['id'])
|
23
25
|
|
24
26
|
# refresh droplet state with provider
|
25
27
|
Provider.droplet(@machine, :refresh => true)
|
@@ -5,7 +5,7 @@ module VagrantPlugins
|
|
5
5
|
module Actions
|
6
6
|
class Rebuild
|
7
7
|
include Helpers::Client
|
8
|
-
|
8
|
+
include Vagrant::Util::Retryable
|
9
9
|
|
10
10
|
def initialize(app, env)
|
11
11
|
@app = app
|
@@ -17,17 +17,18 @@ module VagrantPlugins
|
|
17
17
|
def call(env)
|
18
18
|
# look up image id
|
19
19
|
image_id = @client
|
20
|
-
.request('/images')
|
20
|
+
.request('/v2/images')
|
21
21
|
.find_id(:images, :name => @machine.provider_config.image)
|
22
22
|
|
23
23
|
# submit rebuild request
|
24
|
-
result = @client.
|
25
|
-
:
|
24
|
+
result = @client.post("/v2/droplets/#{@machine.id}/actions", {
|
25
|
+
:type => 'rebuild',
|
26
|
+
:image => image_id
|
26
27
|
})
|
27
28
|
|
28
29
|
# wait for request to complete
|
29
30
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.rebuilding')
|
30
|
-
@client.wait_for_event(env, result['
|
31
|
+
@client.wait_for_event(env, result['action']['id'])
|
31
32
|
|
32
33
|
# refresh droplet state with provider
|
33
34
|
Provider.droplet(@machine, :refresh => true)
|
@@ -15,11 +15,13 @@ module VagrantPlugins
|
|
15
15
|
|
16
16
|
def call(env)
|
17
17
|
# submit reboot droplet request
|
18
|
-
result = @client.
|
18
|
+
result = @client.post("/v2/droplets/#{@machine.id}/actions", {
|
19
|
+
:type => 'reboot'
|
20
|
+
})
|
19
21
|
|
20
22
|
# wait for request to complete
|
21
23
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.reloading')
|
22
|
-
@client.wait_for_event(env, result['
|
24
|
+
@client.wait_for_event(env, result['action']['id'])
|
23
25
|
|
24
26
|
@app.call(env)
|
25
27
|
end
|
@@ -20,7 +20,7 @@ module VagrantPlugins
|
|
20
20
|
begin
|
21
21
|
# assigns existing ssh key id to env for use by other commands
|
22
22
|
env[:ssh_key_id] = @client
|
23
|
-
.request('/
|
23
|
+
.request('/v2/account/keys')
|
24
24
|
.find_id(:ssh_keys, :name => ssh_key_name)
|
25
25
|
|
26
26
|
env[:ui].info I18n.t('vagrant_digital_ocean.info.using_key', {
|
@@ -38,7 +38,7 @@ module VagrantPlugins
|
|
38
38
|
def create_ssh_key(name, env)
|
39
39
|
# assumes public key exists on the same path as private key with .pub ext
|
40
40
|
path = @machine.config.ssh.private_key_path
|
41
|
-
|
41
|
+
path = path[0] if path.is_a?(Array)
|
42
42
|
path = File.expand_path(path, @machine.env.root_path)
|
43
43
|
pub_key = DigitalOcean.public_key(path)
|
44
44
|
|
@@ -46,9 +46,9 @@ module VagrantPlugins
|
|
46
46
|
:name => name
|
47
47
|
})
|
48
48
|
|
49
|
-
result = @client.
|
49
|
+
result = @client.post('/v2/account/keys', {
|
50
50
|
:name => name,
|
51
|
-
:
|
51
|
+
:public_key => pub_key
|
52
52
|
})
|
53
53
|
result['ssh_key']['id']
|
54
54
|
end
|
@@ -44,7 +44,7 @@ module VagrantPlugins
|
|
44
44
|
|
45
45
|
# add the specified key to the authorized keys file
|
46
46
|
path = @machine.config.ssh.private_key_path
|
47
|
-
|
47
|
+
path = path[0] if path.is_a?(Array)
|
48
48
|
path = File.expand_path(path, @machine.env.root_path)
|
49
49
|
pub_key = DigitalOcean.public_key(path)
|
50
50
|
@machine.communicate.execute(<<-BASH)
|
@@ -17,9 +17,14 @@ module VagrantPlugins
|
|
17
17
|
@machine.config.vm.synced_folders.each do |id, data|
|
18
18
|
next if data[:disabled]
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
if @machine.guest.capability?(:rsync_installed)
|
21
|
+
installed = @machine.guest.capability(:rsync_installed)
|
22
|
+
if !installed
|
23
|
+
can_install = @machine.guest.capability?(:rsync_install)
|
24
|
+
raise Vagrant::Errors::RSyncNotInstalledInGuest if !can_install
|
25
|
+
@machine.ui.info I18n.t("vagrant.rsync_installing")
|
26
|
+
@machine.guest.capability(:rsync_install)
|
27
|
+
end
|
23
28
|
end
|
24
29
|
|
25
30
|
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
@@ -47,21 +52,12 @@ module VagrantPlugins
|
|
47
52
|
key = ssh_info[:private_key_path]
|
48
53
|
key = key[0] if key.is_a?(Array)
|
49
54
|
|
50
|
-
|
51
|
-
# build exclude rules
|
52
|
-
excludes = ['.vagrant/']
|
53
|
-
excludes += Array(data[:rsync__exclude]).map(&:to_s) if data[:rsync__exclude]
|
54
|
-
excludes.uniq!
|
55
|
-
|
56
|
-
|
57
|
-
|
58
55
|
# rsync over to the guest path using the ssh info
|
59
56
|
command = [
|
60
|
-
"rsync", "--verbose", "--
|
57
|
+
"rsync", "--verbose", "--archive", "-z", "--delete",
|
61
58
|
"-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no -i '#{key}'",
|
62
59
|
hostpath,
|
63
|
-
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"
|
64
|
-
{ :notify => [:stdout, :stderr] } ].flatten
|
60
|
+
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
65
61
|
|
66
62
|
# we need to fix permissions when using rsync.exe on windows, see
|
67
63
|
# http://stackoverflow.com/questions/5798807/rsync-permission-denied-created-directories-have-no-permissions
|
@@ -69,12 +65,7 @@ module VagrantPlugins
|
|
69
65
|
command.insert(1, "--chmod", "ugo=rwX")
|
70
66
|
end
|
71
67
|
|
72
|
-
r = Vagrant::Util::Subprocess.execute(*command)
|
73
|
-
if type == :stdout || type == :stderr
|
74
|
-
@machine.env.ui.info(data, :new_line => false, :prefix => false)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
68
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
78
69
|
if r.exit_code != 0
|
79
70
|
raise Errors::RsyncError,
|
80
71
|
:guestpath => guestpath,
|
@@ -88,4 +79,4 @@ module VagrantPlugins
|
|
88
79
|
end
|
89
80
|
end
|
90
81
|
end
|
91
|
-
end
|
82
|
+
end
|
@@ -1,52 +1,54 @@
|
|
1
1
|
module VagrantPlugins
|
2
2
|
module DigitalOcean
|
3
3
|
class Config < Vagrant.plugin('2', :config)
|
4
|
-
attr_accessor :
|
5
|
-
attr_accessor :api_key
|
4
|
+
attr_accessor :token
|
6
5
|
attr_accessor :image
|
7
6
|
attr_accessor :region
|
8
7
|
attr_accessor :size
|
9
8
|
attr_accessor :private_networking
|
9
|
+
attr_accessor :ipv6
|
10
10
|
attr_accessor :backups_enabled
|
11
11
|
attr_accessor :ca_path
|
12
12
|
attr_accessor :ssh_key_name
|
13
13
|
attr_accessor :setup
|
14
|
+
attr_accessor :user_data
|
14
15
|
|
15
16
|
alias_method :setup?, :setup
|
16
17
|
|
17
18
|
def initialize
|
18
|
-
@
|
19
|
-
@api_key = UNSET_VALUE
|
19
|
+
@token = UNSET_VALUE
|
20
20
|
@image = UNSET_VALUE
|
21
21
|
@region = UNSET_VALUE
|
22
22
|
@size = UNSET_VALUE
|
23
23
|
@private_networking = UNSET_VALUE
|
24
|
+
@ipv6 = UNSET_VALUE
|
24
25
|
@backups_enable = UNSET_VALUE
|
25
26
|
@ca_path = UNSET_VALUE
|
26
27
|
@ssh_key_name = UNSET_VALUE
|
27
28
|
@setup = UNSET_VALUE
|
29
|
+
@user_data = UNSET_VALUE
|
28
30
|
end
|
29
31
|
|
30
32
|
def finalize!
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
34
|
-
@
|
35
|
-
@size = '512MB' if @size == UNSET_VALUE
|
33
|
+
@token = ENV['DO_TOKEN'] if @token == UNSET_VALUE
|
34
|
+
@image = 'Ubuntu 14.04 x64' if @image == UNSET_VALUE
|
35
|
+
@region = 'nyc2' if @region == UNSET_VALUE
|
36
|
+
@size = '512mb' if @size == UNSET_VALUE
|
36
37
|
@private_networking = false if @private_networking == UNSET_VALUE
|
38
|
+
@ipv6 = false if @ipv6 == UNSET_VALUE
|
37
39
|
@backups_enabled = false if @backups_enabled == UNSET_VALUE
|
38
40
|
@ca_path = nil if @ca_path == UNSET_VALUE
|
39
41
|
@ssh_key_name = 'Vagrant' if @ssh_key_name == UNSET_VALUE
|
40
42
|
@setup = true if @setup == UNSET_VALUE
|
43
|
+
@user_data = nil if @user_data == UNSET_VALUE
|
41
44
|
end
|
42
45
|
|
43
46
|
def validate(machine)
|
44
47
|
errors = []
|
45
|
-
errors << I18n.t('vagrant_digital_ocean.config.
|
46
|
-
errors << I18n.t('vagrant_digital_ocean.config.api_key') if !@api_key
|
48
|
+
errors << I18n.t('vagrant_digital_ocean.config.token') if !@token
|
47
49
|
|
48
50
|
key = machine.config.ssh.private_key_path
|
49
|
-
|
51
|
+
key = key[0] if key.is_a?(Array)
|
50
52
|
if !key
|
51
53
|
errors << I18n.t('vagrant_digital_ocean.config.private_key')
|
52
54
|
elsif !File.file?(File.expand_path("#{key}.pub", machine.env.root_path))
|
@@ -15,7 +15,7 @@ module VagrantPlugins
|
|
15
15
|
include Vagrant::Util::Retryable
|
16
16
|
|
17
17
|
def initialize(machine)
|
18
|
-
|
18
|
+
@logger = Log4r::Logger.new('vagrant::digitalocean::apiclient')
|
19
19
|
@config = machine.provider_config
|
20
20
|
@client = Faraday.new({
|
21
21
|
:url => 'https://api.digitalocean.com/',
|
@@ -25,13 +25,23 @@ module VagrantPlugins
|
|
25
25
|
})
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def delete(path, params = {}, method = :delete)
|
29
|
+
@client.request :url_encoded
|
30
|
+
request(path, params, :delete)
|
31
|
+
end
|
32
|
+
|
33
|
+
def post(path, params = {}, method = :post)
|
34
|
+
@client.headers['Content-Type'] = 'application/json'
|
35
|
+
request(path, params, :post)
|
36
|
+
end
|
37
|
+
|
38
|
+
def request(path, params = {}, method = :get)
|
29
39
|
begin
|
30
|
-
|
31
|
-
result = @client.
|
32
|
-
|
33
|
-
|
34
|
-
|
40
|
+
@logger.info "Request: #{path}"
|
41
|
+
result = @client.send(method) do |req|
|
42
|
+
req.url path, params
|
43
|
+
req.headers['Authorization'] = "Bearer #{@config.token}"
|
44
|
+
end
|
35
45
|
rescue Faraday::Error::ConnectionFailed => e
|
36
46
|
# TODO this is suspect but because farady wraps the exception
|
37
47
|
# in something generic there doesn't appear to be another
|
@@ -43,26 +53,33 @@ module VagrantPlugins
|
|
43
53
|
raise e
|
44
54
|
end
|
45
55
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
unless method == :delete
|
57
|
+
begin
|
58
|
+
body = JSON.parse(result.body)
|
59
|
+
@logger.info "Response: #{body}"
|
60
|
+
next_page = body["links"]["pages"]["next"] rescue nil
|
61
|
+
unless next_page.nil?
|
62
|
+
uri = URI.parse(next_page)
|
63
|
+
new_path = path.split("?")[0]
|
64
|
+
next_result = self.request("#{new_path}?#{uri.query}")
|
65
|
+
req_target = new_path.split("/")[-1]
|
66
|
+
body["#{req_target}"].concat(next_result["#{req_target}"])
|
67
|
+
end
|
68
|
+
rescue JSON::ParserError => e
|
69
|
+
raise(Errors::JSONError, {
|
70
|
+
:message => e.message,
|
71
|
+
:path => path,
|
72
|
+
:params => params,
|
73
|
+
:response => result.body
|
74
|
+
})
|
75
|
+
end
|
59
76
|
end
|
60
77
|
|
61
|
-
|
78
|
+
unless /^2\d\d$/ =~ result.status.to_s
|
62
79
|
raise(Errors::APIStatusError, {
|
63
80
|
:path => path,
|
64
81
|
:params => params,
|
65
|
-
:status =>
|
82
|
+
:status => result.status,
|
66
83
|
:response => body.inspect
|
67
84
|
})
|
68
85
|
end
|
@@ -75,11 +92,11 @@ module VagrantPlugins
|
|
75
92
|
# stop waiting if interrupted
|
76
93
|
next if env[:interrupted]
|
77
94
|
|
78
|
-
# check
|
79
|
-
result = self.request("/
|
95
|
+
# check action status
|
96
|
+
result = self.request("/v2/actions/#{id}")
|
80
97
|
|
81
98
|
yield result if block_given?
|
82
|
-
raise 'not ready' if result['
|
99
|
+
raise 'not ready' if result['action']['status'] != 'completed'
|
83
100
|
end
|
84
101
|
end
|
85
102
|
end
|
@@ -10,14 +10,14 @@ module VagrantPlugins
|
|
10
10
|
@result[key.to_s]
|
11
11
|
end
|
12
12
|
|
13
|
-
def find_id(sub_obj, search)
|
13
|
+
def find_id(sub_obj, search) #:ssh_keys, {:name => 'ijin (vagrant)'}
|
14
14
|
find(sub_obj, search)["id"]
|
15
15
|
end
|
16
16
|
|
17
17
|
def find(sub_obj, search)
|
18
|
-
key = search.keys.first
|
19
|
-
value = search[key].to_s
|
20
|
-
key = key.to_s
|
18
|
+
key = search.keys.first #:slug
|
19
|
+
value = search[key].to_s #sfo1
|
20
|
+
key = key.to_s #slug
|
21
21
|
|
22
22
|
result = @result[sub_obj.to_s].inject(nil) do |result, obj|
|
23
23
|
obj[key] == value ? obj : result
|
@@ -12,14 +12,14 @@ module VagrantPlugins
|
|
12
12
|
|
13
13
|
# load status of droplets if it has not been done before
|
14
14
|
if !@droplets
|
15
|
-
result = client.request('/droplets')
|
15
|
+
result = client.request('/v2/droplets')
|
16
16
|
@droplets = result['droplets']
|
17
17
|
end
|
18
18
|
|
19
19
|
if opts[:refresh] && machine.id
|
20
20
|
# refresh the droplet status for the given machine
|
21
21
|
@droplets.delete_if { |d| d['id'].to_s == machine.id }
|
22
|
-
result = client.request("/droplets/#{machine.id}")
|
22
|
+
result = client.request("/v2/droplets/#{machine.id}")
|
23
23
|
@droplets << droplet = result['droplet']
|
24
24
|
else
|
25
25
|
# lookup droplet status for the given machine
|
@@ -79,8 +79,10 @@ module VagrantPlugins
|
|
79
79
|
|
80
80
|
return nil if droplet['status'].to_sym != :active
|
81
81
|
|
82
|
+
public_network = droplet['networks']['v4'].find { |network| network['type'] == 'public' }
|
83
|
+
|
82
84
|
return {
|
83
|
-
:host =>
|
85
|
+
:host => public_network['ip_address'],
|
84
86
|
:port => '22',
|
85
87
|
:username => 'root',
|
86
88
|
:private_key_path => nil
|
data/locales/en.yml
CHANGED
@@ -19,9 +19,9 @@ en:
|
|
19
19
|
creating_key: "Creating new SSH key: %{name}..."
|
20
20
|
trying_rsync_install: "Rsync not found, attempting to install with yum..."
|
21
21
|
rsyncing: "Rsyncing folder: %{hostpath} => %{guestpath}..."
|
22
|
+
rsync_missing: "The rsync executable was not found in the current path."
|
22
23
|
config:
|
23
|
-
|
24
|
-
api_key: "API key is required"
|
24
|
+
token: "Token is required"
|
25
25
|
private_key: "SSH private key path is required"
|
26
26
|
public_key: "SSH public key not found: %{key}"
|
27
27
|
errors:
|
data/test/Vagrantfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Vagrant.require_plugin('vagrant-
|
1
|
+
Vagrant.require_plugin('vagrant-digitalocean')
|
2
2
|
Vagrant.require_plugin('vagrant-omnibus')
|
3
3
|
|
4
4
|
Vagrant.configure('2') do |config|
|
@@ -12,8 +12,7 @@ Vagrant.configure('2') do |config|
|
|
12
12
|
config.vm.provider :chassis_digitalocean do |provider, override|
|
13
13
|
override.vm.box = 'chassis_digitalocean'
|
14
14
|
override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
|
15
|
-
provider.
|
16
|
-
provider.api_key = ENV['DO_API_KEY']
|
15
|
+
provider.token = ENV['DO_TOKEN']
|
17
16
|
provider.ssh_key_name = 'Test Key'
|
18
17
|
end
|
19
18
|
|
@@ -25,8 +24,8 @@ Vagrant.configure('2') do |config|
|
|
25
24
|
end
|
26
25
|
|
27
26
|
config.vm.define :ubuntu do |ubuntu|
|
28
|
-
ubuntu.vm.provider :
|
29
|
-
provider.image = 'Ubuntu
|
27
|
+
ubuntu.vm.provider :digital_ocean do |provider|
|
28
|
+
provider.image = 'Ubuntu 14.04 x64'
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
data/test/test.sh
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
# if ! vagrant box list | grep
|
2
|
-
# vagrant box add
|
1
|
+
# if ! bundle exec vagrant box list | grep digital_ocean 1>/dev/null; then
|
2
|
+
# bundle exec vagrant box add digital_ocean box/digital_ocean.box
|
3
3
|
# fi
|
4
4
|
|
5
5
|
cd test
|
6
6
|
|
7
|
-
vagrant up --provider=
|
8
|
-
vagrant up
|
9
|
-
vagrant provision
|
10
|
-
vagrant rebuild
|
11
|
-
vagrant halt
|
12
|
-
vagrant destroy
|
7
|
+
bundle exec vagrant up --provider=digital_ocean
|
8
|
+
bundle exec vagrant up
|
9
|
+
bundle exec vagrant provision
|
10
|
+
bundle exec vagrant rebuild
|
11
|
+
bundle exec vagrant halt
|
12
|
+
bundle exec vagrant destroy
|
13
13
|
|
14
14
|
cd ..
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-chassis-digitalocean
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|