34
testinfra Documentation Release 1.5.5 Philippe Pepiot Jun 30, 2017

Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

  • Upload
    others

  • View
    11

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra DocumentationRelease 1.5.5

Philippe Pepiot

Jun 30, 2017

Page 2: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor
Page 3: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

Contents

1 About 3

2 Quick start 5

3 Documentation 73.1 Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3.1.1 1.5.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.1.2 1.5.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.1.3 1.5.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.1.4 1.5.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.1.5 1.5.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.1.6 1.5.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.1.7 1.4.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3.2 Invocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.1 Test multiples hosts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.2 Parallel execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.3 Advanced invocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.3 Connection backends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.3.1 local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.3.2 paramiko . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.3.3 docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.3.4 ssh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.3.5 salt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.3.6 ansible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.3.7 kubectl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3.4 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.4.1 Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.4.2 LocalCommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.4.3 TestinfraBackend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.4.4 Sudo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.4.5 File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.4.6 User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.4.7 Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.4.8 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.4.9 Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.4.10 PipPackage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.4.11 Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

i

Page 4: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

3.4.12 Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.4.13 Supervisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.4.14 Socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.4.15 SystemInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.4.16 Salt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.4.17 Ansible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.4.18 PuppetResource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203.4.19 Facter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203.4.20 Sysctl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.4.21 MountPoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.5 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.5.1 Connection API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3.6 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.6.1 Parametrize your tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.6.2 Using unittest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.6.3 Make your own modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.6.4 Share your modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.6.5 Integration with vagrant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.6.6 Integration with jenkins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.6.7 Integration with nagios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.6.8 Test docker images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3.7 Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.7.1 Issue Tracker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.7.2 IRC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.7.3 pytest documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.7.4 Community Contributions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

ii

Page 5: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

Latest documentation: https://testinfra.readthedocs.io/en/latest

Contents 1

Page 6: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

2 Contents

Page 7: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

CHAPTER 1

About

With Testinfra you can write unit tests in Python to test actual state of your servers configured by managements toolslike Salt, Ansible, Puppet, Chef and so on.

Testinfra aims to be a Serverspec equivalent in python and is written as a plugin to the powerful Pytest test engine

3

Page 8: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

4 Chapter 1. About

Page 9: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

CHAPTER 2

Quick start

Install testinfra using pip:

$ pip install testinfra

# or install the devel version$ pip install 'git+https://github.com/philpep/testinfra@master#egg=testinfra'

Write your first tests file to test_myinfra.py:

def test_passwd_file(File):passwd = File("/etc/passwd")assert passwd.contains("root")assert passwd.user == "root"assert passwd.group == "root"assert passwd.mode == 0o644

def test_nginx_is_installed(Package):nginx = Package("nginx")assert nginx.is_installedassert nginx.version.startswith("1.2")

def test_nginx_running_and_enabled(Service):nginx = Service("nginx")assert nginx.is_runningassert nginx.is_enabled

And run it:

$ testinfra -v test_myinfra.py

====================== test session starts ======================platform linux -- Python 2.7.3 -- py-1.4.26 -- pytest-2.6.4

5

Page 10: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

plugins: testinfracollected 3 items

test_myinfra.py::test_passwd_file[local] PASSEDtest_myinfra.py::test_nginx_is_installed[local] PASSEDtest_myinfra.py::test_nginx_running_and_enabled[local] PASSED

=================== 3 passed in 0.66 seconds ====================

6 Chapter 2. Quick start

Page 11: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

CHAPTER 3

Documentation

Changelog

1.5.5

