Skip to content

Commit

Permalink
Converts config tests to testinfra "host" pragma
Browse files Browse the repository at this point in the history
The old sytanx of automatic module imports as part of the test function args
has been deprecated since testinfra v1.6.0 (2017-04-21). It's still
working, but planned to be dropped as of testinfra v2.0. Took the
opportunity to convert our checks throughout.
  • Loading branch information
Conor Schaefer committed Feb 5, 2019
1 parent db583f9 commit 66ac605
Show file tree
Hide file tree
Showing 27 changed files with 366 additions and 358 deletions.
16 changes: 8 additions & 8 deletions molecule/builder-trusty/tests/test_build_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,43 @@
]


def test_pip_wheel_installed(Command):
def test_pip_wheel_installed(host):
"""
Ensure `wheel` is installed via pip, for packaging Python
dependencies into a Debian package.
"""
c = Command("pip list installed")
c = host.run("pip list installed")
assert "wheel" in c.stdout
assert c.rc == 0


def test_sass_gem_installed(Command):
def test_sass_gem_installed(host):
"""
Ensure the `sass` Ruby gem is installed, for compiling SASS to CSS.
"""
c = Command("gem list")
c = host.run("gem list")
assert "sass (3.4.23)" in c.stdout
assert c.rc == 0


def test_pip_dependencies_installed(Command):
def test_pip_dependencies_installed(host):
"""
Ensure the development pip dependencies are installed
"""
c = Command("pip list installed")
c = host.run("pip list installed")
assert "Flask-Babel" in c.stdout
assert c.rc == 0


@pytest.mark.xfail(reason="This check conflicts with the concept of pegging"
"dependencies")
def test_build_all_packages_updated(Command):
def test_build_all_packages_updated(host):
"""
Ensure a dist-upgrade has already been run, by checking that no
packages are eligible for upgrade currently. This will ensure that
all upgrades, security and otherwise, have been applied to the VM
used to build packages.
"""
c = Command('aptitude --simulate -y dist-upgrade')
c = host.run('aptitude --simulate -y dist-upgrade')
assert c.rc == 0
assert "No packages will be installed, upgraded, or removed." in c.stdout
4 changes: 2 additions & 2 deletions molecule/builder-trusty/tests/test_legacy_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
'/tmp/build-securedrop-ossec-agent',
'/tmp/build-securedrop-ossec-server',
])
def test_build_ossec_apt_dependencies(File, build_path):
def test_build_ossec_apt_dependencies(host, build_path):
"""
Ensure that unwanted build paths are absent. Most of these were created
as unwanted side-effects during CI-related changes to the build scripts.
All paths are rightly considered "legacy" and should never be present on
the build host. This test is strictly for guarding against regressions.
"""
assert not File(build_path).exists
assert not host.file(build_path).exists
62 changes: 31 additions & 31 deletions molecule/builder-trusty/tests/test_securedrop_deb_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,18 @@ def get_deb_tags():


@pytest.mark.parametrize("deb", deb_packages)
def test_build_deb_packages(File, deb):
def test_build_deb_packages(host, deb):
"""
Sanity check the built Debian packages for Control field
values and general package structure.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
assert deb_package.is_file


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_packages_appear_installable(File, Command, Sudo, deb):
def test_deb_packages_appear_installable(host, deb):
"""
Confirms that a dry-run of installation reports no errors.
Simple check for valid Debian package structure, but not thorough.
Expand All @@ -94,16 +94,16 @@ def test_deb_packages_appear_installable(File, Command, Sudo, deb):
Testing application behavior is left to the functional tests.
"""

deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))

deb_basename = os.path.basename(deb_package.path)
package_name = extract_package_name_from_filepath(deb_package.path)
assert deb_basename.startswith(package_name)

# Sudo is required to call `dpkg --install`, even as dry-run.
with Sudo():
c = Command("dpkg --install --dry-run {}".format(deb_package.path))
# sudo is required to call `dpkg --install`, even as dry-run.
with host.sudo():
c = host.run("dpkg --install --dry-run {}".format(deb_package.path))
assert "Selecting previously unselected package {}".format(
package_name) in c.stdout
regex = "Preparing to unpack [./]+{} ...".format(
Expand All @@ -113,18 +113,18 @@ def test_deb_packages_appear_installable(File, Command, Sudo, deb):


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_control_fields(File, Command, deb):
def test_deb_package_control_fields(host, deb):
"""
Ensure Debian Control fields are populated as expected in the package.
These checks are rather superficial, and don't actually confirm that the
.deb files are not broken. At a later date, consider integration tests
that actually use these built files during an Ansible provisioning run.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
package_name = extract_package_name_from_filepath(deb_package.path)
# The `--field` option will display all fields if none are specified.
c = Command("dpkg-deb --field {}".format(deb_package.path))
c = host.run("dpkg-deb --field {}".format(deb_package.path))

