Skip to content

Commit

Permalink
⚡ Make terraform deploy forward abort to terraform
Browse files Browse the repository at this point in the history
  • Loading branch information
simonrainerson authored and abbec committed Mar 21, 2024
1 parent dbe1a6f commit 802eea3
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- Terraform deploy now sends sigint to terraform on ctrl+C, giving it a chance
to shut down a little more gracefully.

## [4.1.0] - 2024-02-16

### Added
Expand Down
1 change: 0 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,3 @@
}
);
}

2 changes: 1 addition & 1 deletion terraform/deployment/deployer.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
python3.pkgs.buildPythonApplication
{
name = "terraform-deployer";
version = "2.0.0";
version = "2.0.1";
src = ./.;
}
40 changes: 37 additions & 3 deletions terraform/deployment/terraform.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@
import os
import pathlib
import shutil
import signal
import subprocess
import sys
import time
import types
import typing

"""Have we received an abort signal (SIGINT/SIGTERM)?"""
abort_requested: bool = False

def _setup_sources(source: pathlib.Path) -> None:
shutil.copytree(src=source, dst=os.getcwd(), dirs_exist_ok=True)
Expand All @@ -19,10 +24,36 @@ def _setup_sources(source: pathlib.Path) -> None:
os.chmod(path=os.path.join(root, content), mode=0o755)


def _handle_termination(signum: int, frame: typing.Optional[types.FrameType]):
# Make sure we always wait for terraform to exit
# so it can remove lock files and exit cleanly.
print(f"Abort requested ({signal.strsignal(signum)}).")
global abort_requested
abort_requested = True


def _run_terraform(command: str, args: typing.List[str] = None) -> None:
subprocess.check_call(
["terraform", command, "-lock-timeout=300s", "-input=false"] + (args or []),
)
global abort_requested
if abort_requested:
raise subprocess.CalledProcessError(1, "did-not-start-terraform")

aborted = False
cmd = ["terraform", command, "-lock-timeout=300s", "-input=false"] + (args or [])
with subprocess.Popen(cmd, start_new_session=True) as process:
while process.poll() is None:
if abort_requested:
os.killpg(os.getpgid(process.pid), signal.SIGINT)
abort_requested = False
aborted = True
print("Waiting for terraform to exit")

time.sleep(0.25)

# terraform returns 0 when aborted via SIGINT
if aborted:
raise subprocess.CalledProcessError(-signal.SIGINT, " ".join(cmd))
elif process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, " ".join(cmd))


def apply(args: argparse.Namespace) -> None:
Expand Down Expand Up @@ -71,6 +102,9 @@ def main() -> None:

args = parser.parse_args()

signal.signal(signal.SIGTERM, _handle_termination)
signal.signal(signal.SIGINT, _handle_termination)

try:
if args.subcommand is None:
apply(args)
Expand Down

0 comments on commit 802eea3

Please sign in to comment.