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
6 changes: 6 additions & 0 deletions .checkov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
soft-fail: true
framework:
- terraform
skip-check:
- CKV_TF_1 # Ensure Terraform module sources use a commit hash
- CKV_TF_2 # Ensure Terraform module sources use a tag with a version number
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CI

on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]

permissions:
contents: write

jobs:
test:
name: Pre-commit Tests
runs-on: ubuntu-latest
container:
image: ghcr.io/makeitworkcloud/runner:latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Initialize OpenTofu
run: tofu init -backend=false

- name: Run tests
run: make test

release:
name: Create Release
runs-on: ubuntu-latest
needs: [test]
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# vim swap files
**/*.sw[po]

# Terraform state and lock files
**/.terraform.lock.hcl
**/.terraform

# IDE Folders
**/.vscode

# Mac Finder cache
**/.DS_Store
36 changes: 36 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: check-vcs-permalinks
- id: destroyed-symlinks
- id: detect-private-key
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.104.0
hooks:
- id: terraform_validate
args:
- --hook-config=--retry-once-with-cleanup=true
- --args=-no-color
- --tf-init-args=-reconfigure
- --tf-init-args=-upgrade
- id: terraform_tflint
args:
- --args=--minimum-failure-severity=error
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
- id: terraform_checkov
args:
- --args=--config-file __GIT_WORKING_DIR__/.checkov.yml
- id: terraform_fmt
args:
- --args=-no-color
- --args=-diff
- --args=-recursive
- id: terraform_docs
args:
- --args=--config=.terraform-docs.yml
16 changes: 16 additions & 0 deletions .terraform-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
formatter: "markdown"

output:
file: "README.md"
mode: inject

settings:
color: false
lockfile: false

sort:
enabled: true
by: name

recursive:
enabled: false
10 changes: 10 additions & 0 deletions .tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugin "terraform" {
enabled = true
preset = "recommended"
}

config {
call_module_type = "local"
force = false
disabled_by_default = false
}
44 changes: 44 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
SHELL := /bin/bash
TERRAFORM := $(shell which tofu)

.PHONY: help init test pre-commit-check-deps pre-commit-install-hooks

help:
@echo "Terraform Module targets"
@echo "------------------------"
@echo
@echo "\thelp: show this help text"
@echo "\tinit: run 'terraform init' (no backend)"
@echo "\ttest: run pre-commit checks"
@echo
@echo "One-time repo init targets"
@echo "--------------------------"
@echo
@echo "\tpre-commit-install-hooks: install pre-commit hooks"
@echo "\tpre-commit-check-deps: check pre-commit dependencies"
@echo

init:
@${TERRAFORM} init -backend=false -upgrade

test: .git/hooks/pre-commit
@pre-commit run -a

DEPS_PRE_COMMIT=$(shell which pre-commit || echo "pre-commit not found")
DEPS_TERRAFORM_DOCS=$(shell which terraform-docs || echo "terraform-docs not found")
DEPS_TFLINT=$(shell which tflint || echo "tflint not found")
DEPS_CHECKOV=$(shell which checkov || echo "checkov not found")
DEPS_JQ=$(shell which jq || echo "jq not found")
pre-commit-check-deps:
@echo "Checking for pre-commit and its dependencies:"
@echo " pre-commit: ${DEPS_PRE_COMMIT}"
@echo " terraform-docs: ${DEPS_TERRAFORM_DOCS}"
@echo " tflint: ${DEPS_TFLINT}"
@echo " checkov: ${DEPS_CHECKOV}"
@echo " jq: ${DEPS_JQ}"
@echo ""

pre-commit-install-hooks: .git/hooks/pre-commit

.git/hooks/pre-commit: pre-commit-check-deps
@pre-commit install --install-hooks
95 changes: 95 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# terraform-libvirt-domain

Terraform module for creating libvirt domains (VMs) with cloud-init and optional Ansible Automation Platform integration.

## Usage

