Merge pull request #1340 from GoogleCloudPlatform/jccb/tests-lockfile

Extend tests to use lockfile if available
This commit is contained in:
Julio Castillo 2023-04-26 11:10:12 +02:00 committed by GitHub
commit eedd805bd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 106 additions and 275 deletions

View File

@ -41,11 +41,21 @@ runs:
- name: Configure provider cache
shell: bash
run: |
echo 'plugin_cache_dir = "/home/runner/.terraform.d/plugin-cache"' \
echo 'plugin_cache_dir = "${{ env.TF_PLUGIN_CACHE_DIR }}"' \
| tee -a /home/runner/.terraformrc
echo 'disable_checkpoint = true' \
| tee -a /home/runner/.terraformrc
mkdir -p ${{ env.TF_PLUGIN_CACHE_DIR }}
- name: Download lockfile
uses: actions/download-artifact@v3
with:
name: lockfile
path: tools/lockfile
- name: Download Terraform provider cache
uses: actions/cache@v3
with:
path: ${{ env.TF_PLUGIN_CACHE_DIR }}
key: ${{ runner.os }}-terraform-${{ hashFiles('tools/lockfile/.terraform.lock.hcl') }}
# avoid conflicts with user-installed providers on local machines
- name: Pin provider versions
shell: bash

View File

@ -29,10 +29,46 @@ env:
PYTHON_VERSION: "3.10"
TF_PLUGIN_CACHE_DIR: "/home/runner/.terraform.d/plugin-cache"
TF_VERSION: 1.4.4
TFTEST_COPY: 1
jobs:
setup-tf-providers:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
terraform_wrapper: false
- name: Build lockfile and fetch providers
shell: bash
run: |
mkdir -p ${{ env.TF_PLUGIN_CACHE_DIR }}
echo 'plugin_cache_dir = "${{ env.TF_PLUGIN_CACHE_DIR }}"' | tee -a /home/runner/.terraformrc
echo 'disable_checkpoint = true' | tee -a /home/runner/.terraformrc
cp default-versions.tf tools/lockfile
sed -i 's/>=\(.*# tftest\)/=\1/g' tools/lockfile/default-versions.tf
cd tools/lockfile
terraform init -upgrade=true
- name: Upload Terraform provider cache
uses: actions/cache@v3
with:
path: ${{ env.TF_PLUGIN_CACHE_DIR }}
key: ${{ runner.os }}-terraform-${{ hashFiles('tools/lockfile/.terraform.lock.hcl') }}
- name: Upload lockfile
uses: actions/upload-artifact@v3
with:
name: lockfile
path: tools/lockfile/.terraform.lock.hcl
examples-blueprints:
runs-on: ubuntu-latest
needs: setup-tf-providers
steps:
- uses: actions/checkout@v3
@ -43,10 +79,11 @@ jobs:
TERRAFORM_VERSION: ${{ env.TERRAFORM_VERSION }}
- name: Run tests on documentation examples
run: pytest -vv -k blueprints/ tests/examples
run: pytest -vv -n4 -k blueprints/ tests/examples
examples-modules:
runs-on: ubuntu-latest
needs: setup-tf-providers
steps:
- uses: actions/checkout@v3
@ -57,10 +94,11 @@ jobs:
TERRAFORM_VERSION: ${{ env.TERRAFORM_VERSION }}
- name: Run tests on documentation examples
run: pytest -vv -k modules/ tests/examples
run: pytest -vv -n4 -k modules/ tests/examples
blueprints:
runs-on: ubuntu-latest
needs: setup-tf-providers
steps:
- uses: actions/checkout@v3
@ -71,10 +109,11 @@ jobs:
TERRAFORM_VERSION: ${{ env.TERRAFORM_VERSION }}
- name: Run tests environments
run: pytest -vv tests/blueprints
run: pytest -vv -n4 tests/blueprints
modules:
runs-on: ubuntu-latest
needs: setup-tf-providers
steps:
- uses: actions/checkout@v3
@ -85,10 +124,11 @@ jobs:
TERRAFORM_VERSION: ${{ env.TERRAFORM_VERSION }}
- name: Run tests modules
run: pytest -vv tests/modules
run: pytest -vv -n4 tests/modules
fast:
runs-on: ubuntu-latest
needs: setup-tf-providers
steps:
- uses: actions/checkout@v3
@ -99,4 +139,4 @@ jobs:
TERRAFORM_VERSION: ${{ env.TERRAFORM_VERSION }}
- name: Run tests on FAST stages
run: pytest -vv tests/fast
run: pytest -vv -n4 tests/fast

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,6 +17,5 @@ import pytest
pytest_plugins = (
'tests.fixtures',
'tests.legacy_fixtures',
'tests.collectors',
)

