Skip to content

Commit

Permalink
Added support for tags in BDD feature(s)/scenario(s). #191
Browse files Browse the repository at this point in the history
  • Loading branch information
eerkunt committed Feb 3, 2020
1 parent acb8396 commit 6571a0c
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 4 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# CHANGELOG

### 1.1.5 (2020-02-03)
* Added tags support on BDD feature files. As the first use case you can use @warning tag on top of a scenario for making it not failing. ([docs](https://terraform-compliance.com/pages/bdd-references/using_tags.html)) ([#191](https://github.com/eerkunt/terraform-compliance/issues/191))

## 1.1.4 (2020-02-03)
* Added a new environment variable `TFC_ERROR` to change the name of the default `Failure` error message. ([docs](https://terraform-compliance.com/pages/usage/environment_variables.html)) ([#191](https://github.com/eerkunt/terraform-compliance/issues/191))

### 1.1.2 (2020-02-01)
## 1.1.3 (2020-02-01)
* Cosmetic and some dependency fixes.

### 1.1.2 (2020-02-01)
Expand Down
37 changes: 37 additions & 0 deletions docs/pages/bdd-references/using_tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
layout: default
title: Using Tags
nav_order: 7
has_children: false
parent: BDD Reference
---

# Using Tags

`terraform-compliance` supports using tags within the BDD feature files.

An example tag usage :
```gherkin
Feature: My test feature
@nofail
Scenario: #1 Ensure my specific s3 buckets are private but dont fail
Given I have aws_s3_bucket defined
Then it must contain acl
And its value must be private
Scenario: #2 Some other scenario that may fail
Given ....
...
```

in this case, `terraform-compliance` will execute both scenarios but will never
fail Scenario #1 due to `@nofail` tag. These tags can also be use on top of the
Features instead of Scenarios. Default `Failure :` error heading will also be changed
with the tag name. It will be `nofail :` in the example above.

## Supported Tags

| Tag Name(s) | Description |
|:-----------:|:------------|
| `warning`, `no-failure`, `no-fail`, `info`, `nofailure`, `nofail`, `dontfail` | Do not fail the scenario |
1 change: 1 addition & 0 deletions terraform_compliance/common/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Defaults(object):

def __init__(self):
self.interactive_mode = self.detect_term()
self.no_failure_tags = ['warning', 'no-failure', 'no-fail', 'info', 'nofailure', 'nofail', 'dontfail']

if '--no-ansi' in sys.argv or not sys.stdout.isatty():
self.skip_colour = \
Expand Down
15 changes: 12 additions & 3 deletions terraform_compliance/common/error_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,19 @@ def __init__(self, step_obj, message, exception=Failure):
self.exit_on_failure = literal_eval(world.config.user_data['exit_on_failure'])
self.no_failure = literal_eval(world.config.user_data['no_failure'])
_TFC_ERROR = os.environ.get('TFC_ERROR')
self.exception = exception if _TFC_ERROR is None else type(_TFC_ERROR, (Exception, ), {})
self.exception_name = exception.__name__ if _TFC_ERROR is None else _TFC_ERROR
self.step_obj = step_obj

if step_obj.context.no_failure:
self.exception = type(step_obj.context.failure_class, (Exception, ), {})
self.exception_name = step_obj.context.failure_class
self.no_failure = True
elif _TFC_ERROR is None:
self.exception = exception
self.exception_name = exception.__name__
else:
self.exception = type(_TFC_ERROR, (Exception, ), {})
self.exception_name = _TFC_ERROR

self.step_obj = step_obj
self._process()

def _process(self):
Expand Down
4 changes: 4 additions & 0 deletions terraform_compliance/steps/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from terraform_compliance.common.error_handling import Error
from terraform_compliance.main import Step
from terraform_compliance.common.defaults import Defaults
from terraform_compliance.common.bdd_tags import look_for_bdd_tags

# TODO: Figure out how the IAM policies/statements shown in the plan.out
# TODO: Implement an IAM Compliance via https://github.com/Netflix-Skunkworks/policyuniverse
Expand Down Expand Up @@ -48,6 +49,9 @@ def i_have_name_section_configured(_step_obj, name, type_name='resource', _terra
if type_name.endswith('s'):
type_name = type_name[:-1]

# Process the tags
_step_obj = look_for_bdd_tags(_step_obj)

if name in ('a resource', 'any resource', 'resources'):
_step_obj.context.type = type_name
_step_obj.context.name = name
Expand Down
8 changes: 8 additions & 0 deletions tests/mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ def __init__(self, no_init=None):
self.context_sensitive_sentence = self.sentence
self.state = 'passed'
self.id = 0
self.all_tags = [MockedTags()]

if no_init is None:
self.parent = MockedParentStep()
Expand All @@ -269,6 +270,8 @@ def __init__(self):
self.name = ''
self.addresses = 'aws_db_instance.something'
self.property_name = 'mocked_property'
self.no_failure = False
self.failure_class = 'no_name'


class MockedWorld(object):
Expand Down Expand Up @@ -412,3 +415,8 @@ def __init__(self):
class MockedTerraformResource(object):
def __init__(self):
self.config = {"count": 2}


class MockedTags(object):
def __init__(self, name='no_name'):
self.name = name

0 comments on commit 6571a0c

Please sign in to comment.