Skip to content

Commit 1ca8d84

Browse files
author
Matthew Fisher
committed
add digital ocean provider
1 parent c9127c1 commit 1ca8d84

10 files changed

Lines changed: 429 additions & 2 deletions

File tree

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ gem 'berkshelf'
66

77
gem 'knife-ec2'
88
gem 'knife-rackspace'
9+
gem 'knife-digital_ocean'

Gemfile.lock

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ GEM
88
thread_safe (~> 0.1)
99
tzinfo (~> 0.3.37)
1010
addressable (2.3.5)
11+
akami (1.2.0)
12+
gyoku (>= 0.4.0)
13+
nokogiri (>= 1.4.0)
1114
atomic (1.1.14)
1215
berkshelf (1.2.1)
1316
activesupport
@@ -47,10 +50,24 @@ GEM
4750
activesupport (>= 3.2.0)
4851
hashie (>= 2.0.2)
4952
multi_json (>= 1.3.0)
53+
digital_ocean (1.2.0)
54+
faraday (~> 0.8.7)
55+
faraday_middleware (~> 0.9.0)
56+
json
57+
rash
58+
em-winrm (0.5.4)
59+
eventmachine (= 1.0.0.beta.3)
60+
mixlib-log (>= 1.3.0)
61+
uuidtools (~> 2.1.1)
62+
winrm (~> 1.1.0)
5063
erubis (2.7.0)
64+
eventmachine (1.0.0.beta.3)
5165
excon (0.25.3)
5266
faraday (0.8.8)
5367
multipart-post (~> 1.2.0)
68+
faraday_middleware (0.9.0)
69+
faraday (>= 0.7.4, < 0.9)
70+
ffi (1.9.1)
5471
fog (1.15.0)
5572
builder
5673
excon (~> 0.25.0)
@@ -63,14 +80,35 @@ GEM
6380
ruby-hmac
6481
foodcritic (0.2.0)
6582
formatador (0.2.4)
83+
gssapi (1.0.3)
84+
ffi (>= 1.0.1)
85+
gyoku (1.1.0)
86+
builder (>= 2.1.2)
6687
hashie (2.0.5)
6788
highline (1.6.19)
89+
httpclient (2.3.4.1)
90+
httpi (0.9.7)
91+
rack
6892
i18n (0.6.5)
6993
ipaddress (0.8.0)
7094
json (1.7.7)
95+
knife-digital_ocean (0.2.0)
96+
chef (>= 10.18)
97+
digital_ocean (~> 1.2.0)
98+
highline
7199
knife-ec2 (0.6.4)
72100
chef (>= 0.10.10)
73101
fog (~> 1.6)
102+
knife-rackspace (0.8.1)
103+
chef (>= 0.10.10)
104+
fog (~> 1.12)
105+
knife-windows
106+
knife-windows (0.5.12)
107+
em-winrm (= 0.5.4)
108+
little-plugger (1.1.3)
109+
logging (1.8.1)
110+
little-plugger (>= 1.1.3)
111+
multi_json (>= 1.3.6)
74112
mime-types (1.25)
75113
mini_portile (0.5.1)
76114
minitar (0.5.4)
@@ -95,6 +133,7 @@ GEM
95133
net-ssh-gateway (>= 0.99.0)
96134
nokogiri (1.6.0)
97135
mini_portile (~> 0.5.0)
136+
nori (1.1.5)
98137
ohai (6.18.0)
99138
ipaddress
100139
mixlib-cli
@@ -103,6 +142,9 @@ GEM
103142
mixlib-shellout
104143
systemu
105144
yajl-ruby
145+
rack (1.5.2)
146+
rash (0.4.0)
147+
hashie (~> 2.0.0)
106148
rest-client (1.6.7)
107149
mime-types (>= 1.16)
108150
retryable (1.3.3)
@@ -124,13 +166,33 @@ GEM
124166
retryable
125167
solve (>= 0.4.1)
126168
ruby-hmac (0.4.0)
169+
rubyntlm (0.1.1)
170+
savon (0.9.5)
171+
akami (~> 1.0)
172+
builder (>= 2.1.2)
173+
gyoku (>= 0.4.0)
174+
httpi (~> 0.9)
175+
nokogiri (>= 1.4.0)
176+
nori (~> 1.0)
177+
wasabi (~> 1.0)
127178
solve (0.8.1)
128179
systemu (2.5.2)
129180
thor (0.16.0)
130181
thread_safe (0.1.3)
131182
atomic
132183
timers (1.1.0)
133184
tzinfo (0.3.37)
185+
uuidtools (2.1.4)
186+
wasabi (1.0.0)
187+
nokogiri (>= 1.4.0)
188+
winrm (1.1.3)
189+
gssapi (~> 1.0.0)
190+
httpclient (~> 2.2, >= 2.2.0.2)
191+
logging (~> 1.6, >= 1.6.1)
192+
nokogiri (~> 1.5)
193+
rubyntlm (~> 0.1.1)
194+
savon (= 0.9.5)
195+
uuidtools (~> 2.1.2)
134196
yajl-ruby (1.1.0)
135197

