Skip to main content

GitOps-driven Managed Infrastructure Framework

Project description

infranaut

GitOps-driven Managed Infrastructure Framework — a Python CLI that scaffolds and operates multi-client cloud infrastructure using OpenTofu/Terragrunt + Ansible.

Overview

infranaut generates and manages the directory structure, Terragrunt HCL files, and Ansible inventories for any number of projects deployed on Hetzner Cloud. Each project contains environments; each environment contains workloads.

workspace/
├── .env                    # GIT_USER, GIT_TOKEN, etc.
├── core/                   # Shared Terraform modules & Ansible roles
│   ├── opentofu/
│   └── ansible/
└── projects/
    └── acme/
        ├── opentofu/
        │   ├── _env.hcl
        │   ├── _root.hcl
        │   ├── dev/
        │   │   ├── env.hcl
        │   │   ├── network/
        │   │   └── gitlab/
        │   └── shared/
        │       └── ssh-keys/
        └── ansible/
            ├── ansible.cfg
            └── inventories/
                └── dev/
                    └── gitlab/

Supported workload types

Type Description
gitlab GitLab CE/EE server
kubernetes_cluster Multi-node k8s cluster (controlplanes + workers)
single_node Generic standalone server (Mattermost, Nextcloud, …)
multi_node Generic primary/secondary cluster
mail_server Postfix + Dovecot mail stack

Installation

From PyPI (production)

pip install infranaut

From source (development)

git clone https://gitlab.kopsengineering.com/ksoft/infrastructur/infranaut_ctl.git
cd infranaut_ctl
pip install -e ".[dev]"

Quick start

# 1 — Create a workspace and pull the shared core
infranaut init /srv/infra --core-provider https://gitlab.example.com/ksoft/infra-core.git

# 2 — Create a project
infranaut project create --name acme

# 3 — Add an environment
infranaut env create --project acme --name dev

# 4 — Add workloads
infranaut workload create --project acme --env dev --type gitlab
infranaut workload create --project acme --env dev --type kubernetes_cluster --name k8s
infranaut workload create --project acme --env dev --type single_node --name mattermost

# 5 — Fill in generated inputs.hcl and env.hcl, then deploy
infranaut deploy --project acme --env dev --workload gitlab

# 6 — Regenerate dynamic inventory after a Terraform apply
infranaut inventory generate --project acme --env dev --workload gitlab

Core providers

--core-provider controls what goes into core/ at infranaut init time.

Provider Effect
empty (default) Creates an empty core/ skeleton — add your own modules.
https://…/repo.git Clones the repo with --depth 1 into core/. Credentials are read from the workspace .env file: GIT_USER and GIT_TOKEN.

Git credentials are injected into the HTTPS URL automatically and are never printed to the console.

.env format for git provider

# workspace/.env
GIT_USER=my-ci-user
GIT_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx

Commands reference

infranaut init [PATH] [--core-provider PROVIDER]
infranaut project create --name NAME
infranaut project list
infranaut env create --project PROJECT --name ENV
infranaut env list --project PROJECT
infranaut workload create --project PROJECT --env ENV --type TYPE [--name NAME]
infranaut workload list --project PROJECT --env ENV
infranaut inventory generate --project PROJECT --env ENV --workload WORKLOAD
infranaut deploy --project PROJECT --env ENV [--workload WORKLOAD]
infranaut version

Development workflow

Prerequisites

  • Python 3.11+
  • pip install -e ".[dev]"

Run tests

pytest tests/ -v

Lint

ruff check infranaut/
ruff format infranaut/

Smoke test (full end-to-end, no cloud)

mkdir -p /tmp/smoke && cd /tmp/smoke
infranaut init .
infranaut project create --name acme
infranaut env create --project acme --name dev
infranaut workload create --project acme --env dev --type gitlab
infranaut workload create --project acme --env dev --type kubernetes_cluster --name k8s
infranaut workload create --project acme --env dev --type single_node --name mattermost
infranaut workload create --project acme --env dev --type multi_node --name app
infranaut workload create --project acme --env dev --type mail_server
infranaut workload list --project acme --env dev

Release workflow

infranaut uses semantic versioning. Releases are triggered by pushing a vX.Y.Z tag; GitLab CI builds and publishes to PyPI automatically.

Steps

1. Bump the version in two files:

# infranaut/__init__.py
__version__ = "0.4.0"
# pyproject.toml
version = "0.4.0"

2. Commit and tag:

git add infranaut/__init__.py pyproject.toml
git commit -m "chore: bump version to 0.4.0"
git tag v0.4.0
git push origin dev
git push origin v0.4.0

The CI pipeline runs automatically:

  • lint — ruff style check (non-blocking)
  • test — pytest unit tests
  • smoke-test — full CLI end-to-end without cloud access
  • publish-pypi — builds sdist + wheel, publishes to PyPI via PYPI_TOKEN

Required CI/CD variable

In GitLab → Settings → CI/CD → Variables:

Variable Type Description
PYPI_TOKEN Masked PyPI API token with publish scope

Test procedure — fresh server

Run this after each release to validate the published package on a clean machine.

# 1. Install from PyPI (no local checkout)
pip install infranaut==0.4.0

# 2. Verify the CLI is reachable
infranaut version
infranaut --help

# 3. Initialise a workspace with the empty core
mkdir -p /tmp/infra-test && cd /tmp/infra-test
infranaut init .
# Expected: workspace marker created, core/ skeleton present

# 4. Create a project and environment
infranaut project create --name acme
infranaut env create --project acme --name dev
infranaut env create --project acme --name prod

# 5. Create all workload types
infranaut workload create --project acme --env dev --type gitlab
infranaut workload create --project acme --env dev --type kubernetes_cluster --name k8s
infranaut workload create --project acme --env dev --type single_node --name mattermost
infranaut workload create --project acme --env dev --type multi_node --name backend
infranaut workload create --project acme --env dev --type mail_server

# 6. Check the generated tree
find /tmp/infra-test/projects/acme -type f | sort

# 7. Verify key generated files exist and are non-empty
test -f projects/acme/opentofu/_env.hcl                            && echo "OK _env.hcl"
test -f projects/acme/opentofu/dev/env.hcl                         && echo "OK env.hcl"
test -f projects/acme/opentofu/dev/gitlab/terragrunt.hcl           && echo "OK gitlab terragrunt"
test -f projects/acme/opentofu/dev/k8s/terragrunt.hcl              && echo "OK k8s terragrunt"
test -f projects/acme/opentofu/dev/k8s/inputs.hcl                  && echo "OK k8s inputs"
test -f projects/acme/ansible/inventories/dev/gitlab/inventory.yml && echo "OK gitlab inventory"
test -f projects/acme/ansible/inventories/dev/k8s/inventory.yml    && echo "OK k8s inventory"
test -f projects/acme/ansible/inventories/dev/gitlab/site.yml      && echo "OK gitlab site.yml"

# 8. List projects and workloads (CLI consistency check)
infranaut project list
infranaut workload list --project acme --env dev

# 9. Test init with git core provider (requires git + valid token)
mkdir -p /tmp/infra-git && cd /tmp/infra-git
echo "GIT_USER=your-user" > .env
echo "GIT_TOKEN=your-token" >> .env
infranaut init . --core-provider https://gitlab.example.com/your-org/infra-core.git
# Expected: core/ contains the cloned repo content

# 10. Cleanup
rm -rf /tmp/infra-test /tmp/infra-git

What to check after each step:

  • No Python tracebacks
  • All OK lines printed in step 7
  • Generated HCL and YAML files have the correct project/env/workload names substituted
  • ansible.cfg, inventories/, group_vars/ directories created under ansible/

Project structure (infranaut_ctl)

infranaut_ctl/
├── infranaut/
│   ├── __init__.py
│   ├── main.py              # CLI entry point (Typer app)
│   ├── config.py            # Constants (workload types, etc.)
│   ├── core_provider.py     # Core init: empty or git clone
│   ├── renderer.py          # Jinja2 template renderer
│   ├── output_bridge.py     # Terraform → Ansible variable bridge
│   ├── commands/
│   │   ├── init.py
│   │   ├── project.py
│   │   ├── env_workload.py
│   │   ├── inventory_cmd.py
│   │   └── deploy.py
│   └── templates/
│       ├── project/
│       │   ├── opentofu/    # _env.hcl, _root.hcl, env.hcl, envrc templates
│       │   └── ansible/     # ansible.cfg template
│       └── workloads/
│           ├── gitlab/
│           ├── kubernetes_cluster/
│           ├── single_node/
│           ├── multi_node/
│           ├── mail_server/
│           ├── network/
│           └── ssh_keys/
├── tests/
├── pyproject.toml
└── .gitlab-ci.yml

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infranaut-0.3.0.tar.gz (43.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infranaut-0.3.0-py3-none-any.whl (69.8 kB view details)

Uploaded Python 3

File details

Details for the file infranaut-0.3.0.tar.gz.

File metadata

  • Download URL: infranaut-0.3.0.tar.gz
  • Upload date:
  • Size: 43.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for infranaut-0.3.0.tar.gz
Algorithm Hash digest
SHA256 207841659f43061d0d5cef2ad8358791c86faa74024a91e059081fb14103738d
MD5 ac3208492cf7d5139c6c780164479eaa
BLAKE2b-256 de6e468759628af3ff0dfef0cad5fdab2bec99ecdcc71214c5edc52f1d1866a4

See more details on using hashes here.

File details

Details for the file infranaut-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: infranaut-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 69.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for infranaut-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dc68a06d6c6b35bca289829929c677a207088f84b2256547959bee80a1e6c463
MD5 2e74db02968f6eff664c859e0e801452
BLAKE2b-256 1673f906f948e7ea71dd4e190ecd1acd4ea4eba82860f229a3b626d3ffa211d2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page