assert "Maintainer: SecureDrop Team <securedrop@freedom.press>" in c.stdout
# The securedrop-config package is architecture indepedent
Expand All @@ -138,11 +138,11 @@ def test_deb_package_control_fields(File, Command, deb):


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_control_fields_homepage(File, Command, deb):
deb_package = File(deb.format(
def test_deb_package_control_fields_homepage(host, deb):
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
# The `--field` option will display all fields if none are specified.
c = Command("dpkg-deb --field {}".format(deb_package.path))
c = host.run("dpkg-deb --field {}".format(deb_package.path))
# The OSSEC source packages will have a different homepage;
# all other packages should set securedrop.org as homepage.
if os.path.basename(deb_package.path).startswith('ossec-'):
Expand All @@ -152,61 +152,61 @@ def test_deb_package_control_fields_homepage(File, Command, deb):


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_contains_no_config_file(File, Command, deb):
def test_deb_package_contains_no_config_file(host, deb):
"""
Ensures the `securedrop-app-code` package does not ship a `config.py`
file. Doing so would clobber the site-specific changes made via Ansible.
Somewhat lazily checking all deb packages, rather than just the app-code
package, but it accomplishes the same in a DRY manner.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
c = Command("dpkg-deb --contents {}".format(deb_package.path))
c = host.run("dpkg-deb --contents {}".format(deb_package.path))
assert not re.search("^.*/config\.py$", c.stdout, re.M)


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_contains_pot_file(File, Command, deb):
def test_deb_package_contains_pot_file(host, deb):
"""
Ensures the `securedrop-app-code` package has the
messages.pot file
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
c = Command("dpkg-deb --contents {}".format(deb_package.path))
c = host.run("dpkg-deb --contents {}".format(deb_package.path))
# Only relevant for the securedrop-app-code package:
if "securedrop-app-code" in deb_package.path:
assert re.search("^.*messages.pot$", c.stdout, re.M)


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_contains_mo_file(File, Command, deb):
def test_deb_package_contains_mo_file(host, deb):
"""
Ensures the `securedrop-app-code` package has at least one
compiled mo file.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
c = Command("dpkg-deb --contents {}".format(deb_package.path))
c = host.run("dpkg-deb --contents {}".format(deb_package.path))
# Only relevant for the securedrop-app-code package:
if "securedrop-app-code" in deb_package.path:
assert re.search("^.*messages\.mo$", c.stdout, re.M)


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_contains_no_generated_assets(File, Command, deb):
def test_deb_package_contains_no_generated_assets(host, deb):
"""
Ensures the `securedrop-app-code` package does not ship a minified
static assets, which are built automatically via Flask-Assets, and may be
present in the source directory used to build from.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))

# Only relevant for the securedrop-app-code package:
if "securedrop-app-code" in deb_package.path:
c = Command("dpkg-deb --contents {}".format(deb_package.path))
c = host.run("dpkg-deb --contents {}".format(deb_package.path))
# static/gen/ directory should exist
assert re.search("^.*\./var/www/securedrop"
"/static/gen/$", c.stdout, re.M)
Expand All @@ -229,31 +229,31 @@ def test_deb_package_contains_no_generated_assets(File, Command, deb):