136198
PLATFORMS
@@ -140,4 +202,6 @@ DEPENDENCIES
140202
berkshelf
141203
chef
142204
foodcritic
205+
knife-digital_ocean
143206
knife-ec2
207+
knife-rackspace

api/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class Provider(UuidAuditedModel):
109109
('mock', 'Mock Reference Provider'),
110110
('rackspace', 'Rackspace Open Cloud'),
111111
('static', 'Static Node'),
112+
('digitalocean', 'Digital Ocean'),
112113
)
113114

114115
owner = models.ForeignKey(settings.AUTH_USER_MODEL)

client/deis.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,14 @@ def providers_create(self, args):
16571657
'api_key': os.environ['RACKSPACE_API_KEY'],
16581658
'identity_type': os.environ.get('CLOUD_ID_TYPE', 'rackspace'),
16591659
}
1660+
elif type == 'digitalocean':
1661+
# read creds from envvars
1662+
for k in ('DIGITALOCEAN_CLIENT_ID', 'DIGITALOCEAN_API_KEY'):
1663+
if not k in os.environ:
1664+
msg = "Missing environment variable: {}".format(k)
1665+
raise EnvironmentError(msg)
1666+
creds = {'client_id': os.environ['DIGITALOCEAN_CLIENT_ID'],
1667+
'api_key': os.environ['DIGITALOCEAN_API_KEY']}
16601668
else:
16611669
creds = json.loads(args.get('<creds>'))
16621670
id = args.get('<id>') # @ReservedAssignment
@@ -1701,7 +1709,7 @@ def providers_discover(self, args):
17011709
else:
17021710
raise ResponseError(response)
17031711
else:
1704-
print('No credentials discovered, did you install the EC2 Command Line tools?')
1712+
print('No EC2 credentials discovered. Did you install the EC2 Command Line tools?')
17051713
if 'RACKSPACE_API_KEY' in os.environ and 'RACKSPACE_USERNAME' in os.environ:
17061714
print("Found Rackspace credentials: {}".format(os.environ['RACKSPACE_API_KEY']))
17071715
inp = raw_input('Import these credentials? (y/n) : ')
@@ -1721,7 +1729,27 @@ def providers_discover(self, args):
17211729
else:
17221730
raise ResponseError(response)
17231731
else:
1724-
print('No Rackspace credentials discovered')
1732+
print('No Rackspace credentials discovered.')
1733+
if 'DIGITALOCEAN_API_KEY' in os.environ and 'DIGITALOCEAN_CLIENT_ID' in os.environ:
1734+
print("Found Digitalocean credentials: {}".format(os.environ['DIGITALOCEAN_CLIENT_ID']))
1735+
inp = raw_input('Import these credentials? (y/n) : ')
1736+
if inp.lower().strip('\n') != 'y':
1737+
print('Aborting.')
1738+
else:
1739+
creds = {'client_id': os.environ['DIGITALOCEAN_CLIENT_ID'],
1740+
'api_key': os.environ['DIGITALOCEAN_API_KEY'],
1741+
}
1742+
body = {'creds': json.dumps(creds)}
1743+
sys.stdout.write('Uploading Digitalocean credentials... ')
1744+
sys.stdout.flush()
1745+
response = self._dispatch('patch', 'api/providers/digitalocean',
1746+
json.dumps(body))
1747+
if response.status_code == requests.codes.ok: # @UndefinedVariable
1748+
print('done')
1749+
else:
1750+
raise ResponseError(response)
1751+
else:
1752+
print('No Digitalocean credentials discovered.')
17251753