View File

@ -25,6 +25,7 @@ import pytest
import tftest
import yaml
_REPO_ROOT = Path(__file__).parents[1]
PlanSummary = collections.namedtuple('PlanSummary', 'values counts outputs')
@ -51,10 +52,14 @@ def _prepare_root_module(path):
'*.auto.tfvars.json',
'[0-9]-*-providers.tf',
'terraform.tfstate*',
'.terraform.lock.hcl',
'terraform.tfvars', '.terraform')
shutil.copytree(path, tmp_path, dirs_exist_ok=True,
ignore=ignore_patterns)
lockfile = _REPO_ROOT / 'tools' / 'lockfile' / '.terraform.lock.hcl'
if lockfile.exists():
shutil.copy(lockfile, tmp_path / '.terraform.lock.hcl')
yield tmp_path
else:
@ -94,7 +99,7 @@ def plan_summary(module_path, basedir, tf_var_files=None, extra_files=None,
"""
# make the module_path relative to the root of the repo while still
# supporting absolute paths
module_path = Path(__file__).parents[1] / module_path
module_path = _REPO_ROOT / module_path
with _prepare_root_module(module_path) as test_path:
binary = os.environ.get('TERRAFORM', 'terraform')
tf = tftest.TerraformTest(test_path, binary=binary)

View File

@ -1,57 +0,0 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Legacy pytest fixtures.
The fixtures contained in this file will eventually go away. Consider
using one of the fixtures in fixtures.py
"""
import inspect
import os
import shutil
import tempfile
import pytest
import tftest
BASEDIR = os.path.dirname(os.path.dirname(__file__))
@pytest.fixture(scope='session')
def apply_runner():
'Return a function to run Terraform apply on a fixture.'
def run_apply(fixture_path=None, **tf_vars):
'Run Terraform plan and returns parsed output.'
if fixture_path is None:
# find out the fixture directory from the caller's directory
caller = inspect.stack()[1]
fixture_path = os.path.join(os.path.dirname(caller.filename), 'fixture')
fixture_parent = os.path.dirname(fixture_path)
fixture_prefix = os.path.basename(fixture_path) + '_'
with tempfile.TemporaryDirectory(prefix=fixture_prefix,
dir=fixture_parent) as tmp_path:
# copy fixture to a temporary directory so we can execute
# multiple tests in parallel
shutil.copytree(fixture_path, tmp_path, dirs_exist_ok=True)
tf = tftest.TerraformTest(tmp_path, BASEDIR,
os.environ.get('TERRAFORM', 'terraform'))
tf.setup(upgrade=True)
apply = tf.apply(tf_vars=tf_vars)
output = tf.output(json_format=True)
return apply, output
return run_apply

View File

@ -1,24 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module "test" {
source = "../../../../modules/cloud-config-container/coredns"
cloud_config = var.cloud_config
config_variables = var.config_variables
coredns_config = var.coredns_config
file_defaults = var.file_defaults
files = var.files
}

View File

@ -1,19 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
output "cloud_config" {
value = module.test.cloud_config
}

View File

@ -1,50 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
variable "cloud_config" {
type = string
default = null
}
variable "config_variables" {
type = map(any)
default = {}
}
variable "coredns_config" {
type = string
default = null
}
variable "file_defaults" {
type = object({
owner = string
permissions = string
})
default = {
owner = "root"
permissions = "0644"
}
}
variable "files" {
type = map(object({
content = string
owner = string
permissions = string
}))
default = {}
}

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -16,10 +16,10 @@ import re
import yaml
def test_defaults(apply_runner):
"Test defalt configuration."
_, output = apply_runner()
cloud_config = output['cloud_config']
def test_defaults(plan_summary):
"Test default configuration."
summary = plan_summary('modules/cloud-config-container/coredns/')
cloud_config = summary.outputs['cloud_config']['value']
yaml.safe_load(cloud_config)
assert cloud_config.startswith('#cloud-config')
assert re.findall(r'(?m)^\s+\-\s*path:\s*(\S+)', cloud_config) == [

View File

@ -1,26 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module "test" {
source = "../../../../modules/cloud-config-container/mysql"
cloud_config = var.cloud_config
config_variables = var.config_variables
image = var.image
kms_config = var.kms_config
mysql_config = var.mysql_config
mysql_data_disk = var.mysql_data_disk
mysql_password = var.mysql_password
}

View File

@ -1,19 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
output "cloud_config" {
value = module.test.cloud_config
}

View File

@ -1,54 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
variable "cloud_config" {
type = string
default = null
}
variable "config_variables" {
type = map(any)
default = {}
}
variable "image" {
type = string
default = "mysql:5.7"
}
variable "kms_config" {
type = object({
project_id = string
keyring = string
location = string
key = string
})
default = null
}
variable "mysql_config" {
type = string
default = null
}
variable "mysql_data_disk" {
type = string
default = null
}
variable "mysql_password" {
type = string
}

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -16,34 +16,34 @@ import re
import yaml
def test_defaults(apply_runner):
def test_defaults(plan_summary):
"Test defalt configuration."
_, output = apply_runner(mysql_password='foo')
cloud_config = output['cloud_config']
# _, output = apply_runner(mysql_password='foo')
summary = plan_summary('modules/cloud-config-container/mysql/',
mysql_password='foo')
cloud_config = summary.outputs['cloud_config']['value']
yaml.safe_load(cloud_config)
assert cloud_config.startswith('#cloud-config')
assert re.findall(r'(?m)^\s+\-\s*path:\s*(\S+)', cloud_config) == [
'/var/lib/docker/daemon.json',
'/run/mysql/secrets/mysql-passwd.txt',
'/var/lib/docker/daemon.json', '/run/mysql/secrets/mysql-passwd.txt',
'/etc/systemd/system/mysql.service'
]
assert 'gcloud' not in cloud_config
def test_kms(apply_runner):
def test_kms(plan_summary):
"Test KMS configuration."
kms_config = (
'{project_id="my-project", keyring="my-keyring", location="eu", key="foo"}'
)
_, output = apply_runner(mysql_password='foo',
kms_config=kms_config)
cloud_config = output['cloud_config']
summary = plan_summary('modules/cloud-config-container/mysql/',
mysql_password='foo', kms_config=kms_config)
cloud_config = summary.outputs['cloud_config']['value']
yaml.safe_load(cloud_config)
assert cloud_config.startswith('#cloud-config')
assert re.findall(r'(?m)^\s+\-\s*path:\s*(\S+)', cloud_config) == [
'/var/lib/docker/daemon.json',
'/run/mysql/secrets/mysql-passwd-cipher.txt',
'/run/mysql/passwd.sh',
'/run/mysql/secrets/mysql-passwd-cipher.txt', '/run/mysql/passwd.sh',
'/etc/systemd/system/mysql.service'
]
assert 'gcloud' in cloud_config

View File

@ -4,3 +4,4 @@ tftest>=1.8.1
marko>=1.2.2
deepdiff>=6.2.3
python-hcl2>=4.3.0
pytest-xdist>=3.1.0

25
tools/lockfile/main.tf Normal file
View File

@ -0,0 +1,25 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
data "archive_file" "bundle" {}
resource "azuread_user" "default" {}
resource "azurerm_resource_group" "default" {}
resource "github_branch" "default" {}
resource "google_service_account" "sa1" {}
resource "google_service_account" "sa2" { provider = google-beta }
resource "local_file" "default" {}
resource "random_pet" "default" {}
resource "time_static" "default" {}
resource "tls_private_key" "default" {}
resource "vsphere_role" "default" {}