From 2cd74823b1f06371aa5448ff9e85acb3b0558b3c Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Thu, 17 Nov 2022 19:15:42 +0100 Subject: [PATCH] Generate files based on readme contents --- modules/endpoints/README.md | 12 ++++++- modules/folder/README.md | 6 ++-- modules/net-vpc/README.md | 4 +-- modules/organization/README.md | 12 +++---- modules/project/README.md | 6 ++-- .../configs/custom-constraints/dataproc.yaml | 11 ------- .../configs/custom-constraints/gke.yaml | 19 ----------- tests/examples/configs/endpoints/openapi.yaml | 1 - .../configs/firewall-policies/cidrs.yaml | 5 --- .../configs/firewall-policies/rules.yaml | 24 -------------- .../configs/firewall/cidr_template.yaml | 6 ---- .../firewall/rules/load_balancers.yaml | 11 ------- .../configs/org-policies/boolean.yaml | 13 -------- tests/examples/configs/org-policies/list.yaml | 27 ---------------- .../examples/configs/subnets/subnet-name.yaml | 15 --------- tests/examples/conftest.py | 23 +++++++++++-- tests/examples/test_plan.py | 32 ++++++++----------- 17 files changed, 58 insertions(+), 169 deletions(-) delete mode 100644 tests/examples/configs/custom-constraints/dataproc.yaml delete mode 100644 tests/examples/configs/custom-constraints/gke.yaml delete mode 100644 tests/examples/configs/endpoints/openapi.yaml delete mode 100644 tests/examples/configs/firewall-policies/cidrs.yaml delete mode 100644 tests/examples/configs/firewall-policies/rules.yaml delete mode 100644 tests/examples/configs/firewall/cidr_template.yaml delete mode 100644 tests/examples/configs/firewall/rules/load_balancers.yaml delete mode 100644 tests/examples/configs/org-policies/boolean.yaml delete mode 100644 tests/examples/configs/org-policies/list.yaml delete mode 100644 tests/examples/configs/subnets/subnet-name.yaml diff --git a/modules/endpoints/README.md b/modules/endpoints/README.md index a000e2b051..4e6fd2eb94 100644 --- a/modules/endpoints/README.md +++ b/modules/endpoints/README.md @@ -18,7 +18,17 @@ module "endpoint" { ] } } -# tftest modules=1 resources=2 +# tftest modules=1 resources=2 files=openapi +``` + +```yaml +# tftest file openapi configs/endpoints/openapi.yaml +swagger: "2.0" +info: + description: "A simple Google Cloud Endpoints API example." + title: "Endpoints Example" + version: "1.0.0" +host: "echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog" ``` [Here](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/openapi.yaml) you can find an example of an openapi.yaml file. Once created the endpoint, remember to activate the service at project level. diff --git a/modules/folder/README.md b/modules/folder/README.md index 71cf3e084a..5120d24673 100644 --- a/modules/folder/README.md +++ b/modules/folder/README.md @@ -97,11 +97,11 @@ module "folder" { factory-policy = module.folder.firewall_policy_id["factory"] } } -# tftest modules=1 resources=5 +# tftest modules=1 resources=5 files=cidrs,rules ``` ```yaml -# tftest file configs/firewall-policies/cidrs.yaml +# tftest file cidrs configs/firewall-policies/cidrs.yaml rfc1918: - 10.0.0.0/8 - 172.16.0.0/12 @@ -109,7 +109,7 @@ rfc1918: ``` ```yaml -# tftest file configs/firewall-policies/rules.yaml +# tftest file rules configs/firewall-policies/rules.yaml allow-admins: description: Access from the admin subnet to all subnets direction: INGRESS diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md index 6b08c3b081..b596940623 100644 --- a/modules/net-vpc/README.md +++ b/modules/net-vpc/README.md @@ -233,11 +233,11 @@ module "vpc" { name = "my-network" data_folder = "config/subnets" } -# tftest modules=1 resources=1 +# tftest modules=1 resources=1 file=subnets ``` ```yaml -# ./config/subnets/subnet-name.yaml +# tftest file subnets ./config/subnets/subnet-name.yaml region: europe-west1 description: Sample description ip_cidr_range: 10.0.0.0/24 diff --git a/modules/organization/README.md b/modules/organization/README.md index f60413f26e..a716e665b7 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -139,11 +139,11 @@ module "org" { org_policy_custom_constraints_data_path = "configs/custom-constraints" } -# tftest modules=1 resources=3 +# tftest modules=1 resources=3 files=gke,dataproc ``` ```yaml -# tftest file configs/custom-constraints/gke.yaml +# tftest file gke configs/custom-constraints/gke.yaml custom.gkeEnableLogging: resource_types: - container.googleapis.com/Cluster @@ -165,7 +165,7 @@ custom.gkeEnableAutoUpgrade: ``` ```yaml -# tftest file configs/custom-constraints/dataproc.yaml +# tftest file dataproc configs/custom-constraints/dataproc.yaml custom.dataprocNoMoreThan10Workers: resource_types: - dataproc.googleapis.com/Cluster @@ -234,11 +234,11 @@ module "org" { factory-policy = module.org.firewall_policy_id["factory"] } } -# tftest modules=1 resources=4 +# tftest modules=1 resources=4 files=cidrs,rules ``` ```yaml -# tftest file configs/firewall-policies/cidrs.yaml +# tftest file cidrs configs/firewall-policies/cidrs.yaml rfc1918: - 10.0.0.0/8 - 172.16.0.0/12 @@ -246,7 +246,7 @@ rfc1918: ``` ```yaml -# tftest file configs/firewall-policies/rules.yaml +# tftest file rules configs/firewall-policies/rules.yaml allow-admins: description: Access from the admin subnet to all subnets direction: INGRESS diff --git a/modules/project/README.md b/modules/project/README.md index 53ab731db6..b6fb3881cb 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -226,11 +226,11 @@ module "folder" { name = "Folder name" org_policies_data_path = "configs/org-policies/" } -# tftest modules=1 resources=6 +# tftest modules=1 resources=6 files=boolean,list ``` ```yaml -# tftest file configs/org-policies/boolean.yaml +# tftest file boolean configs/org-policies/boolean.yaml iam.disableServiceAccountKeyCreation: enforce: true @@ -246,7 +246,7 @@ iam.disableServiceAccountKeyUpload: ``` ```yaml -# tftest file configs/org-policies/list.yaml +# tftest file list configs/org-policies/list.yaml compute.vmExternalIpAccess: deny: all: true diff --git a/tests/examples/configs/custom-constraints/dataproc.yaml b/tests/examples/configs/custom-constraints/dataproc.yaml deleted file mode 100644 index 0aa55484ff..0000000000 --- a/tests/examples/configs/custom-constraints/dataproc.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# skip boilerplate check -custom.dataprocNoMoreThan10Workers: - resource_types: - - dataproc.googleapis.com/Cluster - method_types: - - CREATE - - UPDATE - condition: resource.config.workerConfig.numInstances + resource.config.secondaryWorkerConfig.numInstances > 10 - action_type: DENY - display_name: Total number of worker instances cannot be larger than 10 - description: Cluster cannot have more than 10 workers, including primary and secondary workers. diff --git a/tests/examples/configs/custom-constraints/gke.yaml b/tests/examples/configs/custom-constraints/gke.yaml deleted file mode 100644 index c47c41e32d..0000000000 --- a/tests/examples/configs/custom-constraints/gke.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# skip boilerplate check -custom.gkeEnableLogging: - resource_types: - - container.googleapis.com/Cluster - method_types: - - CREATE - - UPDATE - condition: resource.loggingService == "none" - action_type: DENY - display_name: Do not disable Cloud Logging -custom.gkeEnableAutoUpgrade: - resource_types: - - container.googleapis.com/NodePool - method_types: - - CREATE - condition: resource.management.autoUpgrade == true - action_type: ALLOW - display_name: Enable node auto-upgrade - description: All node pools must have node auto-upgrade enabled. diff --git a/tests/examples/configs/endpoints/openapi.yaml b/tests/examples/configs/endpoints/openapi.yaml deleted file mode 100644 index 6f848aa990..0000000000 --- a/tests/examples/configs/endpoints/openapi.yaml +++ /dev/null @@ -1 +0,0 @@ -# skip boilerplate check diff --git a/tests/examples/configs/firewall-policies/cidrs.yaml b/tests/examples/configs/firewall-policies/cidrs.yaml deleted file mode 100644 index de1b86fb68..0000000000 --- a/tests/examples/configs/firewall-policies/cidrs.yaml +++ /dev/null @@ -1,5 +0,0 @@ -# skip boilerplate check -rfc1918: - - 10.0.0.0/8 - - 172.16.0.0/12 - - 192.168.0.0/16 diff --git a/tests/examples/configs/firewall-policies/rules.yaml b/tests/examples/configs/firewall-policies/rules.yaml deleted file mode 100644 index d7725a4d90..0000000000 --- a/tests/examples/configs/firewall-policies/rules.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# skip boilerplate check -allow-admins: - description: Access from the admin subnet to all subnets - direction: INGRESS - action: allow - priority: 1000 - ranges: - - $rfc1918 - ports: - all: [] - target_resources: null - enable_logging: false - -allow-ssh-from-iap: - description: Enable SSH from IAP - direction: INGRESS - action: allow - priority: 1002 - ranges: - - 35.235.240.0/20 - ports: - tcp: ["22"] - target_resources: null - enable_logging: false diff --git a/tests/examples/configs/firewall/cidr_template.yaml b/tests/examples/configs/firewall/cidr_template.yaml deleted file mode 100644 index 3350e0e06c..0000000000 --- a/tests/examples/configs/firewall/cidr_template.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# skip boilerplate check -healthchecks: - - 35.191.0.0/16 - - 130.211.0.0/22 - - 209.85.152.0/22 - - 209.85.204.0/22 diff --git a/tests/examples/configs/firewall/rules/load_balancers.yaml b/tests/examples/configs/firewall/rules/load_balancers.yaml deleted file mode 100644 index bfaf474e54..0000000000 --- a/tests/examples/configs/firewall/rules/load_balancers.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# skip boilerplate check -allow-healthchecks: - description: Allow ingress from healthchecks. - ranges: - - healthchecks - targets: ["lb-backends"] - rules: - - protocol: tcp - ports: - - 80 - - 443 diff --git a/tests/examples/configs/org-policies/boolean.yaml b/tests/examples/configs/org-policies/boolean.yaml deleted file mode 100644 index b9cbe38882..0000000000 --- a/tests/examples/configs/org-policies/boolean.yaml +++ /dev/null @@ -1,13 +0,0 @@ -# skip boilerplate check -iam.disableServiceAccountKeyCreation: - enforce: true - -iam.disableServiceAccountKeyUpload: - enforce: false - rules: - - condition: - expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") - title: condition - description: test condition - location: xxx - enforce: true diff --git a/tests/examples/configs/org-policies/list.yaml b/tests/examples/configs/org-policies/list.yaml deleted file mode 100644 index 00a44a88a4..0000000000 --- a/tests/examples/configs/org-policies/list.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# skip boilerplate check -compute.vmExternalIpAccess: - deny: - all: true - -iam.allowedPolicyMemberDomains: - allow: - values: - - C0xxxxxxx - - C0yyyyyyy - -compute.restrictLoadBalancerCreationForTypes: - deny: - values: ["in:EXTERNAL"] - rules: - - condition: - expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") - title: condition - description: test condition - allow: - values: ["in:EXTERNAL"] - - condition: - expression: resource.matchTagId("tagKeys/12345", "tagValues/12345") - title: condition2 - description: test condition2 - allow: - all: true diff --git a/tests/examples/configs/subnets/subnet-name.yaml b/tests/examples/configs/subnets/subnet-name.yaml deleted file mode 100644 index 4416cf11a8..0000000000 --- a/tests/examples/configs/subnets/subnet-name.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# skip boilerplate check -region: europe-west1 -description: Sample description -ip_cidr_range: 10.0.0.0/24 -# optional attributes -enable_private_access: false # defaults to true -iam_users: ["foobar@example.com"] # grant compute/networkUser to users -iam_groups: ["lorem@example.com"] # grant compute/networkUser to groups -iam_service_accounts: ["fbz@prj.iam.gserviceaccount.com"] -secondary_ip_ranges: # map of secondary ip ranges - secondary-range-a: 192.168.0.0/24 -flow_logs: # enable, set to empty map to use defaults - - aggregation_interval: "INTERVAL_5_SEC" - - flow_sampling: 0.5 - - metadata: "INCLUDE_ALL_METADATA" diff --git a/tests/examples/conftest.py b/tests/examples/conftest.py index 6d6246a327..b2b915ea1d 100644 --- a/tests/examples/conftest.py +++ b/tests/examples/conftest.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import collections +import re from pathlib import Path import marko @@ -21,6 +23,11 @@ MODULES_PATH = FABRIC_ROOT / 'modules/' BLUEPRINTS_PATH = FABRIC_ROOT / 'blueprints/' +FILE_TEST_RE = re.compile(r'# tftest file (\w+) ([\S]+)') + +Example = collections.namedtuple('Example', 'code files') +File = collections.namedtuple('File', 'path content') + def pytest_generate_tests(metafunc): if 'example' in metafunc.fixturenames: @@ -37,15 +44,25 @@ def pytest_generate_tests(metafunc): doc = marko.parse(readme.read_text()) index = 0 last_header = None - mark = pytest.mark.xdist_group(name=module.name) + files = {} + + #first pass: collect all tftest tagged files + for child in doc.children: + if isinstance(child, marko.block.FencedCode): + code = child.children[0].children + match = FILE_TEST_RE.search(code) + if match: + name, path = match.groups() + files[name] = File(path, code) + for child in doc.children: if isinstance(child, marko.block.FencedCode): index += 1 code = child.children[0].children if 'tftest skip' in code: continue - if child.lang == 'hcl' or 'tftest file' in code: - examples.append(pytest.param(code, marks=mark)) + if child.lang == 'hcl': + examples.append(Example(code, files)) path = module.relative_to(FABRIC_ROOT) name = f'{path}:{last_header}' if index > 1: diff --git a/tests/examples/test_plan.py b/tests/examples/test_plan.py index c22f9998db..2bb45af12d 100644 --- a/tests/examples/test_plan.py +++ b/tests/examples/test_plan.py @@ -16,18 +16,23 @@ from pathlib import Path BASE_PATH = Path(__file__).parent -COUNT_TEST_RE = re.compile(r'# tftest modules=(\d+) resources=(\d+)') -FILE_TEST_RE = re.compile(r'# tftest file (.+)') +COUNT_TEST_RE = re.compile( + r'# tftest modules=(\d+) resources=(\d+)(?: files=([\w,]+))?') def test_example(recursive_e2e_plan_runner, tmp_path, example): - (tmp_path / 'fabric').symlink_to(Path(BASE_PATH, '../../').resolve()) - (tmp_path / 'variables.tf').symlink_to( - Path(BASE_PATH, 'variables.tf').resolve()) - (tmp_path / 'configs').symlink_to(Path(BASE_PATH, 'configs').resolve()) - (tmp_path / 'main.tf').write_text(example) + if match := COUNT_TEST_RE.search(example.code): + (tmp_path / 'fabric').symlink_to(Path(BASE_PATH, '../../')) + (tmp_path / 'variables.tf').symlink_to(Path(BASE_PATH, 'variables.tf')) + (tmp_path / 'main.tf').write_text(example.code) + + if match.group(3) is not None: + requested_files = match.group(3).split(',') + for f in requested_files: + destination = tmp_path / example.files[f].path + destination.parent.mkdir(parents=True, exist_ok=True) + destination.write_text(example.files[f].content) - if match := COUNT_TEST_RE.search(example): expected_modules = int(match.group(1)) if match is not None else 1 expected_resources = int(match.group(2)) if match is not None else 1 @@ -36,16 +41,5 @@ def test_example(recursive_e2e_plan_runner, tmp_path, example): assert expected_modules == num_modules, 'wrong number of modules' assert expected_resources == num_resources, 'wrong number of resources' - elif match := FILE_TEST_RE.search(example): - filename = tmp_path / match.group(1) - assert filename.exists(), f'cant read {filename}' - - file_content = filename.read_text() - - # skip first line - file_content = file_content.split('\n', 1)[1] - example = example.split('\n', 1)[1] - assert file_content == example, "README inline file and fixture file don't match" - else: assert False, "can't find tftest directive"