diff --git a/README.md b/README.md index 68a6e7a..a9548ac 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,27 @@ python-terraform is a python module provide a wrapper of `terraform` command lin pip install python-terraform ## Usage -####For any terraform command +#### For any terraform command from python_terraform import Terraform t = Terraform() return_code, stdout, stderr = t.(*arguments, **options) + +**Note**: method name same as reserved keyword like `import` won't be accepted by python interpreter, +to be able to call the method, you could call cmd_name by adding `_cmd` after command name, for example, +`import` here could be called by + + from python_terraform import Terraform + t = Terraform() + return_code, stdout, stderr = t.import_cmd(*arguments, **options) + +or just call cmd method directly + + from python_terraform import Terraform + t = Terraform() + return_code, stdout, stderr = t.cmd(, *arguments, **options) -####For any argument +#### For any argument simply pass the string to arguments of the method, for example, terraform apply target_dir @@ -24,7 +38,7 @@ simply pass the string to arguments of the method, for example, terraform import aws_instance.foo i-abcd1234 --> .import('aws_instance.foo', 'i-abcd1234') -####For any options +#### For any options * dash to underscore diff --git a/python_terraform/__init__.py b/python_terraform/__init__.py index 769350e..fe0d3d3 100644 --- a/python_terraform/__init__.py +++ b/python_terraform/__init__.py @@ -33,8 +33,9 @@ class Terraform(object): variables=None, parallelism=None, var_file=None, - terraform_bin_path=None): - """ + terraform_bin_path=None, + is_env_vars_included=True): + """ :param working_dir: the folder of the working folder, if not given, will be current working folder :param targets: list of target @@ -47,7 +48,10 @@ class Terraform(object): :param var_file: passed as value of -var-file option, could be string or list, list stands for multiple -var-file option :param terraform_bin_path: binary path of terraform + :type is_env_vars_included: bool + :param is_env_vars_included: included env variables when calling terraform cmd """ + self.is_env_vars_included = is_env_vars_included self.working_dir = working_dir self.state = state self.targets = [] if targets is None else targets @@ -64,8 +68,11 @@ class Terraform(object): def __getattr__(self, item): def wrapper(*args, **kwargs): + cmd_name = str(item) + if cmd_name.endswith('_cmd'): + cmd_name = cmd_name[:-4] logging.debug('called with %r and %r' % (args, kwargs)) - return self.cmd(item, *args, **kwargs) + return self.cmd(cmd_name, *args, **kwargs) return wrapper @@ -222,9 +229,12 @@ class Terraform(object): working_folder = self.working_dir if self.working_dir else None - p = subprocess.Popen(cmd_string, stdout=stdout, - stderr=stderr, shell=True, - cwd=working_folder) + environ_vars = {} + if self.is_env_vars_included: + environ_vars = os.environ.copy() + + p = subprocess.Popen(cmd_string, stdout=stdout, stderr=stderr, shell=True, + cwd=working_folder, env=environ_vars) out, err = p.communicate() ret_code = p.returncode log.debug('output: {o}'.format(o=out)) diff --git a/test/test_terraform.py b/test/test_terraform.py index eacb781..0a2487d 100644 --- a/test/test_terraform.py +++ b/test/test_terraform.py @@ -1,3 +1,7 @@ +try: + from cStringIO import StringIO # Python 2 +except ImportError: + from io import StringIO from python_terraform import * import pytest import os @@ -6,6 +10,9 @@ import re import shutil logging.basicConfig(level=logging.DEBUG) +root_logger = logging.getLogger() +# ch = logging.StreamHandler(sys.stdout) +# root_logger.addHandler(ch) current_path = os.path.dirname(os.path.realpath(__file__)) STRING_CASES = [ @@ -23,11 +30,20 @@ STRING_CASES = [ ] CMD_CASES = [ - ['method', 'expected_output'], + ['method', 'expected_output', 'expected_ret_code', 'expected_logs'], [ [ lambda x: x.cmd('plan', 'var_to_output', no_color=IsFlagged, var={'test_var': 'test'}) , - "doesn't need to do anything" + "doesn't need to do anything", + 0, + '' + ], + # try import aws instance + [ + lambda x: x.cmd('import', 'aws_instance.foo', 'i-abcd1234', no_color=IsFlagged), + '', + 1, + 'command: terraform import -no-color aws_instance.foo i-abcd1234' ] ] ] @@ -47,6 +63,19 @@ def fmt_test_file(request): return +@pytest.fixture() +def string_logger(request): + log_stream = StringIO() + handler = logging.StreamHandler(log_stream) + root_logger.addHandler(handler) + + def td(): + root_logger.removeHandler(handler) + + request.addfinalizer(td) + return log_stream + + class TestTerraform(object): def teardown_method(self, method): """ teardown any state that was previously setup with a setup_method @@ -73,11 +102,14 @@ class TestTerraform(object): assert s in result @pytest.mark.parametrize(*CMD_CASES) - def test_cmd(self, method, expected_output): + def test_cmd(self, method, expected_output, expected_ret_code, expected_logs, string_logger): tf = Terraform(working_dir=current_path) ret, out, err = method(tf) + logs = str(string_logger.getvalue()) + logs = logs.replace('\n', '') assert expected_output in out - assert ret == 0 + assert expected_ret_code == ret + assert expected_logs in logs @pytest.mark.parametrize( ("folder", "variables", "var_files", "expected_output", "options"), @@ -161,3 +193,10 @@ class TestTerraform(object): tf = Terraform(working_dir=current_path, variables={'test_var': 'test'}) ret, out, err = tf.fmt(diff=True) assert ret == 0 + + def test_import(self, string_logger): + tf = Terraform(working_dir=current_path) + tf.import_cmd('aws_instance.foo', 'i-abc1234', no_color=IsFlagged) + logs = string_logger.getvalue() + print(logs) + assert 'command: terraform import -no-color aws_instance.foo i-abc1234' in logs diff --git a/test/vars_require_input/main.tf b/test/vars_require_input/main.tf index 43e8e65..d3eaed3 100644 --- a/test/vars_require_input/main.tf +++ b/test/vars_require_input/main.tf @@ -10,11 +10,11 @@ variable "list" { variable "map" { default = {} - type = "map" + type = "map" } resource "aws_instance" "bar" { foo = "${var.ami}" bar = "${join(",", var.list)}" baz = "${join(",", keys(var.map))}" -} \ No newline at end of file +}