```hcl
module "vm" {
source = "git::https://github.com/makeitworkcloud/terraform-libvirt-domain.git?ref=v1.0.0"

name = "my-vm"
description = "My virtual machine"
vcpu = 2
memory = 4096

cloudinit_meta_data_template = file("${path.module}/templates/meta-data.tpl")
cloudinit_meta_data_vars = { hostname = "my-vm" }
cloudinit_user_data_template = file("${path.module}/templates/user-data.tpl")
cloudinit_user_data_vars = {}
cloudinit_network_config_template = file("${path.module}/templates/network-config.tpl")
cloudinit_network_config_vars = { ip_address = "192.168.1.100" }

private_ip_addr = "192.168.1.100"
proxyhost = "bastion.example.com"
}
```

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3 |
| <a name="requirement_libvirt"></a> [libvirt](#requirement\_libvirt) | >= 0.9.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aap"></a> [aap](#provider\_aap) | n/a |
| <a name="provider_libvirt"></a> [libvirt](#provider\_libvirt) | >= 0.9.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| aap_host.host | resource |
| aap_job.job | resource |
| [libvirt_cloudinit_disk.commoninit](https://registry.terraform.io/providers/dmacvicar/libvirt/latest/docs/resources/cloudinit_disk) | resource |
| [libvirt_domain.vm](https://registry.terraform.io/providers/dmacvicar/libvirt/latest/docs/resources/domain) | resource |
| [libvirt_volume.boot](https://registry.terraform.io/providers/dmacvicar/libvirt/latest/docs/resources/volume) | resource |
| [libvirt_volume.cloudinit](https://registry.terraform.io/providers/dmacvicar/libvirt/latest/docs/resources/volume) | resource |
| [libvirt_volume.extra](https://registry.terraform.io/providers/dmacvicar/libvirt/latest/docs/resources/volume) | resource |
| aap_inventory.inventory | data source |
| aap_job_template.job_template | data source |
| aap_organization.org | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_aap_inventory_name"></a> [aap\_inventory\_name](#input\_aap\_inventory\_name) | Name of the AAP inventory to use. | `string` | `"libvirt-infra"` | no |
| <a name="input_aap_job_template_name"></a> [aap\_job\_template\_name](#input\_aap\_job\_template\_name) | Name of the AAP job template to run. If left empty, will default to configure\_<name> | `string` | `""` | no |
| <a name="input_aap_org_name"></a> [aap\_org\_name](#input\_aap\_org\_name) | Name of the Ansible Automation Platform (AAP) organization. | `string` | `"Default"` | no |
| <a name="input_boot_image_url"></a> [boot\_image\_url](#input\_boot\_image\_url) | URL for the base QCOW2 image used as the boot disk. | `string` | `"https://download.fedoraproject.org/pub/fedora/linux/releases/42/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-42-1.1.x86_64.qcow2"` | no |
| <a name="input_bridge_name"></a> [bridge\_name](#input\_bridge\_name) | Name of the network bridge for the second network interface. | `string` | `"nm-bridge"` | no |
| <a name="input_cloudinit_meta_data_template"></a> [cloudinit\_meta\_data\_template](#input\_cloudinit\_meta\_data\_template) | The template content for cloud-init meta-data configuration. | `string` | n/a | yes |
| <a name="input_cloudinit_meta_data_vars"></a> [cloudinit\_meta\_data\_vars](#input\_cloudinit\_meta\_data\_vars) | Variable map for the cloud-init meta-data template. | `map(string)` | n/a | yes |
| <a name="input_cloudinit_network_config_template"></a> [cloudinit\_network\_config\_template](#input\_cloudinit\_network\_config\_template) | The template content for cloud-init network configuration. | `string` | n/a | yes |
| <a name="input_cloudinit_network_config_vars"></a> [cloudinit\_network\_config\_vars](#input\_cloudinit\_network\_config\_vars) | Variable map for the cloud-init network configuration template. | `map(string)` | n/a | yes |
| <a name="input_cloudinit_user_data_template"></a> [cloudinit\_user\_data\_template](#input\_cloudinit\_user\_data\_template) | The template content for cloud-init user-data configuration. | `string` | n/a | yes |
| <a name="input_cloudinit_user_data_vars"></a> [cloudinit\_user\_data\_vars](#input\_cloudinit\_user\_data\_vars) | Variable map for the cloud-init user-data template. Set to {} if not used. | `map(string)` | n/a | yes |
| <a name="input_description"></a> [description](#input\_description) | Description for the libvirt domain (virtual machine). | `string` | `""` | no |
| <a name="input_enable_aap"></a> [enable\_aap](#input\_enable\_aap) | Whether to provision Ansible Automation Platform (AAP) resources for this domain. | `bool` | `false` | no |
| <a name="input_extra_volumes"></a> [extra\_volumes](#input\_extra\_volumes) | List of additional volumes to attach to the domain. Each object should contain:<br/> - name: Name of the volume.<br/> - size: Size of the volume in bytes.<br/>Example:<br/>[<br/> {<br/> name = "runner-var-lib-docker.qcow2"<br/> size = 107374182400<br/> }<br/>] | <pre>list(object({<br/> name = string<br/> size = number<br/> }))</pre> | `[]` | no |
| <a name="input_memory"></a> [memory](#input\_memory) | Amount of memory (in MB) to assign to the domain. | `number` | `2048` | no |
| <a name="input_name"></a> [name](#input\_name) | The name of the libvirt domain (virtual machine) and related resources. | `string` | n/a | yes |
| <a name="input_private_ip_addr"></a> [private\_ip\_addr](#input\_private\_ip\_addr) | Private IP address to assign to the VM (used for network config and inventory). | `string` | n/a | yes |
| <a name="input_proxyhost"></a> [proxyhost](#input\_proxyhost) | Proxy host for SSH connection, used in ansible\_ssh\_common\_args. | `string` | n/a | yes |
| <a name="input_storage_pool"></a> [storage\_pool](#input\_storage\_pool) | Name of the libvirt storage pool where volumes will be created. | `string` | `"default"` | no |
| <a name="input_vcpu"></a> [vcpu](#input\_vcpu) | Number of virtual CPUs to assign to the domain. | `number` | `1` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_boot_volume_id"></a> [boot\_volume\_id](#output\_boot\_volume\_id) | The ID of the boot volume |
| <a name="output_cloudinit_disk_id"></a> [cloudinit\_disk\_id](#output\_cloudinit\_disk\_id) | The ID of the cloud-init disk |
| <a name="output_domain_id"></a> [domain\_id](#output\_domain\_id) | The ID of the libvirt domain |
| <a name="output_domain_name"></a> [domain\_name](#output\_domain\_name) | The name of the libvirt domain |
<!-- END_TF_DOCS -->
Loading