Skip to content

Commit 2b4d7f8

Browse files
committed
Fixed #177 -- added docstrings for cm modules.
1 parent 0bc763b commit 2b4d7f8

4 files changed

Lines changed: 208 additions & 14 deletions

File tree

cm/chef.py

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
"""
2+
Deis configuration management implementation for Opscode Chef.
3+
"""
14

25
from __future__ import unicode_literals
36

@@ -12,6 +15,7 @@
1215
from api.ssh import exec_ssh, connect_ssh
1316
from cm.chef_api import ChefAPI
1417

18+
1519
CHEF_CONFIG_PATH = '/etc/chef'
1620
CHEF_INSTALL_TYPE = 'gems'
1721
CHEF_RUBY_VERSION = '1.9.1'
@@ -56,11 +60,19 @@
5660
def _get_client():
5761
"""
5862
Return a new instance of a Chef API Client
63+
64+
:rtype: a :class:`~cm.chef_api.ChefAPI` object
5965
"""
6066
return ChefAPI(CHEF_SERVER_URL, CHEF_CLIENT_NAME, CHEF_CLIENT_KEY)
6167

6268

6369
def bootstrap_node(node):
70+
"""
71+
Bootstrap the Chef configuration management tools onto a node.
72+
73+
:param node: a dict containing the node's fully-qualified domain name and SSH info
74+
:raises: RuntimeError
75+
"""
6476
# block until we can connect over ssh
6577
ssh = connect_ssh(node['ssh_username'], node['fqdn'], node.get('ssh_port', 22),
6678
node['ssh_private_key'], timeout=120)
@@ -114,23 +126,42 @@ def _construct_run_list(node):
114126

115127
def purge_node(node):
116128
"""
117-
Purge the Node & Client records from Chef Server
129+
Purge a node and its client from Chef configuration management.
130+
131+
:param node: a dict containing the id of a node to purge
118132
"""
119133
client = _get_client()
120134
client.delete_node(node['id'])
121135
client.delete_client(node['id'])
122136

123137

124138
def converge_controller():
139+
"""
140+
Converge this controller node.
141+
142+
"Converge" means to change a node's configuration to match that defined by
143+
configuration management.
144+
145+
:returns: the output of the convergence command, in this case `sudo chef-client`
146+
"""
125147
try:
126148
return subprocess.check_output(['sudo', 'chef-client'])
127-
except subprocess.CalledProcessError as e:
128-
print(e)
129-
print(e.output)
130-
raise e
149+
except subprocess.CalledProcessError as err:
150+
print(err)
151+
print(err.output)
152+
raise err
131153

132154

133155
def converge_node(node):
156+
"""
157+
Converge a node.
158+
159+
"Converge" means to change a node's configuration to match that defined by
160+
configuration management.
161+
162+
:param node: a dict containing the node's fully-qualified domain name and SSH info
163+
:returns: a tuple of the convergence command's (output, return_code)
164+
"""
134165
ssh = connect_ssh(node['ssh_username'],
135166
node['fqdn'], 22,
136167
node['ssh_private_key'])
@@ -143,14 +174,29 @@ def converge_node(node):
143174

144175

145176
def run_node(node, command):
146-
ssh = connect_ssh(node['ssh_username'],
147-
node['fqdn'], node['ssh_port'],
148-
node['ssh_private_key'])
177+
"""
178+
Run a command on a node.
179+
180+
:param node: a dict containing the node's fully-qualified domain name and SSH info
181+
:param command: the command-line to execute on the node
182+
:returns: a tuple of the command's (output, return_code)
183+
"""
184+
ssh = connect_ssh(node['ssh_username'], node['fqdn'],
185+
node['ssh_port'], node['ssh_private_key'])
149186
output, rc = exec_ssh(ssh, command, pty=True)
150187
return output, rc
151188

152189

153190
def converge_formation(formation):
191+
"""
192+
Converge all nodes in a formation.
193+
194+
"Converge" means to change a node's configuration to match that defined by
195+
configuration management.
196+
197+
:param formation: a :class:`~api.models.Formation` to converge
198+
:returns: the combined output of the nodes' convergence commands
199+
"""
154200
nodes = formation.node_set.all()
155201
subtasks = []
156202
for n in nodes:
@@ -164,26 +210,73 @@ def converge_formation(formation):
164210

