Skip to content

Commit

Permalink
feat: expose working dir and tf runner off test resources api when ru…
Browse files Browse the repository at this point in the history
…nning live (#44)
  • Loading branch information
kapilt authored Nov 9, 2021
1 parent 6d3ac3b commit 5f2cec6
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 15 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pytest-terraform"
version = "0.5.3"
version = "0.6.0"
description = "A pytest plugin for using terraform fixtures"
authors = ["Kapil Thangavelu <[email protected]>"]
license = "Apache-2.0"
Expand Down
3 changes: 2 additions & 1 deletion pytest_terraform/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
def pytest_configure(config):
config.addinivalue_line("markers", "terraform: tests using terraform fixtures")

tf.LazyPluginCacheDir.value = cache_dir = config.getoption("dest_tf_plugin")
cache_dir = config.getoption("dest_tf_plugin")
if not os.path.exists(cache_dir):
os.mkdir(cache_dir)
tf.LazyPluginCacheDir.value = os.path.abspath(cache_dir)

tf.LazyModuleDir.value = config.getoption("dest_tf_mod_dir") or config.getini(
"terraform-mod-dir"
Expand Down
49 changes: 36 additions & 13 deletions pytest_terraform/tf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class TerraformRunner(object):
"apply": "apply {input} {color} {state} {approve} {plan}",
"plan": "plan {input} {color} {state} {output}",
"destroy": "destroy {input} {color} {state} {approve}",
"show": "show {color} -json {state_path}",
}

template_defaults = {
Expand Down Expand Up @@ -72,7 +73,7 @@ def apply(self, plan=True):
elif plan:
apply_args = self._get_cmd_args("apply", plan="")
self._run_cmd(apply_args)
return TerraformState.from_file(self.state_path)
return TerraformState.from_file(self.state_path, self)

def plan(self, output=""):
output = output and "-out=%s" % output or ""
Expand All @@ -84,6 +85,13 @@ def init(self):
def destroy(self):
self._run_cmd(self._get_cmd_args("destroy"))

def show(self):
return json.loads(
self._run_cmd(
self._get_cmd_args("show", state_path=self.state_path), output=True
).decode("utf8")
)

def _get_cmd_args(self, cmd_name, tf_bin=None, env=None, **kw):
tf_bin = tf_bin and tf_bin or self.tf_bin
kw.update(self.template_defaults)
Expand All @@ -92,17 +100,21 @@ def _get_cmd_args(self, cmd_name, tf_bin=None, env=None, **kw):
filter(None, self.command_templates[cmd_name].format(**kw).split(" "))
)

def _run_cmd(self, args):
def _run_cmd(self, args, output=False):
env = dict(os.environ)
tf_env = {}
if LazyPluginCacheDir.resolve():
env["TF_PLUGIN_CACHE_DIR"] = LazyPluginCacheDir.resolve()
env["TF_IN_AUTOMATION"] = "yes"
tf_env["TF_PLUGIN_CACHE_DIR"] = LazyPluginCacheDir.resolve()
tf_env["TF_IN_AUTOMATION"] = "yes"
if self.module_dir:
env["TF_DATA_DIR"] = self.work_dir
tf_env["TF_DATA_DIR"] = self.work_dir
cwd = self.module_dir or self.work_dir
print("run cmd", args, file=sys.stderr)
env.update(tf_env)
print("run cmd", args, tf_env, cwd, file=sys.stderr)
run_cmd = subprocess.check_call
run_cmd(args, cwd=cwd, stderr=subprocess.STDOUT, env=env)
if output:
run_cmd = subprocess.check_output
return run_cmd(args, cwd=cwd, stderr=subprocess.STDOUT, env=env)


class TerraformStateJson(UserString):
Expand Down Expand Up @@ -152,10 +164,21 @@ class TerraformState(object):
attributes which contain the key 'name' will also be present.
"""

def __init__(self, resources, outputs):
def __init__(self, resources, outputs, runner=None):
self._runner = runner
self.outputs = outputs
self.resources = resources

@property
def work_dir(self):
if self._runner:
return self._runner.work_dir

@property
def terraform(self):
if self._runner:
return self._runner

def __getitem__(self, k):
v = self.get(k)
if v is None:
Expand Down Expand Up @@ -189,7 +212,7 @@ def get(self, k, default=None):
return default

@classmethod
def from_file(cls, path: str):
def from_file(cls, path: str, runner=None):
"""create TerraformState from a file
File can either be a Terraform Plan state, or a recorded
Expand All @@ -201,17 +224,17 @@ def from_file(cls, path: str):
with open(path) as fh:
state = fh.read()

return cls.from_string(state)
return cls.from_string(state, runner)

@classmethod
def from_string(cls, state: Union[TerraformStateJson, str]):
def from_string(cls, state: Union[TerraformStateJson, str], runner=None):
"""create TerraformState from string
State string can be a bytestring or a TerraformStateJson
string object
"""
resources, outputs = cls.parse_state(state)
return cls(resources, outputs)
return cls(resources, outputs, runner)

def update(self, state: Union[TerraformStateJson, str]):
"""update TerraformState values"""
Expand Down Expand Up @@ -385,7 +408,7 @@ def create(self, request, module_dir):
try:
state = self.runner.apply()
state_json = state.export()
test_api = TerraformTestApi.from_string(state_json)
test_api = TerraformTestApi.from_string(state_json, self.runner)

self.config.hook.pytest_terraform_modify_state(tfstate=state_json)

Expand Down
2 changes: 2 additions & 0 deletions tests/test_terraform.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ def test_tf_runner(testdir, tmpdir):
with open(tmpdir.join("foo.bar")) as fh:
assert fh.read() == "foo!"

assert state.work_dir is not None
assert isinstance(state.terraform.show(), dict)
trunner.destroy()
assert False is tmpdir.join("foo.bar").exists()

Expand Down

0 comments on commit 5f2cec6

Please sign in to comment.