Skip to content

Commit

Permalink
fix: initialise provider cache in same process as running TF
Browse files Browse the repository at this point in the history
This ensures that they're executed on the same machine.
As separate processes, a remote execution might execute these on different machines.
As well, it's possible that locally the mkdir is cached even  if it needs to be run again
  • Loading branch information
lilatomic committed Jan 26, 2025
1 parent d97a1be commit d26e69e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 15 deletions.
13 changes: 11 additions & 2 deletions src/python/pants/backend/terraform/goals/deploy_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import json
import shlex

import pytest

Expand All @@ -16,6 +17,14 @@
standard_deployment = standard_deployment


def _extract_terraform_argv_from_script(script_argv) -> tuple[str, ...]:
"""Extract the argv of the invocation of Terraform from its launcher script."""
script = script_argv[2]
tf_invocation = script.split("&&")
argv = shlex.split(tf_invocation[-1])
return tuple(argv)


def test_run_terraform_deploy(rule_runner: RuleRunner, standard_deployment, tmpdir) -> None:
"""Test end-to-end running of a deployment."""
rule_runner.write_files(standard_deployment.files)
Expand Down Expand Up @@ -44,7 +53,7 @@ def test_deploy_terraform_forwards_args(rule_runner: RuleRunner, standard_deploy
deploy_process = rule_runner.request(DeployProcess, [field_set])
assert deploy_process.process

argv = deploy_process.process.process.argv
argv = _extract_terraform_argv_from_script(deploy_process.process.process.argv)

assert "-chdir=src/tf" in argv, "Did not find expected -chdir"
assert "-var-file=stg.tfvars" in argv, "Did not find expected -var-file"
Expand All @@ -70,7 +79,7 @@ def test_deploy_terraform_adheres_to_dry_run_flag(
deploy_process = rule_runner.request(DeployProcess, [field_set])
assert deploy_process.process

argv = deploy_process.process.process.argv
argv = _extract_terraform_argv_from_script(deploy_process.process.process.argv)

assert action in argv, f"Expected {action} in argv"
assert not_action not in argv, f"Did not expect {not_action} in argv"
Expand Down
35 changes: 22 additions & 13 deletions src/python/pants/backend/terraform/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import shlex
from dataclasses import dataclass
from pathlib import Path
from typing import Tuple
from typing import Iterable, Tuple

from pants.core.goals.resolves import ExportableTool
from pants.core.util_rules import external_tool
Expand All @@ -29,12 +29,12 @@
ExternalToolRequest,
TemplatedExternalTool,
)
from pants.core.util_rules.system_binaries import MkdirBinary
from pants.core.util_rules.system_binaries import BashBinary, MkdirBinary
from pants.engine.env_vars import EXTRA_ENV_VARS_USAGE_HELP, EnvironmentVars, EnvironmentVarsRequest
from pants.engine.fs import EMPTY_DIGEST, Digest
from pants.engine.internals.selectors import Get
from pants.engine.platform import Platform
from pants.engine.process import FallibleProcessResult, Process
from pants.engine.process import Process
from pants.engine.rules import collect_rules, rule
from pants.engine.unions import UnionRule
from pants.option.option_types import ArgsListOption, BoolOption, StrListOption
Expand Down Expand Up @@ -418,10 +418,17 @@ class TerraformProcess:
chdir: str = "." # directory for terraform's `-chdir` argument


def _make_launcher_script(bash: BashBinary, commands: Iterable[Iterable[str]]) -> tuple[str, ...]:
"""Assemble several command invocations into an inline launcher script, suitable for passing as
`Process(argv=(bash.path, "-c", script), ...)`"""
return (bash.path, "-c", " && ".join([shlex.join(command) for command in commands]))


@rule
async def setup_terraform_process(
request: TerraformProcess,
terraform: TerraformTool,
bash: BashBinary,
mkdir: MkdirBinary,
platform: Platform,
) -> Process:
Expand Down Expand Up @@ -453,18 +460,20 @@ def prepend_paths(paths: Tuple[str, ...]) -> Tuple[str, ...]:
return tuple((Path(request.chdir) / path).as_posix() for path in paths)

# Initialise the Terraform provider cache, since Terraform expects the directory to already exist.
await Get(
FallibleProcessResult,
Process(
argv=[mkdir.path, "-p", tf_plugin_cache_dir],
append_only_caches=terraform.append_only_caches,
description="initialise Terraform plugin cache dir",
level=LogLevel.DEBUG,
),
)
initialize_provider_cache_cmd = (mkdir.path, "-p", tf_plugin_cache_dir)
run_terraform_cmd = (
"__terraform/terraform",
f"-chdir={shlex.quote(request.chdir)}",
) + request.args

return Process(
argv=("__terraform/terraform", f"-chdir={shlex.quote(request.chdir)}") + request.args,
argv=_make_launcher_script(
bash,
(
initialize_provider_cache_cmd,
run_terraform_cmd,
),
),
input_digest=request.input_digest,
immutable_input_digests=immutable_input_digests,
output_files=prepend_paths(request.output_files),
Expand Down

0 comments on commit d26e69e

Please sign in to comment.