• backends: Fix ansible backend with ansible >= 2.3 (#195)

1.5.4

• backends: fallback to UTF-8 encoding when system encoding is ASCII.

• Service: fix is_running() on systems using Upstart

1.5.3

• Sudo: restore backend command in case of exceptions

1.5.2

• Honnor become_user when using the ansible backend

1.5.1

• Add dependency on importlib on python 2.6

7

Page 12: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

1.5.0

• New kubectl backend

• Command: check_output strip carriage return and newlines (#164)

• Package: rpm improve getting version() and release()

• User: add gecos (comment) field (#155)

1.4.5

• SystemInfo: detect codename from VERSION_CODENAME in /etc/os-release (fallback when lsb_release isn’tinstalled).

• Package: add release property for rpm based systems.

Invocation

Test multiples hosts

By default Testinfra launch tests on local machine, but you can also test remotes systems using paramiko (a sshimplementation in python):

$ pip install paramiko$ testinfra -v --hosts=localhost,root@webserver:2222 test_myinfra.py

====================== test session starts ======================platform linux -- Python 2.7.3 -- py-1.4.26 -- pytest-2.6.4plugins: testinfracollected 3 items

test_myinfra.py::test_passwd_file[localhost] PASSEDtest_myinfra.py::test_nginx_is_installed[localhost] PASSEDtest_myinfra.py::test_nginx_running_and_enabled[localhost] PASSEDtest_myinfra.py::test_passwd_file[root@webserver:2222] PASSEDtest_myinfra.py::test_nginx_is_installed[root@webserver:2222] PASSEDtest_myinfra.py::test_nginx_running_and_enabled[root@webserver:2222] PASSED

=================== 6 passed in 8.49 seconds ====================

You can also set hosts per test module:

testinfra_hosts = ["localhost", "root@webserver:2222"]

def test_foo(File, Package, Service):[....]

Parallel execution

If you have a lot of tests, you can use the pytest-xdist plugin to run tests using multiples process:

8 Chapter 3. Documentation

Page 13: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

$ pip install pytest-xdist

# Launch tests using 3 processes$ testinfra -n 3 -v --host=web1,web2,web3,web4,web5,web6 test_myinfra.py

Advanced invocation

# Test recursively all test files (starting with `test_`) in current directory$ testinfra

# Filter function/hosts with pytest -k option$ testinfra --hosts=webserver,dnsserver -k webserver -k nginx

For more usages and features, see the Pytest documentation.

Connection backends

Testinfra comes with several connections backends for remote command execution, they are controlled with the--connection parameter.

For all backends, command can be run as superuser with the --sudo option or as specific user by adding a--sudo-user option.

local

This is the default backend when not hosts are provided (either via --hosts or in modules). Commands are runlocally in a subprocess under the current user:

$ testinfra --sudo test_myinfra.py

paramiko

This is the default backend when a hosts list is provided, paramiko is a python implementation of SSHv2 protocol.Testinfra will not ask you for a password, so you must be able to connect without password (using password less keysor using ssh-agent).

You can provide an alternate ssh-config and use sudo on the remote host:

$ testinfra --ssh-config=/path/to/ssh_config --sudo --hosts=server

docker

The docker backend can be used to test running containers. It use the docker exec command:

$ testinfra --connection=docker --hosts=[user@]docker_id_or_name

See also the Test docker images example.

3.3. Connection backends 9

Page 14: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

ssh

This is a pure ssh backend using the ssh command available in $PATH. Example:

$ testinfra --connection=ssh --hosts=server

The ssh backend also accept --ssh-config and --sudo parameters.

salt

The salt backend use the salt python client API and can be used from the salt-master server:

$ testinfra --connection=salt # equivalent to --hosts='*'$ testinfra --connection=salt --hosts=minion1,minion2$ testinfra --connection=salt --hosts='web*'$ testinfra --connection=salt --hosts=G@os:Debian

Testinfra will use the salt connection channel to run commands.

Host can be seleted using glob or compound matchers.

ansible

The ansible backend use the ansible python API:

$ testinfra --connection=ansible # tests all inventory hosts$ testinfra --connection=ansible --hosts=host1,host2$ testinfra --connection=ansible --hosts='web*'

You can use an alternative inventory with the --ansible-inventory option.

Note: Ansible settings such as remote_user, etc., may be configured by using Ansible’s environment variables.

kubectl

The kubectl backend can be used to test containers running in Kubernetes. It use the kubectl exec command:

$ testinfra --connection=kubectl --hosts=pod_id-123456789-9fng/container_name

Modules

Testinfra modules are provided as pytest fixtures, declare them as arguments of your test function to make themavailable:

def test_foo(Package, File, Command):[...]

Note that you can also Using unittest.

10 Chapter 3. Documentation

Page 15: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

Command

class testinfra.modules.command.Command(command, *args)Run given command and return rc (exit status), stdout and stderr

>>> cmd = Command("ls -l /etc/passwd")>>> cmd.rc0>>> cmd.stdout'-rw-r--r-- 1 root root 1790 Feb 11 00:28 /etc/passwd\n'>>> cmd.stderr''

Good practice: always use shell arguments quoting to avoid shell injection

>>> cmd = Command("ls -l -- %s", "/;echo inject")CommandResult(

rc=2, stdout='',stderr='ls: cannot access /;echo inject: No such file or directory\n',command="ls -l '/;echo inject'")

exists(command)Return True if given command exist in $PATH

check_output(command, *args, **kwargs)Get stdout of a command which has run successfully

Returns stdout without trailing newline

Raises AssertionError

run_expect(expected, command, *args, **kwargs)Run command and check it return an expected exit status

Parameters expected – A list of expected exit status

Raises AssertionError

run_test(command, *args, **kwargs)Run command and check it return an exit status of 0 or 1

Raises AssertionError

LocalCommand

testinfra.plugin.LocalCommand(command, *args)Run commands locally

Same as Command but run commands locally with subprocess even when the connection backend is not “local”.

Note: LocalCommand does NOT respect --sudo option

TestinfraBackend

class testinfra.backend.base.BaseBackendRepresent the connection to the remote or local system

3.4. Modules 11

Page 16: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

classmethod get_connection_type()Return the connection backend used as string.

Can be local, paramiko, ssh, docker, salt or ansible

get_hostname()Return the hostname (for testinfra) of the remote or local system

Can be useful for multi-hosts tests:

Example:

import requests

def test(TestinfraBackend):host = TestinfraBackend.get_hostname()response = requests.get("http://" + host)assert response.status_code == 200

$ testinfra --hosts=server1,server2 test.py

test.py::test[paramiko://server1] PASSEDtest.py::test[paramiko://server2] PASSED

get_module(name)Return the testinfra module adapted to the current backend

def test(Package):[...]

# Is equivalent todef test(TestinfraBackend):

Package = TestinfraBackend.get_module("Package")

Sudo

class testinfra.modules.sudo.Sudo(user=None)Sudo module allow to run certain portion of code under another user.

It is used as a context manager and can be nested.

>>> Command.check_output("whoami")'phil'>>> with Sudo():... Command.check_output("whoami")... with Sudo("www-data"):... Command.check_output("whoami")...'root''www-data'

File

class testinfra.modules.file.File(path)Test various files attributes

12 Chapter 3. Documentation

Page 17: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

existsTest if file exists

>>> File("/etc/passwd").existsTrue>>> File("/nonexistent").existsFalse

is_file

is_directory

is_pipe

is_socket

is_symlink

linked_toResolve symlink

>>> File("/var/lock").linked_to'/run/lock'

userReturn file owner as string

>>> File("/etc/passwd").user'root'

uidReturn file user id as integer

>>> File("/etc/passwd").uid0

group

gid

modeReturn file mode as octal integer

>>> File("/etc/passwd").mode384 # 0o600 (octal)>>> File("/etc/password").mode == 0o600True>>> oct(File("/etc/password").mode) == '0600'True

Note: Python 3 oct(x)_ function will produce '0o600'

You can also utilize the file mode constants from the stat library for testing file mode.

>>> import stat>>> File("/etc/password").mode == stat.S_IRUSR | stat.S_IWUSRTrue

contains(pattern)

md5sum

3.4. Modules 13

Page 18: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

sha256sum

contentReturn file content as bytes

>>> File("/tmp/foo").contentb'caf\xc3\xa9'

content_stringReturn file content as string

>>> File("/tmp/foo").content_string'café'

mtimeReturn time of last modification as datetime.datetime object

>>> File("/etc/passwd").mtimedatetime.datetime(2015, 3, 15, 20, 25, 40)

sizeReturn size of file in bytes

User

class testinfra.modules.user.User(name=None)Test unix users

If name is not supplied, test the current user

nameReturn user name

exists

uidReturn user ID

gidReturn effective group ID

groupReturn effective group name

gidsReturn the list of user group IDs

groupsReturn the list of user group names

homeReturn the user home directory

shellReturn the user login shell

passwordReturn the crypted user password

gecosReturn the user comment/gecos field

14 Chapter 3. Documentation

Page 19: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

expiration_dateReturn the account expiration date

>>> User("phil").expiration_datedatetime.datetime(2020, 1, 1, 0, 0)>>> User("root").expiration_dateNone

classmethod get_module_class(_backend)

Group

class testinfra.modules.group.Group(name=None)Test unix group

exists

gid

Interface

class testinfra.modules.interface.Interface(name)Test network interfaces

exists

speed

addressesReturn ipv4 and ipv6 addresses on the interface

>>> Interface("eth0").addresses['192.168.31.254', '192.168.31.252', 'fe80::e291:f5ff:fe98:6b8c']

Package

class testinfra.modules.package.Package(name)Test packages status and version

is_installedTest if the package is installed

>>> Package("nginx").is_installedTrue

Supported package systems:

•apt (Debian, Ubuntu, ...)

•rpm (RHEL, Centos, Fedora, ...)

•pkg_info (OpenBSD)

•pkg_info (NetBSD)

•pkg (FreeBSD)

3.4. Modules 15

Page 20: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

releaseReturn the release specific info from the package version

>>> Package("nginx").release'1.el6'

versionReturn package version as returned by the package system

>>> Package("nginx").version'1.2.1-2.2+wheezy3'

PipPackage

class testinfra.modules.pip.PipPackageTest pip packages status and version

get_packages(pip_path=u’pip’)Get all installed packages and versions returned by pip list:

>>> PipPackage.get_packages(pip_path='~/venv/website/bin/pip'){'Django': {'version': '1.10.2'},'mywebsite': {'version': '1.0a3', 'path': '/srv/website'},'psycopg2': {'version': '2.6.2'}}

get_outdated_packages(pip_path=u’pip’)Get all outdated packages with current and latest version

>>> PipPackage.get_outdated_packages(pip_path='~/venv/website/bin/pip'){'Django': {'current': '1.10.2', 'latest': '1.10.3'}}

Process

class testinfra.modules.process.ProcessTest Processes attributes

Processes are selected using filter() or get(), attributes names are described in the ps(1) man page.

>>> master = Process.get(user="root", comm="nginx")# Here is the master nginx process (running as root)>>> master.args'nginx: master process /usr/sbin/nginx -g daemon on; master_process on;'# Here are the worker processes (Parent PID = master PID)>>> workers = Process.filter(ppid=master.pid)>>> len(workers)4# Nginx don't eat memory>>> sum([w.pmem for w in workers])0.8# But php does !>>> sum([p.pmem for p in Process.filter(comm="php5-fpm")])19.2

filter(**filters)Get a list of matching process

16 Chapter 3. Documentation

Page 21: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

>>> Process.filter(user="root", comm="zsh")[<process zsh (pid=2715)>, <process zsh (pid=10502)>, ...]

get(**filters)Get one matching process

Raise RuntimeError if no process found or multiple process matching filters.

Service

class testinfra.modules.service.Service(name)Test services

Implementations:

•Linux: detect Systemd or Upstart, fallback to SysV

•FreeBSD: service(1)

•OpenBSD: /etc/rc.d/$name check for is_running (is_enabled is not yet implemented)

•NetBSD: /etc/rc.d/$name onestatus for is_running (is_enabled is not yet imple-mented)

is_runningTest if service is running

is_enabledTest if service is enabled

Supervisor

class testinfra.modules.supervisor.Supervisor(name, _attrs_cache=None)Test supervisor managed services

>>> gunicorn = Supervisor("gunicorn")>>> gunicorn.status'RUNNING'>>> gunicorn.is_runningTrue>>> gunicorn.pid4242

is_runningReturn True if managed service is in status RUNNING

statusReturn the status of the managed service

Status can be STOPPED, STARTING, RUNNING, BACKOFF, STOPPING, EXITED, FATAL, UN-KNOWN.

See http://supervisord.org/subprocess.html#process-states

pidReturn the pid (as int) of the managed service

classmethod get_services()Get a list of services running under supervisor

3.4. Modules 17

Page 22: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

>>> Supervisor.get_services()[<Supervisor(name="gunicorn", status="RUNNING", pid=4232)><Supervisor(name="celery", status="FATAL", pid=None)>]

Socket

class testinfra.modules.socket.Socket(socketspec)Test listening tcp/udp and unix sockets

socketspec must be specified as <protocol>://<host>:<port>

This module requires the netstat command to on the target host.

Example:

•Unix sockets: unix:///var/run/docker.sock

•All ipv4 and ipv6 tcp sockets on port 22: tcp://22

•All ipv4 sockets on port 22: tcp://0.0.0.0:22

•All ipv6 sockets on port 22: tcp://:::22

•udp socket on 127.0.0.1 port 69: udp://127.0.0.1:69

is_listeningTest if socket is listening

>>> Socket("unix:///var/run/docker.sock").is_listeningFalse>>> # This HTTP server listen on all ipv4 adresses but not on ipv6>>> Socket("tcp://0.0.0.0:80").is_listeningTrue>>> Socket("tcp://:::80").is_listeningFalse>>> Socket("tcp://80").is_listeningFalse

Note: If you don’t specify a host for udp and tcp sockets, then the socket is listening if and only if thesocket listen on both all ipv4 and ipv6 addresses (ie 0.0.0.0 and ::)

clientsReturn a list of clients connected to a listening socket

For tcp and udp sockets a list of pair (adress, port) is returned. For unix sockets a list of None is returned(thus you can make a len() for counting clients).

>>> Socket("tcp://22").clients[('2001:db8:0:1', 44298), ('192.168.31.254', 34866)]>>> Socket("unix:///var/run/docker.sock")[None, None, None]

classmethod get_listening_sockets()Return a list of all listening sockets

>>> Socket.get_listening_sockets()['tcp://0.0.0.0:22', 'tcp://:::22', 'unix:///run/systemd/private', ...]

18 Chapter 3. Documentation

Page 23: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

SystemInfo

class testinfra.modules.systeminfo.SystemInfoReturn system informations

typeOS type

>>> SystemInfo.type'linux'

distributionDistribution name

>>> SystemInfo.distribution'debian'

releaseDistribution release number

>>> SystemInfo.release'7.8'

codenameRelease code name

>>> SystemInfo.codename'wheezy'

Salt

class testinfra.modules.salt.Salt(function, args=None)Run salt module functions

>>> Salt("pkg.version", "nginx")'1.6.2-5'>>> Salt("pkg.version", ["nginx", "php5-fpm"]){'nginx': '1.6.2-5', 'php5-fpm': '5.6.7+dfsg-1'}>>> Salt("grains.item", ["osarch", "mem_total", "num_cpus"]){'osarch': 'amd64', 'num_cpus': 4, 'mem_total': 15520}

Run salt-call sys.doc to get a complete list of functions

Ansible

class testinfra.modules.ansible.Ansible(module_name, module_args=None, check=True)Run Ansible module functions

This module is only available with the ansible connection backend.

Check mode is enabled by default, you can disable it with check=False.

>>> Ansible("apt", "name=nginx state=present")["changed"]False>>> Ansible("command", "echo foo", check=False)["stdout"]'foo'

3.4. Modules 19

Page 24: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

>>> Ansible("setup")["ansible_facts"]["ansible_lsb"]["codename"]'jessie'>>> Ansible("file", "path=/etc/passwd")["mode"]'0640'

exception AnsibleException(result)Exception raised when an error occur in an ansible call

result from ansible can be accessed through the result attribute

>>> try:... Ansible("command", "echo foo")... except Ansible.AnsibleException as exc:... assert exc.result['failed'] is True... assert exc.result['msg'] == 'check mode not supported for command'

Ansible.get_variables()Returns a dict of ansible variables

>>> Ansible.get_variables(){

'inventory_hostname': 'localhost','group_names': ['ungrouped'],'foo': 'bar',

}

PuppetResource

class testinfra.modules.puppet.PuppetResource(type, name=None)Get puppet resources

Run puppet resource --types to get a list of available types.

>>> PuppetResource("user", "www-data"){

'www-data': {'ensure': 'present','comment': 'www-data','gid': '33','home': '/var/www','shell': '/usr/sbin/nologin','uid': '33',

},}

Facter

class testinfra.modules.puppet.Facter(*facts)Get facts with facter

>>> Facter(){

"operatingsystem": "Debian","kernel": "linux",[...]

20 Chapter 3. Documentation

Page 25: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

}>>> Facter("kernelversion", "is_virtual"){"kernelversion": "3.16.0","is_virtual": "false"

}

Sysctl

class testinfra.modules.sysctl.Sysctl(name)Test kernel parameters

>>> Sysctl("kernel.osrelease")"3.16.0-4-amd64">>> Sysctl("vm.dirty_ratio")20

MountPoint

class testinfra.modules.mountpoint.MountPoint(path)Test Mount Points

existsReturn True if the mountpoint exists

>>> MountPoint("/").existsTrue

>>> MountPoint("/not/a/mountpoint").existsFalse

filesystemReturns the filesystem type associated

>>> MountPoint("/").filesystem'ext4'

deviceReturn the device associated

>>> MountPoint("/").device'/dev/sda1'

optionsReturn a list of options that a mount point has been created with

>>> MountPoint("/").options['rw', 'relatime', 'data=ordered']

classmethod get_mountpoints()Returns a list of MountPoint instances

3.4. Modules 21

Page 26: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

>>> MountPoint.get_mountpoints()[<MountPoint(path=/proc, device=proc, filesystem=proc, options=rw,nosuid,→˓nodev,noexec,relatime)><MountPoint(path=/, device=/dev/sda1, filesystem=ext4, options=rw,relatime,→˓errors=remount-ro,data=ordered)>]

API

Connection API

You can use testinfra outside of pytest or you can dynamically get a connection and call fonction from modules:

>>> import testinfra>>> conn = testinfra.get_backend("paramiko://root@server:2222", sudo=True)>>> conn.File("/etc/shadow").mode == 0o640True

Same applies to all Modules.

For instance you could make a test to compare two files on two different servers:

import testinfra

def test_same_passwd():a = testinfra.get_backend("ssh://a")b = testinfra.get_backend("ssh://b")assert a.File("/etc/passwd").content == a.File("/etc/passwd").content

Examples

Parametrize your tests

Pytest support test parametrization:

# BAD: If the test fails on nginx, python is not testeddef test_packages(Package):

for name, version in (("nginx", "1.6"),("python", "2.7"),

):assert Package(name).is_installedassert Package(name).version.startswith(version)

# GOOD: Each package is tested# $ testinfra -v test.py# [...]# test.py::test_package[local-nginx-1.6] PASSED# test.py::test_package[local-python-2.7] PASSED# [...]import pytest

22 Chapter 3. Documentation

Page 27: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

@pytest.mark.parametrize("name,version", [("nginx", "1.6"),("python", "2.7"),

])def test_packages(Package, name, version):

assert Package(name).is_installedassert Package(name).version.startswith(version)

Using unittest

Testinfra can be used with python standard unit test framework unittest instead of pytest:

import unittestimport testinfra

class Test(unittest.TestCase):

def setUp(self):self.b = testinfra.get_backend("paramiko://root@host")

def test_nginx_config(self):self.assertEqual(self.b.Command("nginx -t").rc, 0)

def test_nginx_service(self):service = self.b.Service("nginx")self.assertTrue(service.is_running)self.assertTrue(service.is_enabled)

if __name__ == "__main__":unittest.main()

$ python test.py..----------------------------------------------------------------------Ran 2 tests in 0.705s

OK

Make your own modules

Suppose you want to create a simple wrapper around the echo command. You just have to declare a pytest fixture:

import pytest

@pytest.fixture()def Echo(Command):

def f(arg):return Command.check_output("echo %s", arg)

return f

3.6. Examples 23

Page 28: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

def test(Echo):assert Echo("foo") == "foo"

If you want to use it in all your test file, just put it in a conftest.py file.

Share your modules

Suppose you wrote a more useful module than the echo wrapper above and want to share with the entire world. Youcan package your plugin as a pytest plugin.

See philpep/testinfra-echo to see an example of pytest plugin based on testinfra.

Integration with vagrant

Vagrant is a tool that setup and provision development environment (virtual machines).

When your vagrant machine is up and running, you can easily run your testinfra test suite on it:

vagrant ssh-config > .vagrant/ssh-configtestinfra --hosts=default --ssh-config=.vagrant/ssh-config tests.py

Integration with jenkins

Jenkins is a well known open source continuous integration server.

If your jenkins slave can run vagrant, your build scripts can be like:

pip install testinfra paramikovagrant upvagrant ssh-config > .vagrant/ssh-configtestinfra --hosts=default --ssh-config=.vagrant/ssh-config --junit-xml junit.xml→˓tests.py

Then configure jenkins to get tests results from the junit.xml file.

If you use the docker provisioner in vagrant, and use the docker plugin in jenkins, you might be interested by thephilpep/jenkins-slave:jessie docker image. This is the image used to tests testinfra itself using vagrant and docker (indocker).

Integration with nagios

The tests you will write with testinfra will usually be testing that the services you’re deploying run correctly. This kindof tests are close to monitoring checks, so let’s push them to Nagios !

Testinfra has an option –nagios that enable a compatible nagios plugin beharvior:

$ testinfra -qq --nagios test_ok.py; echo $?TESTINFRA OK - 2 passed, 0 failed, 0 skipped in 2.30 seconds[...]0

$ testinfra -qq --nagios test_fail.py; echo $?TESTINFRA CRITICAL - 1 passed, 1 failed, 0 skipped in 2.24 seconds

24 Chapter 3. Documentation

Page 29: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

[Traceback that explain the failed test]2

You can run these tests from the nagios master or in the target host with NRPE.

Test docker images

Docker is a handy way to test your infrastructure code. This recipe show how to test the resulting docker image withtestinfra and provides awesome features like testing multiple images and run some destructive tests on a dedicatedcontainer.

This will use advanced pytest features, to understand the underlying concepts read the pytest documentation:

• https://pytest.org/latest/fixture.html

• https://pytest.org/latest/parametrize.html

• https://pytest.org/latest/example/markers.html

Put this code in a conftest.py file:

import pytestimport testinfra

# Use testinfra to get a handy function to run commands locallycheck_output = testinfra.get_backend(

"local://").get_module("Command").check_output

@pytest.fixturedef TestinfraBackend(request):

# Override the TestinfraBackend fixture,# all testinfra fixtures (i.e. modules) depend on it.

docker_id = check_output("docker run -d %s tail -f /dev/null", request.param)

def teardown():check_output("docker rm -f %s", docker_id)

# Destroy the container at the end of the fixture liferequest.addfinalizer(teardown)

# Return a dynamic created backendreturn testinfra.get_backend("docker://" + docker_id)

def pytest_generate_tests(metafunc):if "TestinfraBackend" in metafunc.fixturenames:

# Lookup "docker_images" markermarker = getattr(metafunc.function, "docker_images", None)if marker is not None:

images = marker.argselse:

# Default imageimages = ["debian:jessie"]

3.6. Examples 25

Page 30: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

# If the test has a destructive marker, we scope TestinfraBackend# at function level (i.e. executing for each test). If not we scope# at session level (i.e. all tests will share the same container)if getattr(metafunc.function, "destructive", None) is not None:

scope = "function"else:

scope = "session"

metafunc.parametrize("TestinfraBackend", images, indirect=True, scope=scope)

Then create a test_docker.py file with our testinfra tests:

import pytest

# To mark all the tests as destructive:# pytestmark = pytest.mark.destructive

# To run all the tests on given docker images:# pytestmark = pytest.mark.docker_images("debian:jessie", "centos:7")

# Both# pytestmark = [# pytest.mark.destructive,# pytest.mark.docker_images("debian:jessie", "centos:7")# ]

# This test will run on default image (debian:jessie)def test_default(Process):

assert Process.get(pid=1).comm == "tail"

# This test will run on both debian:jessie and centos:7 [email protected]_images("debian:jessie", "centos:7")def test_multiple(Process):

assert Process.get(pid=1).comm == "tail"

# This test is marked as destructive and will run on its own container# It will create a /foo file and run 3 times with different [email protected]@pytest.mark.parametrize("content", ["bar", "baz", "qux"])def test_destructive(Command, File, content):

assert not File("/foo").existsCommand.check_output("echo %s > /foo", content)assert File("/foo").content_string == content + "\n"

Now let’s run it:

$ testinfra -v[...]

test_docker.py::test_default[debian:jessie] PASSEDtest_docker.py::test_multiple[debian:jessie] PASSEDtest_docker.py::test_multiple[centos:7] PASSEDtest_docker.py::test_destructive[debian:jessie-bar] PASSED

26 Chapter 3. Documentation

Page 31: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

test_docker.py::test_destructive[debian:jessie-baz] PASSEDtest_docker.py::test_destructive[debian:jessie-qux] PASSED

Note that you can speedup the tests execution by using pytest-xdist.

Support

If you have questions or need help with testinfra please consider one of the following

Issue Tracker

Checkout existing issues on project issue tracker

IRC

You can also ask questions on IRC in #testinfra channel on Freenode

pytest documentation

testinfra is implemented as pytest plugin so to get the most out of please read pytest documentation

Community Contributions

• Molecule is an Automated testing framework for Ansible roles, with native Testinfra support.

3.7. Support 27

Page 32: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

28 Chapter 3. Documentation

Page 33: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

Index

Aaddresses (testinfra.modules.interface.Interface attribute),

15Ansible (class in testinfra.modules.ansible), 19Ansible.AnsibleException, 20

BBaseBackend (class in testinfra.backend.base), 11

Ccheck_output() (testinfra.modules.command.Command

method), 11clients (testinfra.modules.socket.Socket attribute), 18codename (testinfra.modules.systeminfo.SystemInfo at-

tribute), 19Command (class in testinfra.modules.command), 11contains() (testinfra.modules.file.File method), 13content (testinfra.modules.file.File attribute), 14content_string (testinfra.modules.file.File attribute), 14

Ddevice (testinfra.modules.mountpoint.MountPoint at-

tribute), 21distribution (testinfra.modules.systeminfo.SystemInfo at-

tribute), 19

Eexists (testinfra.modules.file.File attribute), 12exists (testinfra.modules.group.Group attribute), 15exists (testinfra.modules.interface.Interface attribute), 15exists (testinfra.modules.mountpoint.MountPoint at-

tribute), 21exists (testinfra.modules.user.User attribute), 14exists() (testinfra.modules.command.Command method),

11expiration_date (testinfra.modules.user.User attribute), 15

FFacter (class in testinfra.modules.puppet), 20

File (class in testinfra.modules.file), 12filesystem (testinfra.modules.mountpoint.MountPoint at-

tribute), 21filter() (testinfra.modules.process.Process method), 16

Ggecos (testinfra.modules.user.User attribute), 14get() (testinfra.modules.process.Process method), 17get_connection_type() (testin-

fra.backend.base.BaseBackend class method),11

get_hostname() (testinfra.backend.base.BaseBackendmethod), 12

get_listening_sockets() (testinfra.modules.socket.Socketclass method), 18

get_module() (testinfra.backend.base.BaseBackendmethod), 12

get_module_class() (testinfra.modules.user.User classmethod), 15

get_mountpoints() (testin-fra.modules.mountpoint.MountPoint classmethod), 21

get_outdated_packages() (testin-fra.modules.pip.PipPackage method), 16

get_packages() (testinfra.modules.pip.PipPackagemethod), 16

get_services() (testinfra.modules.supervisor.Supervisorclass method), 17

get_variables() (testinfra.modules.ansible.Ansiblemethod), 20

gid (testinfra.modules.file.File attribute), 13gid (testinfra.modules.group.Group attribute), 15gid (testinfra.modules.user.User attribute), 14gids (testinfra.modules.user.User attribute), 14Group (class in testinfra.modules.group), 15group (testinfra.modules.file.File attribute), 13group (testinfra.modules.user.User attribute), 14groups (testinfra.modules.user.User attribute), 14

29

Page 34: Release 1.5.5 Philippe Pepiot - Read the Docs · 3.4.12 Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 3.4.13 Supervisor

testinfra Documentation, Release 1.5.5

Hhome (testinfra.modules.user.User attribute), 14

IInterface (class in testinfra.modules.interface), 15is_directory (testinfra.modules.file.File attribute), 13is_enabled (testinfra.modules.service.Service attribute),

17is_file (testinfra.modules.file.File attribute), 13is_installed (testinfra.modules.package.Package at-

tribute), 15is_listening (testinfra.modules.socket.Socket attribute),

18is_pipe (testinfra.modules.file.File attribute), 13is_running (testinfra.modules.service.Service attribute),

17is_running (testinfra.modules.supervisor.Supervisor at-

tribute), 17is_socket (testinfra.modules.file.File attribute), 13is_symlink (testinfra.modules.file.File attribute), 13

Llinked_to (testinfra.modules.file.File attribute), 13LocalCommand() (in module testinfra.plugin), 11

Mmd5sum (testinfra.modules.file.File attribute), 13mode (testinfra.modules.file.File attribute), 13MountPoint (class in testinfra.modules.mountpoint), 21mtime (testinfra.modules.file.File attribute), 14

Nname (testinfra.modules.user.User attribute), 14

Ooptions (testinfra.modules.mountpoint.MountPoint

attribute), 21

PPackage (class in testinfra.modules.package), 15password (testinfra.modules.user.User attribute), 14pid (testinfra.modules.supervisor.Supervisor attribute), 17PipPackage (class in testinfra.modules.pip), 16Process (class in testinfra.modules.process), 16PuppetResource (class in testinfra.modules.puppet), 20

Rrelease (testinfra.modules.package.Package attribute), 15release (testinfra.modules.systeminfo.SystemInfo at-

tribute), 19run_expect() (testinfra.modules.command.Command

method), 11

run_test() (testinfra.modules.command.Commandmethod), 11

SSalt (class in testinfra.modules.salt), 19Service (class in testinfra.modules.service), 17sha256sum (testinfra.modules.file.File attribute), 13shell (testinfra.modules.user.User attribute), 14size (testinfra.modules.file.File attribute), 14Socket (class in testinfra.modules.socket), 18speed (testinfra.modules.interface.Interface attribute), 15status (testinfra.modules.supervisor.Supervisor attribute),

17Sudo (class in testinfra.modules.sudo), 12Supervisor (class in testinfra.modules.supervisor), 17Sysctl (class in testinfra.modules.sysctl), 21SystemInfo (class in testinfra.modules.systeminfo), 19

Ttype (testinfra.modules.systeminfo.SystemInfo attribute),

19

Uuid (testinfra.modules.file.File attribute), 13uid (testinfra.modules.user.User attribute), 14User (class in testinfra.modules.user), 14user (testinfra.modules.file.File attribute), 13

Vversion (testinfra.modules.package.Package attribute), 16

30 Index