17261754
def providers_info(self, args):
17271755
"""

contrib/digitalocean/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
How to Provision a Deis Controller on Digital Ocean
2+
===================================================
3+
4+
Here are the steps to get started on Digital Ocean:
5+
6+
* install [knife-digital_ocean][kdo]
7+
8+
```
9+
bundle install
10+
```
11+
12+
* install python requirements
13+
14+
```
15+
pip install -r requirements.txt
16+
```
17+
18+
* add the following to ~/.chef/knife.rb
19+
20+
```
21+
knife[:digital_ocean_client_id] = "your digital ocean client ID"
22+
knife[:digital_ocean_api_key] = "your digital ocean API key"
23+
```
24+
25+
* Follow the steps provided in contrib/digitalocean/prepare-digitalocean-snapshot.sh
26+
* Run this command to start the provisioning process
27+
28+
```
29+
./contrib/digitalocean/provision-digitalocean-controller.sh
30+
```
31+
32+
This script will read from your knife config file, create a new SSH key for the controller, upload the SSH key to digital ocean, and provision a Deis Controller from the snapshot created.
33+
34+
[kdo]: https://github.com/rmoriz/knife-digital_ocean
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/bash -ex
2+
3+
#
4+
# Prepare a Deis-optimized snapshot from a vanilla Ubuntu 12.04.3 droplet.
5+
#
6+
# Instructions:
7+
#
8+
# 1. Launch a vanilla Ubuntu 12.04.3 droplet (64-bit)
9+
# 2. Run this script (as root!) to install the packages necessary for faster boot times
10+
# 3. Create a new snapshot of this droplet with the name 'deis-base'
11+
# 4. Create/update your Deis flavors to use your new snapshot
12+
#
13+
14+
THIS_DIR=$(cd $(dirname $0); pwd) # absolute path
15+
CONTRIB_DIR=$(dirname $THIS_DIR)
16+
17+
# upgrade to latest packages
18+
apt-get update
19+
apt-get upgrade -yq
20+
21+
# install HTTPS transport support
22+
apt-get install -qy apt-transport-https
23+
24+
# install docker's dependencies
25+
apt-get install python-software-properties -y
26+
27+
# Add the Docker repository key to your local keychain
28+
# using apt-key finger you can check the fingerprint matches 36A1 D786 9245 C895 0F96 6E92 D857 6A8B A88D 21E9
29+
curl https://get.docker.io/gpg | apt-key add -
30+
31+
# Add the Docker repository to your apt sources list.
32+
echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list
33+
34+
# upgrade to latest packages
35+
apt-get update
36+
apt-get -qy upgrade
37+
38+
# install required packages
39+
apt-get install lxc-docker curl git make python-setuptools python-pip -yq
40+
41+
# create buildstep docker image
42+
git clone -b deis https://github.com/opdemand/buildstep.git
43+
cd buildstep
44+
git checkout deis
45+
make
46+
cd ..
47+
rm -rf buildstep
48+
49+
# install chef 11.x deps
50+
apt-get install -yq ruby1.9.1 ruby1.9.1-dev make
51+
update-alternatives --set ruby /usr/bin/ruby1.9.1
52+
update-alternatives --set gem /usr/bin/gem1.9.1
53+
54+
# clean and remove old packages
55+
apt-get clean
56+
apt-get autoremove -yq
57+
58+
# reset cloud-init
59+
rm -rf /var/lib/cloud
60+
61+
# purge SSH authorized keys
62+
rm -f /root/.ssh/authorized_keys
63+
64+
# ssh host keys are automatically regenerated
65+
# on system boot by ubuntu cloud init
66+
67+
# purge /var/log
68+
find /var/log -type f | xargs rm
69+
70+
# flush writes to block storage
71+
sync

0 commit comments

Comments
 (0)