Skip to content

TerraformPool

Import TerraformPool from the package root:

from libterraform import TerraformPool

TerraformPool runs Terraform commands in parallel across a pool of worker processes. Terraform reuses process-wide state (working directory, stdio, plugin clients, signal handling), so CLI execution is serialized inside a single Python process even when called from multiple threads. TerraformPool gives each command its own worker process, so independent module operations can achieve true parallel Terraform operations.

Execution Model

Each worker process imports libterraform, builds its own TerraformCommand, and runs one command against one module directory. Command results and check=True errors are returned to the parent process unchanged.

Reuse a single pool to amortize the cost of starting workers and loading the shared library. Use it as a context manager, or call shutdown() explicitly.

The examples below use illustrative paths like modules/app; replace them with your own initialized module directories. A program that uses TerraformPool must also run under an if __name__ == "__main__": guard, because the pool starts worker processes. See Parallel Execution for a complete, runnable setup.

Cancellation

Each submitted command is tagged with a run id. A future that has not started running is cancelled normally. For a command already executing in a worker process, future.cancel() asks Terraform to stop through its normal interrupt handling β€” the same cooperative cancellation used by AsyncTerraformCommand β€” delivered to the worker process that owns the run. It returns False (mirroring the standard library, which reports a running task as not cancelled), and the command then returns whatever result Terraform produces as it winds down.

future = pool.command("modules/app").apply(auto_approve=True)
# ... later, to interrupt a long-running apply:
future.cancel()
result = future.result()

Usage

Fan one operation across many module directories with map():

from libterraform import TerraformPool

with TerraformPool(max_workers=4) as pool:
    for result in pool.map("validate", ["modules/a", "modules/b"], check=True):
        print(result.value["valid"])

Submit heterogeneous commands and collect their futures. pool.command(cwd) returns a cwd-bound proxy that mirrors TerraformCommand, but each method returns a concurrent.futures.Future:

with TerraformPool(max_workers=4) as pool:
    plan = pool.command("modules/app").plan(check=True)
    version = pool.run("version")

    print(plan.result().retcode)
    print(version.result()[0])

Use the low-level submit() when you want to name the method dynamically:

future = pool.submit("modules/network", "apply", auto_approve=True)
result = future.result()

pool.run() mirrors TerraformCommand.run() and resolves to the (retcode, stdout, stderr) tuple.

libterraform.pool.TerraformPool

Run Terraform commands in parallel across a pool of worker processes.

The pool owns a concurrent.futures.ProcessPoolExecutor; reuse a single pool to amortize the cost of starting workers and loading the shared library. Use it as a context manager, or call shutdown() explicitly.

Cancellation: a future that has not started running is cancelled normally. For a command already executing in a worker process, future.cancel() asks Terraform to stop through its normal interrupt handling and returns False (mirroring the standard library, which reports a running task as not cancelled). The command then returns whatever result Terraform produces as it winds down.

libterraform.pool.TerraformPool.command

command(cwd=None) -> PoolCommand

Return a cwd-bound proxy whose command methods return futures.

libterraform.pool.TerraformPool.submit

submit(cwd, method, /, *args, **kwargs) -> Future

Submit a single command method for cwd and return its future.

Parameters:

Name Type Description Default
cwd

Working directory for the command (passed to TerraformCommand).

required
method

Name of the TerraformCommand method to call, e.g. "validate" or "apply".

required

libterraform.pool.TerraformPool.run

run(
    cmd: CmdType,
    args: Optional[Sequence[str]] = None,
    options: Optional[dict] = None,
    chdir=None,
    check: bool = False,
    json=False,
) -> Future

Mirror TerraformCommand.run(), returning a future instead.

The future resolves to the (retcode, stdout, stderr) tuple.

libterraform.pool.TerraformPool.map

map(method, cwds, *args, **kwargs) -> Iterator

Run method against each directory in cwds in parallel.

Returns an iterator over the results in the order cwds were given, mirroring concurrent.futures.Executor.map(). The same args and kwargs are passed to every command. Iterating re-raises the first command error encountered.

libterraform.pool.TerraformPool.shutdown

shutdown(
    wait: bool = True, *, cancel_futures: bool = False
) -> None

Shut down the underlying executor and worker manager.