165211

166212
def publish_user(user, data):
213+
"""
214+
Publish a user to configuration management.
215+
216+
:param user: a dict containing the username
217+
:param data: data to store with the user
218+
:returns: a tuple of (body, status) from the underlying HTTP response
219+
:raises: RuntimeError
220+
"""
167221
_publish('deis-users', user['username'], data)
168222

169223

170224
def publish_app(app, data):
225+
"""
226+
Publish an app to configuration management.
227+
228+
:param app: a dict containing the id of the app
229+
:param data: data to store with the app
230+
:returns: a tuple of (body, status) from the underlying HTTP response
231+
:raises: RuntimeError
232+
"""
171233
_publish('deis-apps', app['id'], data)
172234

173235

174236
def purge_app(app):
237+
"""
238+
Purge an app from configuration management.
239+
240+
:param app: a dict containing the id of the app
241+
:returns: a tuple of (body, status) from the underlying HTTP response
242+
:raises: RuntimeError
243+
"""
175244
_purge('deis-apps', app['id'])
176245

177246

178247
def publish_formation(formation, data):
248+
"""
249+
Publish a formation to configuration management.
250+
251+
:param formation: a dict containing the id of the formation
252+
:param data: data to store with the formation
253+
:returns: a tuple of (body, status) from the underlying HTTP response
254+
:raises: RuntimeError
255+
"""
179256
_publish('deis-formations', formation['id'], data)
180257

181258

182259
def purge_formation(formation):
260+
"""
261+
Purge a formation from configuration management.
262+
263+
:param formation: a dict containing the id of the formation
264+
:returns: a tuple of (body, status) from the underlying HTTP response
265+
:raises: RuntimeError
266+
"""
183267
_purge('deis-formations', formation['id'])
184268

185269

186270
def _publish(data_bag, item_name, item_value):
271+
"""
272+
Publish a data bag item to the Chef server.
273+
274+
:param data_bag: the name of a Chef data bag
275+
:param item_name: the name of the item to publish
276+
:param item_value: the value of the item to publish
277+
:returns: a tuple of (body, status) from the underlying HTTP response
278+
:raises: RuntimeError
279+
"""
187280
client = _get_client()
188281
body, status = client.update_databag_item(data_bag, item_name, item_value)
189282
if status != 200:
@@ -194,6 +287,14 @@ def _publish(data_bag, item_name, item_value):
194287

195288

196289
def _purge(databag_name, item_name):
290+
"""
291+
Purge a data bag item from the Chef server.
292+
293+
:param databag_name: the name of a Chef data bag
294+
:param item_name: the name of the item to purge
295+
:returns: a tuple of (body, status) from the underlying HTTP response
296+
:raises: RuntimeError
297+
"""
197298
client = _get_client()
198299
body, status = client.delete_databag_item(databag_name, item_name)
199300
if status == 200 or status == 404:

cm/chef_api.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"""
2-
Much of this has been copied from pyChef.
3-
https://github.com/coderanger/pychef
2+
Classes and functions for interacting with OpsCode Chef.
43
5-
We want a simpler version for making API calls
4+
This file derives from pyChef: https://github.com/coderanger/pychef
65
"""
76

87
import base64
@@ -99,7 +98,19 @@ def create_authorization(blank_headers, verb, url, priv_key, user, body=''):
9998

10099

