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

refactor: DBTP-1630 Terraform environment domain tests refactor #715

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fd35780
Add command level test for without the version flag
ksugden Jan 9, 2025
d47c6ad
Refactor parameter names and tidy test pydocs
ksugden Jan 9, 2025
c673198
Add test for warning on deprecated flag
ksugden Jan 9, 2025
c5239a0
Remove test covered in test_command_environment.py
ksugden Jan 9, 2025
2bc06c6
DBTP-1630 remove --vpc flag depreaction warning and tests
DeveloperConnor Jan 9, 2025
96c03db
first pass at moving files methods into FilesProvider
DeveloperConnor Jan 9, 2025
cf8adf6
add TODO
DeveloperConnor Jan 9, 2025
46d6e19
separate manifest generation from file writing
ksugden Jan 9, 2025
078b792
Move private methods inside the class
ksugden Jan 9, 2025
05dbbd3
inline a bunch of stuff
ksugden Jan 9, 2025
6c7ec8c
inline more stuff
ksugden Jan 9, 2025
58695dd
inline it all!
ksugden Jan 10, 2025
03fc0d3
Add PlatformTerraformManifestGenerator class
ksugden Jan 10, 2025
456ae88
remove print
ksugden Jan 10, 2025
543f1d7
add tests for generate_manifest
ksugden Jan 10, 2025
2b188f9
use PlatformTerraformManifestGenerator in generate function
ksugden Jan 10, 2025
11c8d38
Add file provider dependency for writing manifest file
ksugden Jan 10, 2025
54fec1a
inline environment_config
ksugden Jan 10, 2025
ee4b436
Add further assertions on the expected manifest content
ksugden Jan 10, 2025
53cbcb3
add get_enriched_config function
ksugden Jan 10, 2025
c924ec3
Add comments
ksugden Jan 10, 2025
03e9603
move get_enriched_config into config provider
ksugden Jan 10, 2025
9673547
fixes order of parameters
ksugden Jan 10, 2025
95f93de
added assertions on write_manifest and echo_fn in terraform_generate
DeveloperConnor Jan 10, 2025
e03a3ce
Merge branch 'main' into DBTP-1630-terraform-environment-tests
DeveloperConnor Jan 10, 2025
4000135
Add todo
ksugden Jan 10, 2025
bb17344
remove obsolete test
ksugden Jan 10, 2025
42ff1b5
Adds exception for generate called on non existent env
ksugden Jan 10, 2025
e51456b
Add todo for redundant exception handling
ksugden Jan 10, 2025
828ddaa
remove obsolete function
ksugden Jan 10, 2025
4a7b6d2
Corrects invalid modules version format
ksugden Jan 10, 2025
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
4 changes: 1 addition & 3 deletions dbt_platform_helper/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,13 +460,11 @@ platform-helper environment online --app <application> --env <environment>
## Usage

```
platform-helper environment generate --name <name> [--vpc-name <vpc_name>]
platform-helper environment generate --name <name>
```

## Options

- `--vpc-name <text>`

- `--name
-n <text>`

