Database, SSH, Filesystem, Process, and Infrastructure Automation Patterns: Core Concepts and Mental Model
Build a safe Robot Framework infrastructure-automation mental model that separates database connections and transactions, SSH trust, filesystem ownership, child processes, and evidence lifecycles.
Learning objectives
- Trace an infrastructure-facing Robot keyword across resource, database/SSH/process/filesystem boundary, assertion, and result evidence.
- Separate database connection/transaction state, SSH connection/trust state, filesystem ownership, child-process lifetime, Robot variables, and result artifacts.
- Explain why target allowlists and cleanup ownership are prerequisites, not optional hardening after the script works.
- Recognize current DatabaseLibrary, SSHLibrary, Process, and OperatingSystem version/security boundaries.
- Design read-first, mutate-second infrastructure checks that remain safe under local reruns and CI.
Current compatibility baseline — verified 2026-08-31.
Robot Framework 7.4.2 is the stable course
baseline. The mandatory database layer uses
robotframework-databaselibrary 2.4.1, which
requires Python 3.8.1+ and Robot Framework 5.0.1+; the lab uses
Python's built-in sqlite3 driver, so no database server
is required. SSHLibrary 3.8.0 is still the latest
stable PyPI release and 3.8.1rc1 remains prerelease. Its stable
Paramiko implementation accepts unknown host keys with
AutoAddPolicy; therefore real SSH is optional here and
never used as the mandatory production-security pattern. The
required path is local/free: SQLite, Robot standard
OperatingSystem/Process, synthetic files, and a loopback-equivalent
SSH simulation. No public host, production database, paid service,
Pabot, CI provider, or container runtime is required.
1. The problem: an integration check can become an administration script
Chapter 17 deliberately kept HTTP state inside a loopback fixture. Infrastructure automation raises the stakes because a database statement, filesystem deletion, process termination, or SSH command can change state outside the Robot process. The same syntax can be harmless against a disposable SQLite file and destructive against a production database. The difference is target, privilege, ownership, and lifecycle, not the keyword name.
Robot Framework is valuable here as an orchestration and evidence layer. It should make a small integration contract readable: connect to an explicitly allowed target, inspect current state, perform one bounded mutation, verify the exact outcome, and roll back or delete only resources created by this run. It should not become a generic fleet-management replacement for Terraform, Ansible, Salt, or operating-system administration tooling.
2. Read-only preflight before any mutation
python --version
python -m robot --version
python -m pip show robotframework-databaselibrary robotframework-sshlibrary
# Python stdlib SQLite version:
python -c "import sqlite3; print(sqlite3.sqlite_version)"
# Record the intended Robot output directory before the suite creates scratch state.
Nothing above changes a database, process, or filesystem target. Record Python/Robot/library versions, current working directory, output directory, and intended target identifiers. In the mandatory path the database is a file that will be created under Robot's run-specific output directory; there is no public host and no remote credential.
3. Mental model: infrastructure state is a set of independent lifecycles
flowchart TD A[Robot suite] --> B[Domain infrastructure resource] B --> C1[DatabaseLibrary] B --> C2[OperatingSystem] B --> C3[Process] B -. optional .-> C4[SSHLibrary] C1 --> D1[SQLite connection / transaction] C2 --> D2[Owned filesystem] C3 --> D3[Child process] C4 --> D4[SSH connection + trust] D1 --> E[Assertions] D2 --> E D3 --> E D4 --> E E --> F[output.xml / log.html]
Each branch has a different owner. Closing a database connection does not terminate a child process. Removing a file does not roll back a database transaction. Closing an SSH connection does not prove a remote command left no state behind. Robot variables merely reference these stores; they do not unify them. The result model records observations but is not itself the external state.
4. Terms and ownership before mutation
| Term | Meaning | Owner / lifetime |
|---|---|---|
| Database connection | Python DB-API connection registered by DatabaseLibrary | Library connection store; close explicitly |
| Transaction | Pending database changes between transaction boundaries | Database driver/connection |
| SSH connection | Authenticated network channel and active connection index/alias | SSHLibrary/Paramiko |
| SSH trust | Decision that the remote host key represents the intended host | Client trust store/policy; separate from authentication |
| Filesystem state | Files/directories on the machine running Robot | Operating system; ownership must be proven |
| Child process | Program spawned by Process with its own rc/stdout/stderr/lifetime | OS process table + Process library |
| Target allowlist | Explicit set of permitted hosts/paths/databases | Project governance/configuration |
| Evidence | Rows, rc/stdout/stderr, path tree, logs, output.xml | Run artifacts; retain independently of external state |
5. DatabaseLibrary: query adapter plus explicit connection lifecycle
DatabaseLibrary 2.4.1 is an external Robot library. It does not ship
database engines or all drivers; it calls a Python DB-API module.
For SQLite, the driver is Python's built-in sqlite3,
making it ideal for a disposable course fixture.
*** Settings ***
Library DatabaseLibrary
*** Test Cases ***
Read Local Database
Connect To Database sqlite3 database=${DB_PATH} alias=labdb
${rows}= Query SELECT name, state FROM inventory return_dict=${True} alias=labdb
Log ${rows}
Disconnect From Database alias=labdb
The alias identifies library connection state; it is not the
database transaction itself. DatabaseLibrary's query/execute
keywords normally manage commit/rollback around their operation. The
no_transaction option disables that wrapper when a lab
deliberately needs to observe pending transaction state. Treat that
option as an advanced contract, not a speed flag.
6. SQL text and data are different trust boundaries
A test parameter such as a user name is data. It must not become
executable SQL syntax through string concatenation. DatabaseLibrary
exposes a parameters argument so the underlying DB
driver can bind values.
${params}= Create List alpha
${rows}= Query
... SELECT id, name, state FROM inventory WHERE name = ?
... parameters=${params}
... return_dict=${True}
... alias=labdb
The placeholder style depends on the database driver. SQLite uses
?. A PostgreSQL or Oracle driver may use a different
parameter style. The invariant is the same: keep the statement
structure constant and bind values separately.
7. Filesystem state needs an ownership proof
A path inside ${OUTPUTDIR} is convenient, but location
alone does not prove ownership. The suite must refuse to reuse a
pre-existing scratch directory, mark ownership only after successful
creation, normalize the path before destructive cleanup, and delete
only the exact owned root.
${root}= Normalize Path ${OUTPUTDIR}${/}scratch-rf18
${exists}= Run Keyword And Return Status Directory Should Exist ${root}
Should Be Equal ${exists} ${False}
Create Directory ${root}
VAR ${OWNED_ROOT} ${True} scope=SUITE
This is deliberately stricter than “delete and recreate.” A stale directory is evidence that a prior run or another process owns something there. Failing preflight is safer than silently erasing it.
8. Process is structured execution; shell text is not the default
Robot Framework's Process library passes a program and arguments to
the operating system and returns a result object with return code,
stdout, stderr, and optional redirected paths. Keep
shell=False unless a shell is genuinely required and
controlled. This preserves argument boundaries and avoids a large
class of command-injection problems.
${result}= Run Process ${PYTHON} -c print("rf18-ok")
Should Be Equal As Integers ${result.rc} 0
Should Be Equal ${result.stdout} rf18-ok
Should Be Empty ${result.stderr}
For high-volume child output, redirect stdout/stderr to files rather than retaining unbounded output in memory. Chapter 08 already established that Process is preferred over deprecated OperatingSystem Run-style command keywords.
9. SSH has two separate security questions: who are you, and who is the host?
Authentication proves the client identity to the server. Host-key verification proves the server identity to the client. A password or private key can authenticate perfectly while the client is connected to the wrong host.
Current stable caveat: SSHLibrary 3.8.0 uses
Paramiko AutoAddPolicy for missing host keys. That
accepts unknown hosts rather than enforcing a pre-provisioned
trust decision. For this reason the mandatory chapter path
simulates the SSH contract locally. Do not infer that “SSH
encrypted the traffic” means the host identity was verified.
If your organization needs real Robot-driven SSH, establish the host-key policy outside the test first, use a disposable non-production host, least-privilege account, explicit command allowlist, and a library/client stack whose trust behavior satisfies policy. Never solve a host-key failure by disabling verification.
10. DevOps connection: integration evidence, not fleet administration
| Good Robot integration check | Poor administration pattern |
|---|---|
| Verify a migration produced expected rows in disposable DB | Run arbitrary DDL against a configured production DB |
| Start a local fixture and verify rc/output | Kill processes by broad name or PID pattern |
| Create/remove one owned scratch tree | Recursive delete from cwd or user-provided path |
| Read-only command on allowlisted disposable host | Ad-hoc remote package/service administration |
| Preserve output.xml and external-state evidence | Delete logs after repair to make rerun look clean |
Knowledge check
Why is a Robot variable containing a database alias not “the transaction”?
The alias resolves a DatabaseLibrary connection object. Transaction state lives inside the database driver/connection and has its own commit/rollback semantics.
Why does an SSH password not prove the server identity?
The password authenticates the client to whatever server accepted the connection. Host-key verification is the separate mechanism that binds the server to an expected identity.
Why should a scratch directory pre-existence make setup fail?
Because the current run cannot prove it owns the existing directory. Deleting it would risk removing another run or user’s state.
What evidence should a Process call expose?
At minimum the exact program/arguments or safe command identity, return code, stdout/stderr or their file paths, and timing/cleanup ownership where relevant.
What is the chapter’s main safety rule?
Prove target and ownership before mutation, then mutate narrowly, verify independently, and clean up only resources created by this run.
11. Summary and bridge
Infrastructure-facing Robot automation works when state stores remain explicit: database connection/transaction, SSH session/trust, filesystem tree, child process, Robot scope, and result artifact. Lesson 2 turns this model into a fully disposable SQLite/filesystem/process workflow with an SSH simulation and concrete before/after evidence.
References and version anchors
- Robot Framework 7.4.2 User Guide, Process 7.4.2, and OperatingSystem 7.4.2 — core execution, variables/lifecycle, structured child processes, filesystem operations, and current standard-library semantics.
- DatabaseLibrary 2.4.1 keyword documentation, PyPI release, and maintainer repository — connection, query, transaction wrapper, parameter, retry, alias, and SQLite guidance.
- SSHLibrary keyword documentation, SSHLibrary 3.8.0 on PyPI, and maintainer repository — connection/session behavior and current release status. The mandatory lab does not rely on a real SSH server.
- Python sqlite3 documentation — SQLite connection/transaction behavior used by the local database fixture.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.