101100
class ChefAPI(object):
101+
"""The ChefAPI object is a wrapper for a single Chef server.
102102
103+
.. admonition:: The API stack
104+
105+
PyChef maintains a stack of :class:`ChefAPI` objects to be use with
106+
other methods if an API object isn't given explicitly. The first
107+
ChefAPI created will become the default, though you can set a specific
108+
default using :meth:`ChefAPI.set_default`. You can also use a ChefAPI
109+
as a context manager to create a scoped default::
110+
111+
with ChefAPI('http://localhost:4000', 'client.pem', 'admin'):
112+
n = Node('web1')
113+
"""
103114
headers = {
104115
'Accept': 'application/json',
105116
'X-Chef-Version': '11.0.4.x',

cm/chef_rsa.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""
2-
This file as copied from pyChef at https://github.com/coderanger/pychef
2+
SSL RSA key handling for Chef.
3+
4+
This file derives from pyChef: https://github.com/coderanger/pychef
35
"""
46

57
from ctypes import CDLL

cm/mock.py

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
"""
2+
Deis mock configuration management implementation for testing.
3+
"""
14

25
from __future__ import unicode_literals
36

@@ -8,53 +11,130 @@
811

912

1013
def bootstrap_node(node):
11-
return '', 0
14+
"""
15+
Bootstrap configuration management tools onto a node.
16+
17+
This is a no-op for the mock provider.
18+
19+
:param node: a dict containing the node's fully-qualified domain name and SSH info
20+
"""
21+
pass
1222

1323

1424
def converge_node(node):
25+
"""
26+
Converge a node.
27+
28+
"Converge" means to change a node's configuration to match that defined by
29+
configuration management.
30+
31+
This is a no-op for the mock provider.
32+
33+
:param node: a dict containing the node's fully-qualified domain name and SSH info
34+
:returns: a tuple of the convergence command's (output, return_code)
35+
"""
1536
return '', 0
1637

1738

1839
def run_node(node, command):
40+
"""
41+
Run a command on a node.
42+
43+
This is a no-op for the mock provider.
44+
45+
:param node: a dict containing the node's fully-qualified domain name and SSH info
46+
:param command: the command-line to execute on the node
47+
:returns: a tuple of the command's (output, return_code)
48+
"""
1949
return '', 0
2050

2151

2252
def purge_node(node):
23-
return
53+
"""
54+
Purge a node and its client from Chef configuration management.
55+
56+
This is a no-op for the mock provider.
57+
58+
:param node: a dict containing the id of a node to purge
59+
"""
60+
pass
2461

2562

2663
def publish_user(user, data):
64+
"""
65+
Publish a user to configuration management.
66+
67+
:param user: a dict containing the username
68+
:param data: data to store with the user
69+
"""
2770
path = os.path.join(settings.TEMPDIR, 'user-{username}'.format(**user))
2871
with open(path, 'w') as f:
2972
f.write(json.dumps(data))
3073

3174

3275
def purge_user(user):
76+
"""
77+
Purge a user from configuration management.
78+
79+
:param user: a dict containing the username
80+
"""
3381
path = os.path.join(settings.TEMPDIR, 'user-{username}'.format(**user))
3482
os.remove(path)
3583

3684

3785
def publish_app(app, data):
86+
"""
87+
Publish an app to configuration management.
88+
89+
:param app: a dict containing the id of the app
90+
:param data: data to store with the app
91+
"""
3892
path = os.path.join(settings.TEMPDIR, 'app-{id}'.format(**app))
3993
with open(path, 'w') as f:
4094
f.write(json.dumps(data))
4195

4296

4397
def purge_app(app):
98+
"""
99+
Purge an app from configuration management.
100+
101+
:param user: a dict containing the id of the app
102+
"""
44103
path = os.path.join(settings.TEMPDIR, 'app-{id}'.format(**app))
45104
os.remove(path)
46105

47106

48107
def publish_formation(formation, data):
108+
"""
109+
Publish a formation to configuration management.
110+
111+
:param formation: a dict containing the id of the formation
112+
:param data: data to store with the formation
113+
"""
49114
path = os.path.join(settings.TEMPDIR, 'formation-{id}'.format(**formation))
50115
with open(path, 'w') as f:
51116
f.write(json.dumps(data))
52117

53118

54119
def purge_formation(formation):
120+
"""
121+
Purge a formation from configuration management.
122+
123+
:param formation: a dict containing the id of the formation
124+
"""
55125
path = os.path.join(settings.TEMPDIR, 'formation-{id}'.format(**formation))
56126
os.remove(path)
57127

58128

59129
def converge_controller():
130+
"""
131+
Converge this controller node.
132+
133+
"Converge" means to change a node's configuration to match that defined by
134+
configuration management.
135+
136+
This is a no-op for the mock provider.
137+
138+
:returns: the output of the convergence command, in this case None
139+
"""
60140
return None

0 commit comments

Comments
 (0)