Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

noskip related additions #314

Merged
merged 2 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ permalink: /
- __behaviour driven development:__ We have BDD for nearly everything, why not for IaC ?
- __portable:__ just install it from `pip` or run it via `docker`. See [Installation](/pages/installation/)
- __pre-deploy:__ it validates your code before it is deployed
- __easy to integrate:__ it can run in your pipeline (or in git hooks) to ensure all deployments are validated.
- __segregation of duty:__ you can keep your tests in a different repository where a separate team is responsible.
- __provider agnostic:__ it works with any provider
- __easy to integrate:__ it can run in your pipeline (or in git hooks) to ensure all deployments are validated
- __segregation of duty:__ you can keep your tests in a different repository where a separate team is responsible
- __why ?:__ why not ?

## Idea
Expand Down
8 changes: 4 additions & 4 deletions docs/pages/Examples/noskip.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ Noskip tag fails the scenario or step if it skips. Using this tag lets us use `G
## Then I must have resource defined
Since `THEN` steps exclusively drill down the resource passed from the previous step, we could not write the `THEN` step below, which checks the existence of something outside of its context.

``` Gherkin
```
Given I have azurerm_postgresql_server defined
Then I must have azurerm_postgresql_configuration defined
```

With `@noskip`, we can:
``` Gherkin
```
@noskip_at_line_3
Scenario: resource A implies resource B
Given I have azurerm_postgresql_server defined
Expand All @@ -28,7 +28,7 @@ Note that the scenario doesn't fail if azurerm_postgresql_server doesn't exist.


## Filtering Then
Since `THEN` steps exlusively drill down, we can't write consecutive `THEN` steps that check the properties of the same resource within ta resource and stay on the same level.
Since `THEN` steps exlusively drill down, we can't write consecutive `THEN` steps that check the properties of the same resource within that resource and stay on the same level.

we would need to write a new scenario if we wanted to check a property that was lost during the "drill"

Expand Down Expand Up @@ -58,7 +58,7 @@ If I have azurerm_postgresql_server
Using `THEN its name bust be log_connections` would drill down to `log_connections` and we wouldn't be able check if the value is on or not.

With `@noskip`, we can:
``` Gherkin
```
@noskip_at_lines_4_5
Scenario Outline: Filtering then
Given I have azurerm_postgresql_server defined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
layout: default
title: Using Tags
nav_order: 7
has_children: false
has_children: true
parent: BDD Reference
---

Expand Down
147 changes: 147 additions & 0 deletions docs/pages/bdd-references/using_tags/using_noskip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
layout: default
title: Noskip Tag
nav_order: 1
has_children: false
parent: Using Tags
---

# Noksip Tag

In Terraform-Compliance, `WHEN` always filters and `THEN` always drills down. However, this might not what we want all the time. With `noskip`, conditions can be forced without having to drill down to their values.

Using `@noskip` fails the scenario if any of the steps skips. Using `@noskip_at_lines_2_3`, will fail if there are skipping steps within the scenario that falls into the lines 2 and 3

## Reference
* Table of Contents
{:toc}

# Examples

## Forcing a specific resource while the resources exists with the same type

Assume we wanted to specifically check `log_checkpoints` existed and is set to on, within a plan where there are many `azurerm_postgresql_configuration` resources.

```
# main.tf

resource "azurerm_postgresql_configuration" "log_checkpoints" {
name = "log_checkpoints"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
value = "on"
}

resource "azurerm_postgresql_configuration" "log_connections" {
name = "log_connections"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
value = "on"
}

# ... (many more azurerm_postgresql_configurations below)
```

To do so, we need to filter to the correct `azurerm_postgresql_configuration`, fail if it doesn't exist, then drill to its `value` to finally check whether it's on or not.

```
@noskip
Scenario: log checkpoints must exist and must be set to on.
Given I have azurerm_postgresql_configuration defined
When its name is log_checkpoints
Then it must have value
Then its value must be on

```


If we used
```
Given I have azurerm_postgresql_configuration defined
When its name is not log_checkpoints
Then it must fail
```
We wouldn't filter to the correct resources, since the `WHEN` step would capture all the configurations that are not `log_checkpoints`.


If we tried the following instead,
```
Given I have azurerm_postgresql_configuration defined
Then its name must be log_checkpoints
```
We would end up drilling to the `name`'s value `log_checkpoints`, which would prevent me from checking fields outside of this scope.

------------------------
## Resource A implies Resource B

`noskip` can be used for simulating implications between resources.

Say we wanted the following to hold: if azurerm_postgresql_server is defined, then azurerm_postgresql_configuration must be defined.
The scenario should skip if there are no `azurerm_postgresql_server` defined but fail if it exists without any `azurerm_postgresql_configuration` defined.
```
@noskip_at_line_4
Scenario: Ensure azurerm_postgresql_configuration is defined if a PostgreSQL Database Server exists.
Given I have azurerm_postgresql_server defined
Given I have azurerm_postgresql_configuration defined # line 4
```

Following also accomplishes the same.

```
@noskip_at_line_5
Scenario: Ensure azurerm_postgresql_configuration is defined if a PostgreSQL Database Server exists.
Given I have azurerm_postgresql_server defined
Given I have any resource defined
When its type is azurerm_postgresql_configuration # line 5
```

------------------------
## Using noskip with scenario outlines

Similar to [Forcing a specific resource while the resources exists with the same type](/pages/bdd-references/using_tags/using_noskip.html#forcing-a-specific-resource-while-the-resources-exists-with-the-same-type), we have a large list of `azurerm_postgresql_configuration`s. This time, we would like to check values of each configuration.

```
# main.tf

resource "azurerm_postgresql_configuration" "log_checkpoints" {
name = "log_checkpoints"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
value = "on"
}

resource "azurerm_postgresql_configuration" "connection_throttling" {
name = "connection_throttling"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
value = "off"
}

resource "azurerm_postgresql_configuration" "log_retention_days" {
name = "log_retention_days"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
value = "4"
}

# ... (many more azurerm_postgresql_configurations below)
```


```
@noskip_at_lines_22_23_24
Scenario Outline: Scenario for issue #291
Given I have azurerm_postgresql_configuration defined
When its name is <config_name>
Then it must have value
Then its value must match the "<value>" regex

Examples:
| config_name | value |
| log_checkpoints | on | # line 22
| connection_throttling | off | # line 23
| log_retention_days | ^([4-9]\|\d{2,})$| # line 24
# ...
```

Which is equivalent to only using `@noskip`