From ebf595a2c11a4266b085e10f7319040e988f8da5 Mon Sep 17 00:00:00 2001 From: Kaan Katircioglu Date: Tue, 7 Jul 2020 13:40:11 +0300 Subject: [PATCH] noskip related additions --- docs/index.markdown | 5 +- docs/pages/Examples/noskip.md | 8 +- .../{using_tags.md => using_tags/index.md} | 2 +- .../bdd-references/using_tags/using_noskip.md | 147 ++++++++++++++++++ 4 files changed, 155 insertions(+), 7 deletions(-) rename docs/pages/bdd-references/{using_tags.md => using_tags/index.md} (98%) create mode 100644 docs/pages/bdd-references/using_tags/using_noskip.md diff --git a/docs/index.markdown b/docs/index.markdown index a36176e0..bc434345 100644 --- a/docs/index.markdown +++ b/docs/index.markdown @@ -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 diff --git a/docs/pages/Examples/noskip.md b/docs/pages/Examples/noskip.md index 06fbea29..3820c22c 100644 --- a/docs/pages/Examples/noskip.md +++ b/docs/pages/Examples/noskip.md @@ -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 @@ -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" @@ -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 diff --git a/docs/pages/bdd-references/using_tags.md b/docs/pages/bdd-references/using_tags/index.md similarity index 98% rename from docs/pages/bdd-references/using_tags.md rename to docs/pages/bdd-references/using_tags/index.md index 60524007..d53011f2 100644 --- a/docs/pages/bdd-references/using_tags.md +++ b/docs/pages/bdd-references/using_tags/index.md @@ -2,7 +2,7 @@ layout: default title: Using Tags nav_order: 7 -has_children: false +has_children: true parent: BDD Reference --- diff --git a/docs/pages/bdd-references/using_tags/using_noskip.md b/docs/pages/bdd-references/using_tags/using_noskip.md new file mode 100644 index 00000000..9cfd00c2 --- /dev/null +++ b/docs/pages/bdd-references/using_tags/using_noskip.md @@ -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 + Then it must have value + Then its value must match the "" 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`