terraform: do not immediately fail if a lock is held

terraform will wait 15 minutes to see if the state
is released before returning an error

fixes: #16
This commit is contained in:
Iain Learmonth 2022-05-11 14:13:02 +01:00
parent a2abaabd12
commit a7432a6b96

View file

@ -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:
"""