Expand Down
6 changes: 4 additions & 2 deletions dbt_platform_helper/commands/copilot.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
from dbt_platform_helper.domain.config_validator import ConfigValidator
from dbt_platform_helper.domain.copilot_environment import CopilotTemplating
from dbt_platform_helper.providers.config import ConfigProvider
from dbt_platform_helper.providers.files import FileProvider
from dbt_platform_helper.utils.application import get_application_name
from dbt_platform_helper.utils.application import load_application
from dbt_platform_helper.utils.aws import get_aws_session_or_abort
from dbt_platform_helper.utils.click import ClickDocOptGroup
from dbt_platform_helper.utils.files import generate_override_files
from dbt_platform_helper.utils.files import mkfile
from dbt_platform_helper.utils.messages import abort_with_error
from dbt_platform_helper.utils.template import ADDON_TEMPLATE_MAP
from dbt_platform_helper.utils.template import camel_case
Expand Down Expand Up @@ -379,7 +379,9 @@ def _generate_service_addons(

(output_dir / service_path).mkdir(parents=True, exist_ok=True)
click.echo(
mkfile(output_dir, service_path / f"{addon_name}.yml", contents, overwrite=True)
FileProvider.mkfile(
output_dir, service_path / f"{addon_name}.yml", contents, overwrite=True
)
)


Expand Down
9 changes: 1 addition & 8 deletions dbt_platform_helper/commands/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,8 @@ def online(app, env):


@environment.command()
@click.option("--vpc-name", hidden=True)
@click.option("--name", "-n", required=True)
def generate(name, vpc_name):
if vpc_name:
click.secho(
f"This option is deprecated. Please add the VPC name for your envs to {PLATFORM_CONFIG_FILE}",
fg="red",
)
raise click.Abort
def generate(name):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the deprecation warning when providing a vpc to generate-terraform - its been here for 7months now, seems like no one should be impacted /shrug

try:
config_provider = ConfigProvider(ConfigValidator())
CopilotEnvironment(config_provider).generate(name)
Expand Down
6 changes: 3 additions & 3 deletions dbt_platform_helper/commands/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
from dbt_platform_helper.constants import DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
from dbt_platform_helper.domain.config_validator import ConfigValidator
from dbt_platform_helper.providers.config import ConfigProvider
from dbt_platform_helper.providers.files import FileProvider
from dbt_platform_helper.utils.application import get_application_name
from dbt_platform_helper.utils.aws import get_account_details
from dbt_platform_helper.utils.aws import get_codestar_connection_arn
from dbt_platform_helper.utils.aws import get_public_repository_arn
from dbt_platform_helper.utils.click import ClickDocOptGroup
from dbt_platform_helper.utils.files import generate_override_files_from_template
from dbt_platform_helper.utils.files import mkfile
from dbt_platform_helper.utils.git import git_remote
from dbt_platform_helper.utils.messages import abort_with_error
from dbt_platform_helper.utils.template import setup_templates
Expand Down Expand Up @@ -178,7 +178,7 @@ def _create_file_from_template(
contents = templates.get_template(
f"pipelines/{file_name if template_name is None else template_name}"
).render(template_data)
message = mkfile(base_path, pipelines_dir / file_name, contents, overwrite=True)
message = FileProvider.mkfile(base_path, pipelines_dir / file_name, contents, overwrite=True)
click.echo(message)


Expand Down Expand Up @@ -207,7 +207,7 @@ def _generate_terraform_environment_pipeline_manifest(
dir_path = f"terraform/environment-pipelines/{aws_account}"
makedirs(dir_path, exist_ok=True)

click.echo(mkfile(".", f"{dir_path}/main.tf", contents, overwrite=True))
click.echo(FileProvider.mkfile(".", f"{dir_path}/main.tf", contents, overwrite=True))


def _determine_terraform_platform_modules_version(
Expand Down
12 changes: 8 additions & 4 deletions dbt_platform_helper/domain/codebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from boto3 import Session

from dbt_platform_helper.platform_exception import PlatformException
from dbt_platform_helper.providers.files import FileProvider
from dbt_platform_helper.utils.application import Application
from dbt_platform_helper.utils.application import ApplicationException
from dbt_platform_helper.utils.application import load_application
Expand All @@ -19,7 +20,6 @@
from dbt_platform_helper.utils.aws import get_build_url_from_arn
from dbt_platform_helper.utils.aws import list_latest_images
from dbt_platform_helper.utils.aws import start_build_extraction
from dbt_platform_helper.utils.files import mkfile
from dbt_platform_helper.utils.git import check_if_commit_exists
from dbt_platform_helper.utils.template import setup_templates

Expand Down Expand Up @@ -92,21 +92,25 @@ def prepare(self):
repository=repository, builder_version=builder_version
)
self.echo(
mkfile(
FileProvider.mkfile(
Path("."), ".copilot/image_build_run.sh", image_build_run_contents, overwrite=True
)
)

image_build_run_file = Path(".copilot/image_build_run.sh")
image_build_run_file.chmod(image_build_run_file.stat().st_mode | stat.S_IEXEC)

self.echo(mkfile(Path("."), ".copilot/config.yml", config_contents, overwrite=True))
self.echo(
FileProvider.mkfile(Path("."), ".copilot/config.yml", config_contents, overwrite=True)
)

for phase in ["build", "install", "post_build", "pre_build"]:
phase_contents = templates.get_template(f".copilot/phases/{phase}.sh").render()

self.echo(
mkfile(Path("./.copilot"), f"phases/{phase}.sh", phase_contents, overwrite=True)
FileProvider.mkfile(
Path("./.copilot"), f"phases/{phase}.sh", phase_contents, overwrite=True
)
)

def build(self, app: str, codebase: str, commit: str):
Expand Down
6 changes: 3 additions & 3 deletions dbt_platform_helper/domain/copilot_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import click

from dbt_platform_helper.platform_exception import PlatformException
from dbt_platform_helper.providers.files import FileProvider
from dbt_platform_helper.providers.load_balancers import find_https_listener
from dbt_platform_helper.utils.aws import get_aws_session_or_abort
from dbt_platform_helper.utils.files import mkfile
from dbt_platform_helper.utils.template import S3_CROSS_ACCOUNT_POLICY
from dbt_platform_helper.utils.template import camel_case
from dbt_platform_helper.utils.template import setup_templates
Expand Down Expand Up @@ -111,7 +111,7 @@ def _generate_copilot_environment_manifests(
}
)
click.echo(
mkfile(
FileProvider.mkfile(
".", f"copilot/environments/{environment_name}/manifest.yml", contents, overwrite=True
)
)
Expand Down Expand Up @@ -155,7 +155,7 @@ def generate(self, environment_name):


class CopilotTemplating:
def __init__(self, mkfile_fn=mkfile):
def __init__(self, mkfile_fn=FileProvider.mkfile):
self.mkfile_fn = mkfile_fn

def generate_cross_account_s3_policies(self, environments: dict, extensions):
Expand Down
93 changes: 56 additions & 37 deletions dbt_platform_helper/domain/terraform_environment.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,72 @@
import click

from dbt_platform_helper.constants import DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
from dbt_platform_helper.utils.files import mkfile
from dbt_platform_helper.providers.files import FileProvider
from dbt_platform_helper.utils.template import setup_templates


def _generate_terraform_environment_manifests(
application, env, env_config, cli_terraform_platform_modules_version
):
env_template = setup_templates().get_template("environments/main.tf")
class PlatformTerraformManifestGenerator:
def __init__(self, file_provider):
self.file_provider = file_provider
self.manifest_template = setup_templates().get_template("environments/main.tf")

terraform_platform_modules_version = _determine_terraform_platform_modules_version(
env_config, cli_terraform_platform_modules_version
)

contents = env_template.render(
{
"application": application,
"environment": env,
"config": env_config,
"terraform_platform_modules_version": terraform_platform_modules_version,
}
)

click.echo(mkfile(".", f"terraform/environments/{env}/main.tf", contents, overwrite=True))
def generate_manifest(
self,
environment_name: str,
application_name: str,
environment_config: dict,
terraform_platform_modules_version_override: str = None,
):
terraform_platform_modules_version = (
terraform_platform_modules_version_override
or environment_config.get("versions", {}).get(
"terraform-platform-modules", DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
)
)

return self.manifest_template.render(
{
"application": application_name,
"environment": environment_name,
"config": environment_config,
"terraform_platform_modules_version": terraform_platform_modules_version,
}
)

def _determine_terraform_platform_modules_version(env_conf, cli_terraform_platform_modules_version):
cli_terraform_platform_modules_version = cli_terraform_platform_modules_version
env_conf_terraform_platform_modules_version = env_conf.get("versions", {}).get(
"terraform-platform-modules"
)
version_preference_order = [
cli_terraform_platform_modules_version,
env_conf_terraform_platform_modules_version,
DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION,
]
return [version for version in version_preference_order if version][0]
def write_manifest(self, environment_name: str, manifest_content: str):
return self.file_provider.mkfile(
".",
f"terraform/environments/{environment_name}/main.tf",
manifest_content,
overwrite=True,
)


class TerraformEnvironment:
def __init__(self, config_provider):
def __init__(
self,
config_provider,
manifest_generator: PlatformTerraformManifestGenerator = None,
echo_fn=click.echo,
):
self.echo = echo_fn
self.config_provider = config_provider
self.manifest_generator = manifest_generator or PlatformTerraformManifestGenerator(
FileProvider()
)

def generate(self, name, terraform_platform_modules_version):
config = self.config_provider.load_and_validate_platform_config()
enriched_config = self.config_provider.apply_environment_defaults(config)
def generate(self, environment_name, terraform_platform_modules_version_override=None):
config = self.config_provider.get_enriched_config()

manifest = self.manifest_generator.generate_manifest(
environment_name=environment_name,
application_name=config["application"],
environment_config=config["environments"][environment_name],
terraform_platform_modules_version_override=terraform_platform_modules_version_override,
)

env_config = enriched_config["environments"][name]
_generate_terraform_environment_manifests(
config["application"], name, env_config, terraform_platform_modules_version
self.echo(
self.manifest_generator.write_manifest(
environment_name=environment_name, manifest_content=manifest
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from unittest.mock import Mock

from dbt_platform_helper.constants import DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
from dbt_platform_helper.domain.terraform_environment import (
PlatformTerraformManifestGenerator,
)
from dbt_platform_helper.providers.files import FileProvider


class TestPlatformTerraformManifestGenerator:

def test_generator_generates_expected_manifest_content_with_version_override(self):
test_environment_config = {
"vpc": "vpc3",
"accounts": {
"deploy": {"name": "non-prod-acc", "id": "1122334455"},
"dns": {"name": "non-prod-dns-acc", "id": "6677889900"},
},
"versions": {"terraform-platform-modules": 3},
}
expected_header = "# WARNING: This is an autogenerated file, not for manual editing."
expected_modules = "git::https://github.com/uktrade/terraform-platform-modules.git//extensions?depth=1&ref=123456"
expected_moved_block = (
"moved {\n from = module.extensions-tf\n to = module.extensions\n}\n"
)

result = PlatformTerraformManifestGenerator(Mock()).generate_manifest(
"test", "test-app", test_environment_config, 123456
)

assert expected_header in result
assert expected_modules in result
assert expected_moved_block in result
assert 'environment = "test"' in result
assert 'application = "test-app"' in result
assert 'vpc_name = "vpc3"'

def test_generator_generates_expected_manifest_content_with_tpm_version_set_in_config(self):
test_environment_config = {
"vpc": "vpc3",
"accounts": {
"deploy": {"name": "non-prod-acc", "id": "1122334455"},
"dns": {"name": "non-prod-dns-acc", "id": "6677889900"},
},
"versions": {"terraform-platform-modules": 3},
}
expected_header = "# WARNING: This is an autogenerated file, not for manual editing."
expected_modules = "git::https://github.com/uktrade/terraform-platform-modules.git//extensions?depth=1&ref=3"
expected_moved_block = (
"moved {\n from = module.extensions-tf\n to = module.extensions\n}\n"
)

result = PlatformTerraformManifestGenerator(Mock()).generate_manifest(
"test", "test-app", test_environment_config
)

assert expected_header in result
assert expected_modules in result
assert expected_moved_block in result
assert 'environment = "test"' in result
assert 'application = "test-app"' in result
assert 'vpc_name = "vpc3"'

def test_generator_generates_expected_manifest_content_with_default_version(self):
test_environment_config = {
"vpc": "vpc3",
"accounts": {
"deploy": {"name": "non-prod-acc", "id": "1122334455"},
"dns": {"name": "non-prod-dns-acc", "id": "6677889900"},
},
}
expected_header = "# WARNING: This is an autogenerated file, not for manual editing."
expected_modules = f"git::https://github.com/uktrade/terraform-platform-modules.git//extensions?depth=1&ref={DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION}"
expected_moved_block = (
"moved {\n from = module.extensions-tf\n to = module.extensions\n}\n"
)

result = PlatformTerraformManifestGenerator(Mock()).generate_manifest(
"test", "test-app", test_environment_config
)

assert expected_header in result
assert expected_modules in result
assert expected_moved_block in result
assert 'environment = "test"' in result
assert 'application = "test-app"' in result
assert 'vpc_name = "vpc3"'

def test_generator_write_manifest_makes_the_expected_manifest_file(self):
mock_file_provider = Mock(spec=FileProvider)
PlatformTerraformManifestGenerator(mock_file_provider).write_manifest(
"test-environment", "test-manifest-content"
)

mock_file_provider.mkfile.assert_called_once_with(
".",
f"terraform/environments/test-environment/main.tf",
"test-manifest-content",
overwrite=True,
)
3 changes: 1 addition & 2 deletions dbt_platform_helper/providers/cache.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import os
from datetime import datetime

from dbt_platform_helper.providers.yaml_file import FileProvider
from dbt_platform_helper.providers.yaml_file import YamlFileProvider


class CacheProvider:
def __init__(
self,
file_provider: FileProvider = None,
file_provider: YamlFileProvider = None,
):
self._cache_file = ".platform-helper-config-cache.yml"
self.file_provider = file_provider or YamlFileProvider
Expand Down
Loading
Loading