Skip to content
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ tests/integration/integration_config.yml
# Remove molecule testing deployments
**/molecule/*/deployment

# Remove any Terraform for testing
tests/terraform/.terraform*
tests/terraform/terraform.tfstate*

### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
67 changes: 67 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,70 @@ Commits and pull requests will fail if your contributions do not pass the `pre-c
```bash
pre-commit run -a
```

---

# Testing

This project uses [Hatch](https://hatch.pypa.io/dev/) to manage the project's dependencies, testing environments, and other activities. It also makes heavy use of [Ansible Molecule](https://ansible.readthedocs.io/projects/molecule/) and employs the [EC2 driver](https://github.com/ansible-community/molecule-plugins) to test using cloud instances.

## Setup

### Hatch Build System

You should install `hatch` as [per its documentation](https://hatch.pypa.io/dev/install/#installers). `hatch` should be able to handle all dependencies, including Python versions and virtual environments.

> [!danger] OSX `dirs.data` default!
> The [default data directory](https://hatch.pypa.io/1.13/config/hatch/#data) for `hatch` is `~/Library/Application Support/hatch`, which causes trouble for `molecule`! You might need to change this location to a path with spaces!

### AWS Credentials

You will need valid AWS credentials set in your environment for `molecule` to operate successfully.

In addition, make sure you have a default region declared, either in your `AWS_PROFILE` or `AWS_DEFAULT_REGION`.

### Test Network

`molecule` only manages the EC2 instances, not the VPC and associated networking. To set up the required infrastructure, you can run the following `hatch` commands.

```bash
hatch run molecule:init
```

This will initialize the `tests/terraform` project which establishes the testing network in AWS.

```bash
hatch run molecule:setup
```

This command executes the `tests/terraform` project.

Once your network is set up, be sure to set the `TEST_VPC_SUBNET_ID` and `TEST_VPC_SECURITY_GROUP` variables with the public subnet ID and intra-traffic security group name, respectively, of your testing network.

```bash
$(hatch run molecule:export-subnet)
$(hatch run molecule:export-security-group)
```

## Execution

Running `molecule` is straightforward. First, enable the `hatch` environment:

```bash
hatch shell molecule
```

And then change into the role directory that you wish to test, e.g. `cd roles/prereq_thp`, and run `molecule` from there.

> [!info]
> In some cases, you might need to set your `ANSIBLE_ROLES_PATH` to the `roles` directory of this project.

## Teardown

First, make sure that you have destroyed any `molecule` scenarios that are using your test infrastructure.

And then, from the _project root_, run:

```bash
hatch run molecule:teardown
```
21 changes: 21 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ filterwarnings = [
"ignore:'crypt' is deprecated and slated for removal in Python 3.13:DeprecationWarning",
]

[tool.hatch.envs.molecule]
python = "3.12"
detached = true
extra-dependencies = [
"molecule",
# "molecule-plugins",
# "molecule-plugins[ec2]",
"molecule-plugins @ git+https://github.com/ansible-community/molecule-plugins.git", # Fixes https://github.com/ansible-community/molecule-plugins/issues/239
"boto",
"boto3",
"netaddr",
]

[tool.hatch.envs.molecule.scripts]
init = "terraform -chdir=tests/terraform init"
setup = "terraform -chdir=tests/terraform apply --auto-approve"
teardown = "terraform -chdir=tests/terraform destroy --auto-approve"
subnet = "terraform -chdir=tests/terraform output"
export-subnet = "echo 'export TEST_VPC_SUBNET_ID='$(terraform -chdir=tests/terraform output public_subnet)"
export-security-group = "echo 'export TEST_VPC_SECURITY_GROUP='$(terraform -chdir=tests/terraform output security_group)"

[build-system]
requires = [
"hatchling",
Expand Down
121 changes: 121 additions & 0 deletions tests/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Copyright 2024 Cloudera, Inc.
#
# 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.

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.70.0"
}
random = {
source = "hashicorp/random"
version = "3.6.3"
}
}
}

locals {
resource_name = "molecule-${random_string.molecule.id}"
}

provider "aws" {
default_tags {
tags = {
Name = "${local.resource_name}"
project = "Molecule testing"
terraform-run-id = "${random_string.molecule.id}"
}
}
}

resource "random_string" "molecule" {
length = 6
special = false
numeric = false
upper = false
}

resource "aws_vpc" "molecule" {
enable_dns_support = true
cidr_block = "10.0.0.0/24"
}

resource "aws_internet_gateway" "molecule" {
vpc_id = aws_vpc.molecule.id
}

resource "aws_default_route_table" "molecule" {
default_route_table_id = aws_vpc.molecule.default_route_table_id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.molecule.id
}
}

resource "aws_subnet" "molecule" {
vpc_id = aws_vpc.molecule.id

cidr_block = "10.0.0.0/28"
map_public_ip_on_launch = true
}

resource "aws_route_table_association" "molecule" {
subnet_id = aws_subnet.molecule.id
route_table_id = aws_vpc.molecule.default_route_table_id
}

resource "aws_security_group" "molecule" {
name = local.resource_name
description = "Allow all traffic within security group"
vpc_id = aws_vpc.molecule.id
}

resource "aws_vpc_security_group_ingress_rule" "allow_ssh" {
security_group_id = aws_security_group.molecule.id
description = "Allow inbound SSH traffic"
cidr_ipv4 = "0.0.0.0/0"
from_port = 22
ip_protocol = "tcp"
to_port = 22
tags = {
Name = "${local.resource_name}"
project = "Molecule testing"
terraform-run-id = "${random_string.molecule.id}"
}

}

resource "aws_vpc_security_group_ingress_rule" "allow_intra" {
security_group_id = aws_security_group.molecule.id
description = "Allow all intra-security group traffic"
referenced_security_group_id = aws_security_group.molecule.id
ip_protocol = -1
tags = {
Name = "${local.resource_name}"
project = "Molecule testing"
terraform-run-id = "${random_string.molecule.id}"
}
}

resource "aws_vpc_security_group_egress_rule" "allow_all_traffic_ipv4" {
security_group_id = aws_security_group.molecule.id
cidr_ipv4 = "0.0.0.0/0"
ip_protocol = "-1" # semantically equivalent to all ports
tags = {
Name = "${local.resource_name}"
project = "Molecule testing"
terraform-run-id = "${random_string.molecule.id}"
}
}
23 changes: 23 additions & 0 deletions tests/terraform/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2024 Cloudera, Inc.
#
# 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.

output "public_subnet" {
description = "Subnet ID for the test subnet"
value = aws_subnet.molecule.id
}

output "security_group" {
description = "Security Group name for SSH and intra-network test traffic"
value = aws_security_group.molecule.name
}
Loading