Codebase list bundlewrap / 66feda5
Imported Upstream version 2.18.0 SVN-Git Migration 6 years ago
11 changed file(s) with 169 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
0 # 2.18.0
1
2 2017-05-22
3
4 * added encoding and collation to postgres_db items
5 * added the 'comment' attribute for all items
6 * fixed group deletion
7 * fixed accidental modification of lists in statedicts
8
9
010 # 2.17.1
111
212 2017-04-19
00 # -*- coding: utf-8 -*-
11 from __future__ import unicode_literals
22
3 VERSION = (2, 17, 1)
3 VERSION = (2, 18, 0)
44 VERSION_STRING = ".".join([str(v) for v in VERSION])
55 from __future__ import unicode_literals
66 from copy import copy
77 from datetime import datetime
8 from inspect import cleandoc
89 from os.path import join
10 from textwrap import TextWrapper
911
1012 from bundlewrap.exceptions import BundleError, ItemDependencyError, FaultUnavailable
1113 from bundlewrap.utils import cached_property
1214 from bundlewrap.utils.statedict import diff_keys, diff_value, hash_statedict, validate_statedict
1315 from bundlewrap.utils.text import force_text, mark_for_translation as _
14 from bundlewrap.utils.text import blue, bold, wrap_question
16 from bundlewrap.utils.text import blue, bold, italic, wrap_question
1517 from bundlewrap.utils.ui import io
1618
1719 BUILTIN_ITEM_ATTRIBUTES = {
1820 'cascade_skip': None,
21 'comment': None,
1922 'needed_by': [],
2023 'needs': [],
2124 'preceded_by': [],
2831 'unless': "",
2932 'when_creating': {},
3033 }
34
35 wrapper = TextWrapper(
36 break_long_words=False,
37 break_on_hyphens=False,
38 expand_tabs=False,
39 replace_whitespace=False,
40 )
41
42
43 def format_comment(comment):
44 result = "\n\n"
45 for line in wrapper.wrap(cleandoc(comment)):
46 for inlineline in line.split("\n"):
47 result += "# {}\n".format(italic(inlineline))
48 return result
3149
3250
3351 class ItemStatus(object):
454472 keys_to_fix,
455473 )
456474 question_text = self.ask(cdict, sdict, keys_to_fix)
475 if self.comment:
476 question_text += format_comment(self.comment)
457477 question = wrap_question(
458478 self.id,
459479 question_text,
77 from bundlewrap.utils.text import force_text, mark_for_translation as _
88
99
10 def create_db(node, name, owner):
11 return node.run("sudo -u postgres createdb -wO {owner} {name}".format(
12 name=name,
13 owner=owner,
14 ))
10 def create_db(node, name, owner, when_creating):
11 template = None
12 cmd = "sudo -u postgres createdb -wO {} ".format(owner)
13
14 if when_creating.get('collation') is not None:
15 cmd += "--lc-collate={} ".format(when_creating['collation'])
16 template = "template0"
17
18 if when_creating.get('ctype') is not None:
19 cmd += "--lc-ctype={} ".format(when_creating['ctype'])
20 template = "template0"
21
22 if when_creating.get('encoding') is not None:
23 cmd += "--encoding={} ".format(when_creating['encoding'])
24 template = "template0"
25
26 if template is not None:
27 cmd += "--template={} ".format(template)
28
29 cmd += name
30
31 return node.run(cmd)
1532
1633
1734 def drop_db(node, name):
4966 'owner': "postgres",
5067 }
5168 ITEM_TYPE_NAME = "postgres_db"
69 WHEN_CREATING_ATTRIBUTES = {
70 'collation': None,
71 'ctype': None,
72 'encoding': None,
73 }
5274
5375 def __repr__(self):
5476 return "<PostgresDB name:{}>".format(self.name)
6385 if status.must_be_deleted:
6486 drop_db(self.node, self.name)
6587 elif status.must_be_created:
66 create_db(self.node, self.name, self.attributes['owner'])
88 create_db(self.node, self.name, self.attributes['owner'], self.when_creating)
6789 elif 'owner' in status.keys_to_fix:
6890 set_owner(self.node, self.name, self.attributes['owner'])
6991 else:
144144
145145 def get_auto_deps(self, items):
146146 deps = []
147 groups = self.attributes['groups'] or []
147148 for item in items:
148149 if item.ITEM_TYPE_NAME == "group":
149 if item.attributes['delete']:
150 if not (item.name in groups or (
151 self.attributes['gid'] in [item.attributes['gid'], item.name] and
152 self.attributes['gid'] is not None
153 )):
154 # we don't need to depend on this group
155 continue
156 elif item.attributes['delete']:
150157 raise BundleError(_(
151158 "{item1} (from bundle '{bundle1}') depends on item "
152159 "{item2} (from bundle '{bundle2}') which is set to be deleted"
5959 if isinstance(value1, set):
6060 value1 = sorted(value1)
6161 value2 = sorted(value2)
62 elif isinstance(value1, tuple):
62 else:
63 # convert tuples and create copies of lists before possibly
64 # appending stuff later on (see below)
6365 value1 = list(value1)
6466 value2 = list(value2)
6567 # make sure that *if* we have lines, the last one will also end with
4343 @ansi_wrapper
4444 def inverse(text):
4545 return "\033[0m\033[7m{}\033[0m".format(text)
46
47
48 @ansi_wrapper
49 def italic(text):
50 return "\033[3m{}\033[0m".format(text)
4651
4752
4853 @ansi_wrapper
44 postgres_dbs = {
55 "mydatabase": {
66 "owner": "me",
7 "when_creating": {
8 "encoding": "LATIN1",
9 "collation": "de_DE.ISO-8859-1",
10 "ctype": "de_DE.ISO-8859-1",
11 },
712 },
813 }
914
1823 ### owner
1924
2025 Name of the role which owns this database (defaults to `"postgres"`).
26
27 ### encoding, collation, and ctype
28
29 By default, BundleWrap will only create a database using your default PostgreSQL template, which most likely is `template1`. This means it will use the same encoding and collation that `template1` uses. By specifying any of the attributes `encoding`, `collation`, or `ctype`, BundleWrap will instead create a new database from `template0`, thus allowing you to override said database attributes.
30
31 These options are creation-time only.
6969
7070 <br>
7171
72 ### comment
73
74 This is a string that will be displayed in interactive mode (`bw apply -i`) whenever the item is to be changed in any way. You can use it to warn users before they start disruptive actions.
75
76 <br>
77
7278 ### error_on_missing_fault
7379
7480 This will simply skip an item instead of raising an error when a Fault used for an attribute on the item is unavailable. Faults are special objects used by `repo.vault` to [handle secrets](../guide/secrets.md). A Fault being unavailable can mean you're missing the secret key required to decrypt a secret you're trying to use as an item attribute value.
1515
1616 setup(
1717 name="bundlewrap",
18 version="2.17.1",
18 version="2.18.0",
1919 description="Config management with Python",
2020 long_description=(
2121 "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"
490490 assert run("bw test", path=str(tmpdir))[2] == 1
491491 assert run("bw test group1", path=str(tmpdir))[2] == 1
492492 assert run("bw test group2", path=str(tmpdir))[2] == 1
493
494
495 def test_group_user_dep_deleted(tmpdir):
496 make_repo(
497 tmpdir,
498 nodes={
499 "node1": {
500 'bundles': ["bundle1"],
501 },
502 },
503 bundles={
504 "bundle1": {
505 "users": {
506 "user1": {
507 'groups': ["group1"],
508 },
509 },
510 "groups": {
511 "group1": {
512 'delete': True,
513 },
514 },
515 },
516 },
517 )
518 assert run("bw test", path=str(tmpdir))[2] == 1
519
520
521 def test_group_user_dep_ok(tmpdir):
522 # regression test for #341
523 make_repo(
524 tmpdir,
525 nodes={
526 "node1": {
527 'bundles': ["bundle1"],
528 },
529 },
530 bundles={
531 "bundle1": {
532 "users": {
533 "user1": {},
534 },
535 "groups": {
536 "group1": {'delete': True},
537 },
538 },
539 },
540 )
541 assert run("bw test", path=str(tmpdir))[2] == 0
542
543
544 def test_group_user_dep_deleted_gid(tmpdir):
545 make_repo(
546 tmpdir,
547 nodes={
548 "node1": {
549 'bundles': ["bundle1"],
550 },
551 },
552 bundles={
553 "bundle1": {
554 "users": {
555 "user1": {
556 'gid': "group1",
557 },
558 },
559 "groups": {
560 "group1": {
561 'delete': True,
562 },
563 },
564 },
565 },
566 )
567 assert run("bw test", path=str(tmpdir))[2] == 1