From 38222a42f5b1b974b6e560d48d4e906d3573446e Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 15:39:09 +0800 Subject: [PATCH 1/7] fix terraform import cmd is a reseved word of python --- README.md | 18 +++++++++++++++--- test/test_terraform.py | 22 ++++++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 68a6e7a..5a7a0f7 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,25 @@ 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` could be called directly by using the following + + from python_terraform import Terraform + t = Terraform() + return_code, stdout, stderr = t._method(*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 +36,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/test/test_terraform.py b/test/test_terraform.py index eacb781..961c155 100644 --- a/test/test_terraform.py +++ b/test/test_terraform.py @@ -6,6 +6,8 @@ import re import shutil logging.basicConfig(level=logging.DEBUG) +ch = logging.StreamHandler(sys.stdout) +logging.getLogger().addHandler(ch) current_path = os.path.dirname(os.path.realpath(__file__)) STRING_CASES = [ @@ -23,11 +25,18 @@ STRING_CASES = [ ] CMD_CASES = [ - ['method', 'expected_output'], + ['method', 'expected_output', 'expected_ret_code'], [ [ 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), + 'Import complete!', + 1 ] ] ] @@ -73,11 +82,11 @@ 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): tf = Terraform(working_dir=current_path) ret, out, err = method(tf) assert expected_output in out - assert ret == 0 + assert expected_ret_code == ret @pytest.mark.parametrize( ("folder", "variables", "var_files", "expected_output", "options"), @@ -161,3 +170,8 @@ 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): + tf = Terraform(working_dir=current_path) + tf.cmd('import', 'aws_instance.foo', 'i-abc123') + assert False From 733b8006c51b78397498cc00ac31ba8528643fe5 Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 15:48:28 +0800 Subject: [PATCH 2/7] adding readme and test --- README.md | 5 +++-- python_terraform/__init__.py | 5 ++++- test/test_terraform.py | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5a7a0f7..86a4d92 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,12 @@ python-terraform is a python module provide a wrapper of `terraform` command lin t = Terraform() return_code, stdout, stderr = t.(*arguments, **options) -**Note**: method name same as reserved keyword like `import` could be called directly by using the following +**Note**: method name same as reserved keyword like `import` could be called directly +by adding `_cmd` after command name from python_terraform import Terraform t = Terraform() - return_code, stdout, stderr = t._method(*arguments, **options) + return_code, stdout, stderr = t._cmd(*arguments, **options) or just call cmd method directly diff --git a/python_terraform/__init__.py b/python_terraform/__init__.py index 769350e..8eee5ab 100644 --- a/python_terraform/__init__.py +++ b/python_terraform/__init__.py @@ -64,8 +64,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 diff --git a/test/test_terraform.py b/test/test_terraform.py index 961c155..6ff8e3b 100644 --- a/test/test_terraform.py +++ b/test/test_terraform.py @@ -173,5 +173,6 @@ class TestTerraform(object): def test_import(self): tf = Terraform(working_dir=current_path) - tf.cmd('import', 'aws_instance.foo', 'i-abc123') - assert False + ret, out, err = tf.import_cmd('aws_instance.foo', 'i-abc1234', no_color=IsFlagged) + assert 'Import complete!' in out + assert 1 == ret From 3f18abb40e34149e3ef782ca435e2494d2800b3f Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 16:05:48 +0800 Subject: [PATCH 3/7] fix tests with given environment variables --- python_terraform/__init__.py | 17 ++++++++++++----- test/test_terraform.py | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/python_terraform/__init__.py b/python_terraform/__init__.py index 8eee5ab..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 @@ -225,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 6ff8e3b..727fc80 100644 --- a/test/test_terraform.py +++ b/test/test_terraform.py @@ -83,6 +83,7 @@ class TestTerraform(object): @pytest.mark.parametrize(*CMD_CASES) def test_cmd(self, method, expected_output, expected_ret_code): + os.environ['AWS_DEFAULT_REGION'] = "us-west-1" tf = Terraform(working_dir=current_path) ret, out, err = method(tf) assert expected_output in out @@ -172,6 +173,7 @@ class TestTerraform(object): assert ret == 0 def test_import(self): + os.environ['AWS_DEFAULT_REGION'] = "us-west-1" tf = Terraform(working_dir=current_path) ret, out, err = tf.import_cmd('aws_instance.foo', 'i-abc1234', no_color=IsFlagged) assert 'Import complete!' in out From a6d4ee0316464ed8727766a7c2d3d800a39a9d91 Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 16:09:28 +0800 Subject: [PATCH 4/7] refactor readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 86a4d92..a9548ac 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,13 @@ python-terraform is a python module provide a wrapper of `terraform` command lin t = Terraform() return_code, stdout, stderr = t.(*arguments, **options) -**Note**: method name same as reserved keyword like `import` could be called directly -by adding `_cmd` after command name +**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._cmd(*arguments, **options) + return_code, stdout, stderr = t.import_cmd(*arguments, **options) or just call cmd method directly From b922750de07ab5c2865c599288aa591560c46f5c Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 17:47:36 +0800 Subject: [PATCH 5/7] use log to test --- test/import_test/test.tf | 7 +++++ test/test_terraform.py | 50 ++++++++++++++++++++++++--------- test/vars_require_input/main.tf | 4 +-- 3 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 test/import_test/test.tf diff --git a/test/import_test/test.tf b/test/import_test/test.tf new file mode 100644 index 0000000..9da2429 --- /dev/null +++ b/test/import_test/test.tf @@ -0,0 +1,7 @@ +provider "archive" {} + +data "archive_file" "init" { + type = "zip" + source_file = "${path.module}/init.tpl" + output_path = "${path.module}/init.zip" +} diff --git a/test/test_terraform.py b/test/test_terraform.py index 727fc80..1a1dba5 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,8 +10,9 @@ import re import shutil logging.basicConfig(level=logging.DEBUG) -ch = logging.StreamHandler(sys.stdout) -logging.getLogger().addHandler(ch) +root_logger = logging.getLogger() +# ch = logging.StreamHandler(sys.stdout) +# root_logger.addHandler(ch) current_path = os.path.dirname(os.path.realpath(__file__)) STRING_CASES = [ @@ -25,18 +30,20 @@ STRING_CASES = [ ] CMD_CASES = [ - ['method', 'expected_output', 'expected_ret_code'], + ['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", - 0 + 0, + '' ], # try import aws instance [ lambda x: x.cmd('import', 'aws_instance.foo', 'i-abcd1234', no_color=IsFlagged), - 'Import complete!', - 1 + '', + 1, + 'command: terraform import -no-color aws_instance.foo i-abcd1234' ] ] ] @@ -56,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 @@ -82,12 +102,14 @@ class TestTerraform(object): assert s in result @pytest.mark.parametrize(*CMD_CASES) - def test_cmd(self, method, expected_output, expected_ret_code): - os.environ['AWS_DEFAULT_REGION'] = "us-west-1" + 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 expected_ret_code == ret + assert expected_logs in logs @pytest.mark.parametrize( ("folder", "variables", "var_files", "expected_output", "options"), @@ -172,9 +194,9 @@ class TestTerraform(object): ret, out, err = tf.fmt(diff=True) assert ret == 0 - def test_import(self): - os.environ['AWS_DEFAULT_REGION'] = "us-west-1" - tf = Terraform(working_dir=current_path) - ret, out, err = tf.import_cmd('aws_instance.foo', 'i-abc1234', no_color=IsFlagged) - assert 'Import complete!' in out - assert 1 == ret + def test_import(self, string_logger): + tf = Terraform(working_dir=os.path.join(current_path, 'import_test')) + 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 +} From cc24b9d3e1d2c96d5659f4f30544bdcc9f22eb15 Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 17:48:02 +0800 Subject: [PATCH 6/7] remove file --- test/import_test/test.tf | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 test/import_test/test.tf diff --git a/test/import_test/test.tf b/test/import_test/test.tf deleted file mode 100644 index 9da2429..0000000 --- a/test/import_test/test.tf +++ /dev/null @@ -1,7 +0,0 @@ -provider "archive" {} - -data "archive_file" "init" { - type = "zip" - source_file = "${path.module}/init.tpl" - output_path = "${path.module}/init.zip" -} From 4709bd069a0420308ffb3ff3a8fc5e1d772d138a Mon Sep 17 00:00:00 2001 From: beelit94 Date: Tue, 9 May 2017 17:51:52 +0800 Subject: [PATCH 7/7] fix test code --- test/test_terraform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_terraform.py b/test/test_terraform.py index 1a1dba5..0a2487d 100644 --- a/test/test_terraform.py +++ b/test/test_terraform.py @@ -195,7 +195,7 @@ class TestTerraform(object): assert ret == 0 def test_import(self, string_logger): - tf = Terraform(working_dir=os.path.join(current_path, 'import_test')) + tf = Terraform(working_dir=current_path) tf.import_cmd('aws_instance.foo', 'i-abc1234', no_color=IsFlagged) logs = string_logger.getvalue() print(logs)