def test_dict(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'files': { "/test": { 'content': "yes please", }, }, }, }, ) stdout, stderr, rcode = run("bw hash -d", path=str(tmpdir)) assert rcode == 0 assert stdout == b"8ab35c696b63a853ccf568b27a50e24a69964487 node1\n" stdout, stderr, rcode = run("bw hash -d node1", path=str(tmpdir)) assert rcode == 0 assert stdout == b"503583964eadabacb18fda32cc9fb1e9f66e424b file:/test\n" stdout, stderr, rcode = run("bw hash -d node1 file:/test", path=str(tmpdir)) assert rcode == 0 assert stdout == ( b"content_hash\tc05a36d547e2b1682472f76985018038d1feebc5\n" b"type\tfile\n" )
def test_only_bundle_with_dep(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "foo"): { 'content_type': 'any', 'needs': ["file:" + join(str(tmpdir), "bar")], }, }, }, "test2": { 'files': { join(str(tmpdir), "bar"): { 'content_type': 'any', }, join(str(tmpdir), "baz"): { 'content_type': 'any', }, }, }, }, nodes={ "localhost": { 'bundles': ["test", "test2"], 'os': host_os(), }, }, ) run("bw apply -o bundle:test localhost", path=str(tmpdir)) assert exists(join(str(tmpdir), "foo")) assert exists(join(str(tmpdir), "bar")) assert not exists(join(str(tmpdir), "baz"))
def test_any_content_exists(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "foo"): { 'content_type': 'any', }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) with open(join(str(tmpdir), "foo"), 'wb') as f: f.write(b"existing content") run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "foo"), 'rb') as f: content = f.read() assert content == b"existing content"
def test_binary_template_content(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "foo.bin"): { 'encoding': 'latin-1', }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) with open(join(str(tmpdir), "bundles", "test", "files", "foo.bin"), 'wb') as f: f.write("ö".encode('utf-8')) run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "foo.bin"), 'rb') as f: content = f.read() assert content.decode('latin-1') == "ö"
def test_secret_identifier_twice(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, "node2": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'files': { "/test": { 'content': "${repo.vault.password_for('testing')}", 'content_type': 'mako', }, }, }, }, ) assert run("bw test -s ''", path=str(tmpdir))[2] == 0 assert run("bw test -s 'test'", path=str(tmpdir))[2] == 0 assert run("bw test -s 'test,foo'", path=str(tmpdir))[2] == 0
def test_fault_content_jinja2(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "secret"): { 'content': "{{ repo.vault.password_for('test') }}", 'content_type': 'jinja2', }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "secret")) as f: content = f.read() assert content == "sQDdTXu5OmCki8gdGgYdfTxooevckXcB"
def test_inline(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1", "bundle2"], }, "node2": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": {}, "bundle2": {}, }, ) stdout, stderr, rcode = run("bw nodes -ai | grep '\tbundle' | grep bundle2 | cut -f 1", path=str(tmpdir)) assert stdout == b"node1\n" assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw nodes -ai | grep '\tbundle' | grep -v bundle2 | cut -f 1", path=str(tmpdir)) assert stdout == b"node2\n" assert stderr == b"" assert rcode == 0
def test_group_members_partial_metadata(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'metadata': {'foo': 1}, }, "node2": {}, }, ) with open(join(str(tmpdir), "groups.py"), 'w') as f: f.write(""" groups = { "group1": { 'members_add': lambda node: node.metadata.get('foo') == 1, }, "group2": { 'members': ["node2"], 'metadata': {'foo': 1}, }, } """) stdout, stderr, rcode = run("bw nodes -a node1 | grep \tgroup | cut -f 3", path=str(tmpdir)) assert stdout == b"group1\n" assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw nodes -a node2 | grep \tgroup | cut -f 3", path=str(tmpdir)) assert stdout == b"group2\n" assert stderr == b"" assert rcode == 0
def test_precedes_action(tmpdir): make_repo( tmpdir, bundles={ "test": { 'actions': { "action1": { 'command': "echo 1 > {}".format(join(str(tmpdir), "file")), 'precedes': ["action:action2"], 'triggered': True, }, "action2": { 'command': "echo 2 >> {}".format(join(str(tmpdir), "file")), }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "file")) as f: content = f.read() assert content == "1\n2\n"
def test_precedes_unless4(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "file"): { 'content': "1\n", 'triggered': True, 'precedes': ["action:action3"], }, }, 'actions': { "action2": { 'command': "false", 'needs': ["file:{}".format(join(str(tmpdir), "file"))], }, "action3": { 'command': "echo 3 >> {}".format(join(str(tmpdir), "file")), 'needs': ["action:action2"], }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "file")) as f: content = f.read() assert content == "1\n"
def test_fault_content(tmpdir): make_repo( tmpdir, bundles={ "test": {}, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) with open(join(str(tmpdir), "bundles", "test", "items.py"), 'w') as f: f.write(""" files = {{ "{}": {{ 'content': repo.vault.password_for("test"), }}, }} """.format(join(str(tmpdir), "secret"))) run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "secret")) as f: content = f.read() assert content == "sQDdTXu5OmCki8gdGgYdfTxooevckXcB"
def test_fault_content_mako_metadata(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "secret"): { 'content': "${node.metadata['secret']}", 'content_type': 'mako', }, }, }, }, ) with open(join(str(tmpdir), "nodes.py"), 'w') as f: f.write(""" nodes = {{ "localhost": {{ 'bundles': ["test"], 'metadata': {{'secret': vault.password_for("test")}}, 'os': "{}", }}, }} """.format(host_os())) run("bw apply localhost", path=str(tmpdir)) with open(join(str(tmpdir), "secret")) as f: content = f.read() assert content == "sQDdTXu5OmCki8gdGgYdfTxooevckXcB"
def test_encrypt_file_base64(tmpdir): make_repo(tmpdir) source_file = join(str(tmpdir), "data", "source") with open(source_file, 'wb') as f: f.write("öhai".encode('latin-1')) stdout, stderr, rcode = run( "bw debug -c 'repo.vault.encrypt_file(\"{}\", \"{}\")'".format( source_file, "encrypted", ), path=str(tmpdir), ) assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run( "bw debug -c 'print(repo.vault.decrypt_file_as_base64(\"{}\"))'".format( "encrypted", ), path=str(tmpdir), ) assert b64decode(stdout.decode('utf-8')) == "öhai".encode('latin-1') assert stderr == b"" assert rcode == 0
def test_encrypt_file(tmpdir): make_repo(tmpdir) source_file = join(str(tmpdir), "data", "source") with open(source_file, 'w') as f: f.write("ohai") stdout, stderr, rcode = run( "bw debug -c 'repo.vault.encrypt_file(\"{}\", \"{}\")'".format( source_file, "encrypted", ), path=str(tmpdir), ) assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run( "bw debug -c 'print(repo.vault.decrypt_file(\"{}\"))'".format( "encrypted", ), path=str(tmpdir), ) assert stdout == b"ohai\n" assert stderr == b"" assert rcode == 0
def test_group_members_remove_bundle(tmpdir): make_repo( tmpdir, bundles={ "bundle1": {}, "bundle2": {}, }, nodes={ "node1": {}, "node2": {}, }, ) with open(join(str(tmpdir), "groups.py"), 'w') as f: f.write(""" groups = { "group1": { 'bundles': ["bundle1"], 'members': ["node1", "node2"], }, "group2": { 'bundles': ["bundle1", "bundle2"], 'members': ["node1", "node2"], 'members_remove': lambda node: node.name == "node2", }, } """) stdout, stderr, rcode = run("bw nodes -a node1 | grep \tbundle | cut -f 3", path=str(tmpdir)) assert stdout == b"bundle1\nbundle2\n" assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw nodes -a node2 | grep \tbundle | cut -f 3", path=str(tmpdir)) assert stdout == b"bundle1\n" assert stderr == b"" assert rcode == 0
def test_encrypt(tmpdir): make_repo(tmpdir) stdout, stderr, rcode = run("bw debug -c 'print(repo.vault.encrypt(\"test\"))'", path=str(tmpdir)) assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw debug -c 'print(repo.vault.decrypt(\"{}\"))'".format(stdout.decode('utf-8').strip()), path=str(tmpdir)) assert stdout == b"test\n" assert stderr == b"" assert rcode == 0
def test_empty_group(tmpdir): make_repo( tmpdir, nodes={ "node1": {}, }, groups={ "group1": {}, "group2": {'members': ["node1"]}, }, ) assert run("bw test", path=str(tmpdir))[2] == 0 assert run("bw test -e", path=str(tmpdir))[2] == 1
def test_unknown_subgroup(tmpdir): make_repo( tmpdir, nodes={ "node1": {}, }, groups={ "group1": {'subgroups': ["missing-group"]}, "group2": {'members': ["node1"]}, }, ) assert run("bw test", path=str(tmpdir))[2] == 1 assert run("bw test group1", path=str(tmpdir))[2] == 1 assert run("bw test group2", path=str(tmpdir))[2] == 1
def test_group_members_remove(tmpdir): make_repo( tmpdir, nodes={ "node1": {'os': 'centos'}, "node2": {'os': 'debian'}, "node3": {'os': 'ubuntu'}, "node4": {'os': 'ubuntu'}, }, ) with open(join(str(tmpdir), "groups.py"), 'w') as f: f.write(""" groups = { "group1": { 'members_add': lambda node: node.os == 'ubuntu', }, "group2": { 'members_add': lambda node: node.os == 'ubuntu', 'members_remove': lambda node: node.name == "node3", }, "group3": { 'members_add': lambda node: not node.in_group("group3"), }, "group4": { 'subgroups': ["group3"], 'members_remove': lambda node: node.os == 'debian', }, } """) stdout, stderr, rcode = run("bw nodes -a node1 | grep \tgroup | cut -f 3", path=str(tmpdir)) assert stdout == b"group3\ngroup4\n" assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw nodes -a node2 | grep \tgroup | cut -f 3", path=str(tmpdir)) assert stdout == b"group3\n" assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw nodes -a node3 | grep \tgroup | cut -f 3", path=str(tmpdir)) assert stdout == b"group1\ngroup3\ngroup4\n" assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw nodes -a node4 | grep \tgroup | cut -f 3", path=str(tmpdir)) assert stdout == b"group1\ngroup2\ngroup3\ngroup4\n" assert stderr == b"" assert rcode == 0
def test_group_metadata_collision_subgroups(tmpdir): make_repo( tmpdir, nodes={"node1": {}}, groups={ "group1": { 'members': ["node1"], 'metadata': { 'foo': { 'baz': 1, }, 'bar': 2, }, }, "group2": { 'metadata': { 'foo': { 'baz': 3, }, 'snap': 4, }, 'subgroups': ["group1", "group3"], }, "group3": { 'members': ["node1"], }, }, ) assert run("bw test -M", path=str(tmpdir))[2] == 0
def test_fault_unavailable_multiple(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'files': { "/test": { 'content': "föö", }, "/testdir/test3": { 'content': "${repo.vault.password_for('test', key='404')}", 'content_type': 'mako', }, }, }, }, ) stdout, stderr, rcode = run("bw items -w itemprev node1", path=str(tmpdir)) assert rcode == 0 assert tmpdir.join("itemprev/test").exists() assert not tmpdir.join("itemprev/testdir/test3").exists()
def test_apply(tmpdir): make_repo( tmpdir, bundles={ "bundle1": { 'files': { join(str(tmpdir), "test"): { 'content': "test", }, }, }, }, groups={ "adhoc-localhost": { 'bundles': ["bundle1"], 'member_patterns': ["localhost"], 'os': host_os(), }, }, ) assert not exists(join(str(tmpdir), "test")) stdout, stderr, rcode = run("bw -A apply localhost", path=str(tmpdir)) assert rcode == 0 assert exists(join(str(tmpdir), "test"))
def test_groups(tmpdir): make_repo( tmpdir, groups={ "group1": { 'members': ["node2"], }, "group2": { 'members': ["node1"], }, "group3": { 'subgroup_patterns': ["p2"], }, "group4": { 'subgroups': ["group1"], }, }, nodes={ "node1": {}, "node2": {}, }, ) stdout, stderr, rcode = run("bw nodes --groups", path=str(tmpdir)) assert stdout.decode().strip().split("\n") == [ "node1: group2, group3", "node2: group1, group4", ] assert stderr == b"" assert rcode == 0
def test_deterministic(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'files': { "/test": { 'content': "${node.name}", 'group': None, # BSD has a different default and we don't want to # deal with that here }, }, }, }, ) hashes = set() for i in range(3): stdout, stderr, rcode = run("bw hash", path=str(tmpdir)) hashes.add(stdout.strip()) assert len(hashes) == 1 assert hashes.pop() == b"2203e7acc35608bbff471c023b7b7498e5b385d9"
def test_nondeterministic(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'files': { "/test": { 'content_type': 'mako', 'content': "<% import random %>${random.randint(1, 9999)}", }, }, }, }, ) hashes = set() for i in range(3): stdout, stderr, rcode = run("bw hash", path=str(tmpdir)) hashes.add(stdout.strip()) assert len(hashes) > 1
def test_fix_dir_target(tmpdir): mkdir(join(str(tmpdir), "dir1")) mkdir(join(str(tmpdir), "dir2")) symlink(join(str(tmpdir), "dir1"), join(str(tmpdir), "link")) make_repo( tmpdir, bundles={ "test": { 'symlinks': { join(str(tmpdir), "link"): { 'target': join(str(tmpdir), "dir2"), }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) stdout, stderr, rcode = run("bw apply localhost", path=str(tmpdir)) assert rcode == 0 assert readlink(join(str(tmpdir), "link")) == join(str(tmpdir), "dir2")
def test_metadatapy(tmpdir): make_repo( tmpdir, bundles={"test": {}}, nodes={ "node1": { 'bundles': ["test"], 'metadata': {"foo": "bar"}, }, }, ) with open(join(str(tmpdir), "bundles", "test", "metadata.py"), 'w') as f: f.write( """@metadata_processor def foo(metadata): metadata["baz"] = node.name return metadata, DONE """) stdout, stderr, rcode = run("bw metadata node1", path=str(tmpdir)) assert loads(stdout.decode()) == { "baz": "node1", "foo": "bar", } assert stderr == b"" assert rcode == 0
def test_merge(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'metadata': { "foo": { "bar": "baz", }, }, }, }, groups={ "group1": { 'members': ["node1"], 'metadata': { "ding": 5, "foo": { "bar": "ZAB", "baz": "bar", }, }, }, }, ) stdout, stderr, rcode = run("bw metadata node1", path=str(tmpdir)) assert loads(stdout.decode()) == { "ding": 5, "foo": { "bar": "baz", "baz": "bar", }, } assert stderr == b"" assert rcode == 0
def test_circular_dep_indirect(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { "pkg_apt": { "foo": { 'needs': ["pkg_apt:bar"], }, "bar": { 'needs': ["pkg_apt:baz"], }, "baz": { 'needs': ["pkg_apt:foo"], }, }, }, }, ) assert run("bw test -I", path=str(tmpdir))[2] == 1
def test_empty_verify(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "foo"): { 'content_type': 'any', }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) with open(join(str(tmpdir), "foo"), 'w') as f: f.write("test") stdout, stderr, rcode = run("bw verify localhost", path=str(tmpdir)) assert rcode == 0
def test_group_metadata_collision_dict_ok(tmpdir): make_repo( tmpdir, nodes={"node1": {}}, groups={ "group1": { 'members': ["node1"], 'metadata': { 'foo': { 'bar': 1 }, }, }, "group2": { 'members': ["node1"], 'metadata': { 'foo': { 'baz': 2 }, }, }, }, ) assert run("bw test", path=str(tmpdir))[2] == 0
def test_group_user_dep_deleted_gid(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { "users": { "user1": { 'gid': "group1", }, }, "groups": { "group1": { 'delete': True, }, }, }, }, ) assert run("bw test", path=str(tmpdir))[2] == 1
def test_fault_content_skipped_mako(tmpdir): make_repo( tmpdir, bundles={ "test": { 'files': { join(str(tmpdir), "secret"): { 'content': "${repo.vault.password_for('test', key='unavailable')}", 'content_type': 'mako', }, }, }, }, nodes={ "localhost": { 'bundles': ["test"], 'os': host_os(), }, }, ) stdout, stderr, rcode = run("bw apply localhost", path=str(tmpdir)) assert rcode == 0 assert not exists(join(str(tmpdir), "secret"))
def test_empty_tag_loop(tmpdir): make_repo( tmpdir, nodes={ "localhost": { 'bundles': ["bundle1"], 'os': host_os(), }, }, bundles={ "bundle1": { 'attrs': { 'tags': { "1": { 'needs': {"tag:2"}, }, "2": { 'tags': {"3"}, }, "3": { 'needs': {"tag:1"}, }, }, }, 'items': { 'actions': { "early": { 'command': "true", }, }, }, }, }, ) stdout, stderr, rcode = run("bw apply localhost", path=str(tmpdir)) assert rcode == 1
def test_circular_dep_direct(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'items': { "pkg_apt": { "foo": { 'needs': ["pkg_apt:bar"], }, "bar": { 'needs': ["pkg_apt:foo"], }, }, }, }, }, ) assert run("bw test -I", path=str(tmpdir))[2] == 1
def test_unknown_tag(tmpdir): make_repo( tmpdir, nodes={ "node1": { 'bundles': ["bundle1"], }, }, bundles={ "bundle1": { 'items': { "files": { "/foo": { 'content': "none", 'needs': { "tag:bar", }, }, }, }, }, }, ) assert run("bw test -I", path=str(tmpdir))[2] == 0
def test_groups_for_node(tmpdir): make_repo( tmpdir, nodes={ "node-foo": { 'groups': {"group-foo"} }, "node-bar": {}, "node-baz": {}, "node-pop": { 'groups': {"group-baz"} }, }, groups={ "group-foo": { 'member_patterns': [r".*-bar"], }, "group-bar": { 'subgroups': ["group-foo"], }, "group-baz": {}, "group-frob": { 'members': {"node-pop"}, }, "group-pop": { 'subgroup_patterns': [r"ba"], }, }, ) stdout, stderr, rcode = run("bw plot groups-for-node node-foo", path=str(tmpdir)) assert stdout == b"""digraph bundlewrap { rankdir = LR node [color="#303030"; fillcolor="#303030"; fontname=Helvetica] edge [arrowhead=vee] "group-bar" [fontcolor=white,style=filled]; "group-foo" [fontcolor=white,style=filled]; "group-pop" [fontcolor=white,style=filled]; "node-foo" [fontcolor="#303030",shape=box,style=rounded]; "group-bar" -> "group-foo" [color="#6BB753",penwidth=2] "group-pop" -> "group-bar" [color="#6BB753",penwidth=2] } """ assert stderr == b"" assert rcode == 0 stdout, stderr, rcode = run("bw plot groups-for-node node-pop", path=str(tmpdir)) assert stdout == b"""digraph bundlewrap { rankdir = LR node [color="#303030"; fillcolor="#303030"; fontname=Helvetica] edge [arrowhead=vee] "group-baz" [fontcolor=white,style=filled]; "group-frob" [fontcolor=white,style=filled]; "group-pop" [fontcolor=white,style=filled]; "node-pop" [fontcolor="#303030",shape=box,style=rounded]; "group-frob" -> "node-pop" [color="#D18C57",penwidth=2] "group-pop" -> "group-baz" [color="#6BB753",penwidth=2] } """ assert stderr == b"" assert rcode == 0
def test_single(tmpdir): make_repo(tmpdir, nodes={"node1": {}}) stdout, stderr, rcode = run("bw nodes", path=str(tmpdir)) assert stdout == b"node1\n" assert stderr == b"" assert rcode == 0
def test_object(tmpdir): make_repo(tmpdir) with open(join(str(tmpdir), "nodes.py"), 'w') as f: f.write("nodes = {'node1': {'metadata': {'foo': object}}}") stdout, stderr, rcode = run("bw metadata node1", path=str(tmpdir)) assert rcode == 1
def test_empty(tmpdir): make_repo(tmpdir) stdout, stderr, rcode = run("bw nodes", path=str(tmpdir)) assert stdout == b"" assert stderr == b"" assert rcode == 0
def test_empty(tmpdir): make_repo(tmpdir) stdout, stderr, rcode = run("bw hash", path=str(tmpdir)) assert stdout == b"bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f\n" assert stderr == b""