Codebase list bundlewrap / 2bc06d0
New upstream release Jonathan Carter 3 years ago
16 changed file(s) with 130 addition(s) and 65 deletion(s). Raw diff Collapse all Expand all
0 # 4.2.1
1
2 2020-10-15
3
4 * fixed unintended Fault evaluation in metadata collision error message
5 * fixed sorting of Faults with other types
6 * fixed display of paged output on large macOS terminals
7 * fixed svc_openbsd being applied concurrently
8 * fixed services being reloaded and restarted at the same time
9 * fixed possible mangling of group metadata from items.py
10
11
012 # 4.2.0
113
214 2020-09-21
0 VERSION = (4, 2, 0)
0 VERSION = (4, 2, 1)
11 VERSION_STRING = ".".join([str(v) for v in VERSION])
2727 target_nodes = get_target_nodes(repo, args['targets'])
2828 pending_nodes = target_nodes.copy()
2929
30 io.progress_set_total(count_items(pending_nodes))
31
3230 try:
3331 repo.hooks.apply_start(
3432 repo,
4240 x=red("!!!"),
4341 ))
4442 exit(1)
43
44 io.progress_set_total(count_items(pending_nodes))
4545
4646 start_time = datetime.now()
4747 results = []
3030
3131 def apply(self, *args, **kwargs):
3232 return (Item.STATUS_OK, [])
33
34 def get_canned_actions(self):
35 return {}
3336
3437 def test(self):
3538 pass
205208
206209 def _inject_canned_actions(items):
207210 """
208 Looks for canned actions like "svc_upstart:mysql:reload" in item
209 triggers and adds them to the list of items.
210 """
211 added_actions = {}
212 for item in items.values():
213 for triggered_item_id in item.triggers:
214 if triggered_item_id in added_actions:
215 # action has already been triggered
216 continue
217
218 try:
219 type_name, item_name, action_name = triggered_item_id.split(":")
220 except ValueError:
221 # not a canned action
222 continue
223
224 target_item_id = "{}:{}".format(type_name, item_name)
225
226 try:
227 target_item = items[target_item_id]
228 except KeyError:
229 raise BundleError(_(
230 "{item} in bundle '{bundle}' triggers unknown item '{target_item}'"
231 ).format(
232 bundle=item.bundle.name,
233 item=item.id,
234 target_item=target_item_id,
235 ))
236
237 try:
238 action_attrs = target_item.get_canned_actions()[action_name]
239 except KeyError:
240 raise BundleError(_(
241 "{item} in bundle '{bundle}' triggers unknown "
242 "canned action '{action}' on {target_item}"
243 ).format(
244 action=action_name,
245 bundle=item.bundle.name,
246 item=item.id,
247 target_item=target_item_id,
248 ))
249
250 action_attrs.update({'triggered': True})
211 Looks for canned actions like "svc_upstart:mysql:reload" in items,
212 created actions for them and add those to the list of items.
213 """
214 for item in list(items.values()):
215 for canned_action_name, canned_action_attrs in item.get_canned_actions().items():
216 canned_action_id = f"{item.id}:{canned_action_name}"
217 canned_action_attrs.update({'triggered': True})
251218 action = Action(
252219 item.bundle,
253 triggered_item_id,
254 action_attrs,
220 canned_action_id,
221 canned_action_attrs,
255222 skip_name_validation=True,
256223 )
257224 action._prepare_deps(items)
258 added_actions[triggered_item_id] = action
259
260 items.update({item.id: item for item in added_actions.values()})
225 items[canned_action_id] = action
261226 return items
262227
263228
4444 }
4545 ITEM_TYPE_NAME = "svc_openbsd"
4646
47 @classmethod
48 def block_concurrent(cls, node_os, node_os_version):
49 # https://github.com/bundlewrap/bundlewrap/issues/554
50 return [cls.ITEM_TYPE_NAME]
51
4752 def __repr__(self):
4853 return "<SvcOpenBSD name:{} running:{} enabled:{}>".format(
4954 self.name,
6772 return {
6873 'restart': {
6974 'command': "/etc/rc.d/{} restart".format(self.name),
70 'needs': [self.id],
75 # make sure we don't restart and stopstart simultaneously
76 'needs': [f"{self.id}:stopstart"],
7177 },
7278 'stopstart': {
7379 'command': "/etc/rc.d/{0} stop && /etc/rc.d/{0} start".format(self.name),
8181 return {
8282 'reload': {
8383 'command': "systemctl reload -- {}".format(self.name),
84 'needs': [self.id],
84 # make sure we don't reload and restart simultaneously
85 'needs': [f"{self.id}:restart"],
8586 },
8687 'restart': {
8788 'command': "systemctl restart -- {}".format(self.name),
4646 return {
4747 'reload': {
4848 'command': "/etc/init.d/{} reload".format(self.name),
49 'needs': [self.id],
49 # make sure we don't reload and restart simultaneously
50 'needs': [f"{self.id}:restart"],
5051 },
5152 'restart': {
5253 'command': "/etc/init.d/{} restart".format(self.name),
4545 return {
4646 'reload': {
4747 'command': "reload {}".format(self.name),
48 'needs': [self.id],
48 # make sure we don't reload and restart simultaneously
49 'needs': [f"{self.id}:restart"],
4950 },
5051 'restart': {
5152 'command': "restart {}".format(self.name),
52 'needs': [self.id],
53 # make sure we don't restart and stopstart simultaneously
54 'needs': [f"{self.id}:stopstart"],
5355 },
5456 'stopstart': {
5557 'command': "stop {0} && start {0}".format(self.name),
143143 elif value != prev_value:
144144 raise ValueError(_(
145145 "{node}: {a} and {b} are clashing over this key path: {path} "
146 "(\"{val_a}\" vs. \"{val_b}\")"
146 "({val_a} vs. {val_b})"
147147 ).format(
148148 a=identifier,
149149 b=prev_identifier,
150150 node=node.name,
151151 path="/".join(path),
152 val_a=value,
153 val_b=prev_value,
152 val_a=repr(value),
153 val_b=repr(prev_value),
154154 ))
155155
156156
154154 return len(self.value)
155155
156156 def __lt__(self, other):
157 return self.value < other.value
157 if isinstance(other, Fault):
158 return self.value < other.value
159 else:
160 return self.value < other
161
162 def __gt__(self, other):
163 if isinstance(other, Fault):
164 return self.value > other.value
165 else:
166 return self.value > other
167
168 def __repr__(self):
169 return f"<Fault: {self.id_list}>"
158170
159171 def __str__(self):
160172 return str(self.value)
0 from copy import copy
01 from difflib import unified_diff
12 from hashlib import sha1
23 from json import dumps, JSONEncoder
248249 ):
249250 merged[key] = base[key].union(set(value))
250251 else:
251 merged[key] = value
252 # If we don't copy here, we end up with dicts from groups in
253 # node metadata. Not an issue per se, but a nasty pitfall
254 # when users do things like this in items.py:
255 #
256 # my_dict = node.metadata.get('foo', {})
257 # my_dict['bar'] = 'baz'
258 #
259 # The expectation here is to be able to mangle my_dict
260 # because it is only relevant for the current node. However,
261 # if 'foo' has only been defined in a group, we end up
262 # mangling that dict for every node in the group.
263 # Since we can't really force users to .copy() in this case
264 # (although they should!), we have to do it here.
265 merged[key] = copy(value)
252266
253267 return merged
254268
105105 View the given list of Unicode lines in a pager (e.g. `less`).
106106 """
107107 lines = list(lines)
108 if TTY:
108 line_width = max([len(ansi_clean(line)) for line in lines])
109 if TTY and line_width > get_terminal_size().columns:
109110 write_to_stream(STDOUT_WRITER, SHOW_CURSOR)
110111 env = environ.copy()
111 env["LESS"] = env.get("LESS", "") + " -FR"
112 env["LESS"] = env.get("LESS", "") + " -R"
112113 pager = Popen(
113114 [environ.get("PAGER", "/usr/bin/less")],
114115 env=env,
0 bundlewrap (4.2.1-1) unstable; urgency=medium
1
2 * New upstream release
3
4 -- Jonathan Carter <jcc@debian.org> Sun, 18 Oct 2020 17:04:59 +0200
5
06 bundlewrap (4.2.0-1) unstable; urgency=medium
17
28 * New upstream release
9 * Update VCS field to new unified Python team
10 * Update uploader field to new unified Python team
311
412 -- Jonathan Carter <jcc@debian.org> Tue, 22 Sep 2020 20:21:56 +0200
513
11 Section: python
22 Priority: optional
33 Maintainer: Jonathan Carter <jcc@debian.org>
4 Uploaders: Python Applications Packaging Team <python-apps-team@lists.alioth.debian.org>
4 Uploaders: Debian Python Team <team+python@tracker.debian.org>
55 Build-Depends: debhelper-compat (= 13),
66 dh-python,
77 python3,
22
33 setup(
44 name="bundlewrap",
5 version="4.2.0",
5 version="4.2.1",
66 description="Config management with Python",
77 long_description=(
88 "By allowing for easy and low-overhead config management, BundleWrap fills the gap between complex deployments using Chef or Puppet and old school system administration over SSH.\n"
00 from bundlewrap.utils import Fault
1
2 from pytest import raises
13
24
35 def test_basic_resolve():
369371 hash2 = hash(a)
370372
371373 assert hash1 == hash2
374
375
376 def test_sort():
377 def one():
378 return 1
379
380 def three():
381 return 3
382
383 f1 = Fault("1", one)
384 f3 = Fault("3", three)
385
386 assert sorted([2, f3, f1]) == [f1, 2, f3]
387
388
389 def test_sort_typeerror():
390 def one():
391 return 1
392
393 def three():
394 return 3
395
396 f1 = Fault("1", one)
397 f3 = Fault("3", three)
398
399 with raises(TypeError):
400 sorted(["2", f3, f1])
401
402
403 def test_sort_typeerror_from_fault():
404 def one():
405 return 1
406
407 def three():
408 return "3"
409
410 f1 = Fault("1", one)
411 f3 = Fault("3", three)
412
413 with raises(TypeError):
414 sorted([2, f3, f1])