@pytest.mark.parametrize("deb", deb_packages)
def test_deb_package_contains_css(File, Command, deb):
def test_deb_package_contains_css(host, deb):
"""
Ensures the `securedrop-app-code` package contains files that
are generated during the `sass` build process.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))

# Only relevant for the securedrop-app-code package:
if "securedrop-app-code" in deb_package.path:
c = Command("dpkg-deb --contents {}".format(deb_package.path))
c = host.run("dpkg-deb --contents {}".format(deb_package.path))

for css_type in ['journalist', 'source']:
assert re.search("^.*\./var/www/securedrop/static/"
"css/{}.css$".format(css_type), c.stdout, re.M)


@pytest.mark.parametrize("deb, tag", deb_tags)
def test_deb_package_lintian(File, Command, deb, tag):
def test_deb_package_lintian(host, deb, tag):
"""
Ensures lintian likes our Debian packages.
"""
deb_package = File(deb.format(
deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))
c = Command("""lintian --tags {} --no-tag-display-limit {}""".format(
c = host.run("lintian --tags {} --no-tag-display-limit {}".format(
tag, deb_package.path))
assert len(c.stdout) == 0

Expand Down
16 changes: 8 additions & 8 deletions molecule/testinfra/staging/app-code/test_haveged.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
testinfra_hosts = ["app-staging"]


def test_haveged_config(File):
def test_haveged_config(host):
"""
Ensure haveged's low entrop watermark is sufficiently high.
"""
f = File('/etc/default/haveged')
f = host.file('/etc/default/haveged')
assert f.is_file
assert f.user == 'root'
assert f.group == 'root'
assert oct(f.mode) == '0644'
assert f.contains('^DAEMON_ARGS="-w 2400"$')


def test_haveged_no_duplicate_lines(Command):
def test_haveged_no_duplicate_lines(host):
"""
Regression test to check for duplicate entries. Earlier playbooks
for configuring the SD instances needlessly appended the `DAEMON_ARGS`
line everytime the playbook was run. Fortunately the duplicate lines don't
break the service, but it's still poor form.
"""
c = Command("uniq --repeated /etc/default/haveged")
c = host.run("uniq --repeated /etc/default/haveged")
assert c.rc == 0
assert c.stdout == ""


def test_haveged_is_running(Service, Sudo):
def test_haveged_is_running(host):
"""
Ensure haveged service is running, to provide additional entropy.
"""
# Sudo is necessary to read /proc when running under grsecurity,
# sudo is necessary to read /proc when running under grsecurity,
# which the App hosts do. Not technically necessary under development.
with Sudo():
s = Service("haveged")
with host.sudo():
s = host.service("haveged")
assert s.is_running
assert s.is_enabled
8 changes: 4 additions & 4 deletions molecule/testinfra/staging/app-code/test_redis_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,27 @@
"user={}".format(securedrop_test_vars.securedrop_user),
'environment=HOME="/tmp/python-gnupg"',
])
def test_redis_worker_configuration(File, config_line):
def test_redis_worker_configuration(host, config_line):
"""
Ensure SecureDrop Redis worker config for supervisor service
management is configured correctly.
"""
f = File('/etc/supervisor/conf.d/securedrop_worker.conf')
f = host.file('/etc/supervisor/conf.d/securedrop_worker.conf')
# Config lines may have special characters such as [] which will
# throw off the regex matching, so let's escape those chars.
regex = re.escape(config_line)
assert f.contains('^{}$'.format(regex))


def test_redis_worker_config_file(File):
def test_redis_worker_config_file(host):
"""
Ensure SecureDrop Redis worker config for supervisor service
management has proper ownership and mode.
Using separate test so that the parametrization doesn't rerun
the file mode checks, which would be useless.
"""
f = File('/etc/supervisor/conf.d/securedrop_worker.conf')
f = host.file('/etc/supervisor/conf.d/securedrop_worker.conf')
assert f.is_file
assert oct(f.mode) == '0644'
assert f.user == "root"
Expand Down
Loading

0 comments on commit 66ac605

Please sign in to comment.