Open lorengordon opened 2 years ago
For now, since we always run apply/destroy in our current usage, I'm gonna use setup(upgrade=True, cleanup_on_exit=False)
... That way the .terraform
directory will always be refreshed, and with a working destroy the tfstate file should always be empty anyway...
I was going to suggest that. If you get a better idea let's see if it can be implemented.
I'm not super familiar with the _finalizer
thing, which I assume is a feature of pytest? Right now, it is only configured in the setup method, and the other methods do not influence it...
We wrap the setup apply and destroy in a fixture:
@pytest.fixture(scope='module')
def output(scenarios_dir, tf_vars, scenario):
print(f'Setup starting for {scenario}')
tf = tftest.TerraformTest(scenario, scenarios_dir)
tf.setup()
try:
tf.apply(tf_vars=tf_vars)
print(f'setup complete for {scenario}')
yield tf.output()
tf.destroy(**{'auto_approve': True}, tf_vars=tf_vars)
except Exception as exc:
print(f'Issue during apply, attempting to clean up {exc}')
tf.destroy(**{'auto_approve': True}, tf_vars=tf_vars)
It isn't perfect, but effectively puts a retry on destroy if a transient error occurs.
Ach, completely forgot to answer this, sorry!
@grahamhar I'm struggling to understand your solution (my fault ofc): setup()
has cleanup_on_exit
defaulting to True
, so cleanup of state files in the finalizer happens anyway?
IMHO a simple way of avoiding the above is of course to pass cleanup_on_exit=False
to setup()
, then trapping the potential exception raised during destroy
as in Graham's example, and cleaning up state manually only if destroy
succeeds.
@ludoo Sorry I probably should have provided more explanation, let me provide a few examples of how I think the approach I suggested helps.
I agree it is probably a good idea to set cleanup_on_exit to False.
@grahamhar With that config, what does pytest report if the apply succeeds, the first destroy fails, and the second destroy succeeds? Is it still a test pass (I would think so...)?
Yes you get a test pass which in our use case is what we want.
If that is not what you want add a pytest.fail to the except block
Just ran an apply/destroy cycle through tftest, where on destroy I ran into a timing error when waiting for a resource to change to the expected state:
Ok, not great, but no big deal, just go into the test directory and re-run destroy... Except, the tfstate file is gone, so can't do that!