diff --git a/app/terraform/terraform.py b/app/terraform/terraform.py index 4f063c2..188396c 100644 --- a/app/terraform/terraform.py +++ b/app/terraform/terraform.py @@ -26,26 +26,40 @@ class TerraformAutomation(BaseAutomation): self.tf_posthook(prehook_result=prehook_result) return True if returncode == 0 else False, logs - def tf_apply(self, refresh: bool = True, parallelism: Optional[int] = None) -> Tuple[int, List[Dict[str, Any]]]: + def tf_apply(self, *, + refresh: bool = True, + parallelism: Optional[int] = None, + lock_timeout: int = 15) -> Tuple[int, List[Dict[str, Any]]]: if not parallelism: parallelism = self.parallelism tf = subprocess.run( - ['terraform', 'apply', f'-refresh={str(refresh).lower()}', '-auto-approve', - f'-parallelism={str(parallelism)}', '-json'], + ['terraform', + 'apply', + '-auto-approve', + '-json', + f'-refresh={str(refresh).lower()}', + f'-parallelism={str(parallelism)}', + f'-lock-timeout={str(lock_timeout)}m', + ], cwd=self.working_directory(), stdout=subprocess.PIPE) logs = [] for line in tf.stdout.decode('utf-8').split('\n'): if line.strip(): logs.append(json.loads(line)) - return tf.returncode, logs + return tf.returncode, str(logs) def tf_generate(self): raise NotImplementedError() - def tf_init(self): + def tf_init(self, *, + lock_timeout: int = 15): + # The init command does not support JSON output subprocess.run( - ['terraform', 'init'], + ['terraform', + 'init', + f'-lock-timeout={str(lock_timeout)}m', + ], cwd=self.working_directory()) def tf_output(self) -> Dict[str, Any]: @@ -55,13 +69,24 @@ class TerraformAutomation(BaseAutomation): stdout=subprocess.PIPE) return json.loads(tf.stdout) - def tf_plan(self): + def tf_plan(self, *, + refresh: bool = True, + parallelism: Optional[int] = None, + lock_timeout: int = 15): tf = subprocess.run( - ['terraform', 'plan'], + ['terraform', + 'plan', + '-json', + f'-refresh={str(refresh).lower()}', + f'-parallelism={str(parallelism)}', + f'-lock-timeout={str(lock_timeout)}m', + ], cwd=self.working_directory()) - # TODO: looks like terraform has a -json output mode here but it's - # more like JSON-ND, task is to figure out how to yield those records - # as plan runs, the same is probably also true for apply + logs = [] + for line in tf.stdout.decode('utf-8').split('\n'): + if line.strip(): + logs.append(json.loads(line)) + return tf.returncode, str(logs) def tf_posthook(self, *, prehook_result: Any = None) -> None: """