Skip to main content

A Pulumi dynamic provider for managing Lagoon resources

Project description

Pulumi Lagoon Provider

Tests Python 3.8+ License

A Pulumi dynamic provider for managing Lagoon resources as infrastructure-as-code.

Overview

This provider enables you to manage Lagoon hosting platform resources (projects, environments, variables, etc.) using Pulumi, bringing infrastructure-as-code practices to your Lagoon workflows.

Status: ๐Ÿšง Early Development / Proof of Concept

Features

  • Declarative Configuration: Manage Lagoon resources alongside your AWS/Kubernetes infrastructure
  • State Management: Pulumi tracks resource state and detects drift
  • Type Safety: Python type hints for better IDE support
  • GitOps Ready: Version control your Lagoon configurations

Supported Resources

Core Resources (Complete)

  • LagoonProject - Manage Lagoon projects
  • LagoonEnvironment - Manage environments (branches/PRs)
  • LagoonVariable - Manage project and environment variables

Deploy Target Resources (Complete)

  • LagoonDeployTarget - Manage Kubernetes cluster deploy targets
  • LagoonDeployTargetConfig - Configure project deployment routing to specific clusters based on branch patterns

Planned

  • LagoonGroup - Manage user groups and permissions
  • LagoonNotification - Manage notification integrations
  • LagoonTask - Manage tasks and backups

Quick Start - Complete Test Environment

Set up a complete local development environment with Kind cluster, Lagoon, and the provider:

# Clone the repository
git clone https://github.com/tag1consulting/pulumi-lagoon-provider.git
cd pulumi-lagoon-provider

# Option 1: Use the setup script (recommended)
./scripts/setup-complete.sh

# Option 2: Use Make
make setup-all

# After setup, deploy the example project
make example-up

What gets created:

  • Kind Kubernetes cluster (lagoon)
  • Lagoon Core (API, UI, Keycloak, RabbitMQ, databases)
  • Harbor container registry
  • Ingress controller with TLS
  • Python virtual environment with provider installed
  • Example project ready to deploy

Total setup time: ~15-20 minutes

Installation (Manual)

# Clone the repository
git clone https://github.com/tag1consulting/pulumi-lagoon-provider.git
cd pulumi-lagoon-provider

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install in development mode
pip install -e .

Configuration

For the local test cluster (after running setup):

# The example project handles this automatically via the run-pulumi.sh wrapper
cd examples/simple-project
./scripts/run-pulumi.sh up

For external Lagoon instances, use environment variables (recommended for dynamic providers):

export LAGOON_API_URL=https://api.lagoon.example.com/graphql
export LAGOON_TOKEN=YOUR_TOKEN

Note: Dynamic providers run in a subprocess and cannot access Pulumi config secrets. Always use environment variables for LAGOON_TOKEN.

Usage

import pulumi
import pulumi_lagoon as lagoon

# Create a Lagoon project
project = lagoon.LagoonProject("my-drupal-site",
    name="my-drupal-site",
    git_url="git@github.com:org/repo.git",
    deploytarget_id=1,
    production_environment="main",
    branches="^(main|develop|stage)$",
    pullrequests="^(PR-.*)",
)

# Create production environment
prod_env = lagoon.LagoonEnvironment("production",
    project_id=project.id,
    name="main",
    environment_type="production",
    deploy_type="branch",
)

# Add environment variable
db_config = lagoon.LagoonVariable("database-host",
    project_id=project.id,
    environment_id=prod_env.id,
    name="DATABASE_HOST",
    value="mysql.production.example.com",
    scope="runtime",
)

# Export project details
pulumi.export("project_id", project.id)
pulumi.export("production_url", prod_env.route)

Examples

See the examples/ directory for complete examples:

  • simple-project/ - Use the Lagoon provider to create projects/environments/variables via API
  • single-cluster/ - Deploy complete Lagoon stack to a single Kind cluster
  • multi-cluster/ - Production-like deployment with separate prod/nonprod Kind clusters

Multi-Cluster Example

The multi-cluster example demonstrates a production-like Lagoon deployment with:

  • Production cluster (lagoon-prod): Lagoon core services, Harbor registry, and production workloads
  • Non-production cluster (lagoon-nonprod): Development/staging workloads that connect to prod core
  • Deploy Target Configs: Route deployments to the appropriate cluster based on branch patterns
    • main branch โ†’ production cluster
    • develop, feature/* branches โ†’ non-production cluster
    • Pull requests โ†’ non-production cluster
# Deploy the multi-cluster environment
make multi-cluster-deploy

# Verify deployment
make multi-cluster-verify

# Access information (URLs, credentials)
cd examples/multi-cluster && make show-access-info

The example creates a complete Drupal project with multi-cluster routing configured automatically.

Importing Existing Resources

You can import existing Lagoon resources into Pulumi state using pulumi import. This is useful when adopting infrastructure-as-code for existing Lagoon projects.

Import ID Formats

Resource Import ID Format Example
LagoonProject {numeric_id} pulumi import lagoon:index:Project my-project 123
LagoonDeployTarget {numeric_id} pulumi import lagoon:index:DeployTarget my-target 1
LagoonEnvironment {project_id}:{env_name} pulumi import lagoon:index:Environment my-env 123:main
LagoonVariable {project_id}:{env_id}:{var_name} pulumi import lagoon:index:Variable my-var 123:456:DATABASE_HOST
LagoonVariable (project-level) {project_id}::{var_name} pulumi import lagoon:index:Variable my-var 123::API_KEY
LagoonDeployTargetConfig {project_id}:{config_id} pulumi import lagoon:index:DeployTargetConfig my-config 123:5

Finding Resource IDs

Use the Lagoon CLI to find resource IDs:

# List projects and their IDs
lagoon list projects

# Get project details including environment IDs
lagoon get project --project my-project

# List variables for a project
lagoon list variables --project my-project

Import Examples

# Import an existing project (ID 123)
pulumi import lagoon:index:Project my-site 123

# Import an environment named "main" from project 123
pulumi import lagoon:index:Environment prod-env 123:main

# Import a project-level variable
pulumi import lagoon:index:Variable api-key 123::API_KEY

# Import an environment-level variable (project 123, environment 456)
pulumi import lagoon:index:Variable db-host 123:456:DATABASE_HOST

# Import a deploy target config
pulumi import lagoon:index:DeployTargetConfig routing-config 123:5

After importing, you'll need to add the corresponding resource definition to your Pulumi code.

Development

Prerequisites

  • Python 3.8 or later
  • Pulumi CLI
  • Docker (for local test cluster)
  • kind CLI (for local test cluster)
  • kubectl

Quick Setup

# Complete automated setup (creates Kind cluster, installs Lagoon, provider)
make setup-all

# Or just install the provider for use with existing Lagoon
make venv provider-install

Make Targets

# Setup
make setup-all          # Complete setup: venv, provider, Kind cluster, Lagoon, user, deploy target
make venv               # Create Python virtual environment
make provider-install   # Install provider in development mode
make cluster-up         # Create Kind cluster + deploy Lagoon via Pulumi
make cluster-down       # Destroy Kind cluster and Lagoon resources

# Lagoon Setup (called by setup-all)
make ensure-lagoon-admin   # Create lagoonadmin user in Keycloak
make ensure-deploy-target  # Create deploy target in Lagoon + set Pulumi config

# Example Project (simple-project)
make example-setup      # Initialize example Pulumi stack
make example-preview    # Preview changes (auto token refresh)
make example-up         # Deploy example resources (auto token refresh)
make example-down       # Destroy example resources
make example-output     # Show stack outputs

# Multi-cluster Example
make multi-cluster-up       # Create prod + nonprod Kind clusters with full Lagoon stack:
                            #   - prod cluster: lagoon-core + lagoon-remote + Harbor
                            #   - nonprod cluster: lagoon-remote only (connects to prod core)
make multi-cluster-down     # Destroy multi-cluster environment
make multi-cluster-preview  # Preview multi-cluster changes
make multi-cluster-status   # Show multi-cluster stack outputs
make multi-cluster-clusters # List all Kind clusters

# Cleanup
make clean              # Kill port-forwards, remove temp files
make clean-all          # Full cleanup: clean + destroy cluster + remove venvs

# Status
make cluster-status     # Show cluster and Lagoon status
make help               # Show all available targets

Note: All targets that interact with Lagoon automatically handle:

  • Port-forward setup (temporary, cleaned up after)
  • Token refresh (5-minute token expiration handled)
  • Direct Access Grants enablement in Keycloak
  • User and deploy target creation (if needed)

Manual Setup

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Install in development mode
pip install -e .

# Run tests
pytest tests/

Project Structure

pulumi-lagoon-provider/
โ”œโ”€โ”€ pulumi_lagoon/           # Main provider package
โ”‚   โ”œโ”€โ”€ __init__.py         # Package exports
โ”‚   โ”œโ”€โ”€ client.py           # Lagoon GraphQL API client
โ”‚   โ”œโ”€โ”€ config.py           # Provider configuration
โ”‚   โ”œโ”€โ”€ exceptions.py       # Custom exceptions
โ”‚   โ”œโ”€โ”€ validators.py       # Input validation
โ”‚   โ”œโ”€โ”€ project.py          # LagoonProject resource
โ”‚   โ”œโ”€โ”€ environment.py      # LagoonEnvironment resource
โ”‚   โ”œโ”€โ”€ variable.py         # LagoonVariable resource
โ”‚   โ”œโ”€โ”€ deploytarget.py     # LagoonDeployTarget resource
โ”‚   โ””โ”€โ”€ deploytarget_config.py  # LagoonDeployTargetConfig resource
โ”œโ”€โ”€ examples/
โ”‚   โ”œโ”€โ”€ simple-project/     # API usage example (assumes Lagoon exists)
โ”‚   โ”‚   โ”œโ”€โ”€ __main__.py     # Creates projects/environments/variables
โ”‚   โ”‚   โ””โ”€โ”€ scripts/        # Helper scripts
โ”‚   โ”œโ”€โ”€ single-cluster/     # Single Kind cluster deployment
โ”‚   โ”‚   โ”œโ”€โ”€ __main__.py     # Deploys full Lagoon stack
โ”‚   โ”‚   โ””โ”€โ”€ (symlinks)      # Reuses multi-cluster modules
โ”‚   โ””โ”€โ”€ multi-cluster/      # Production-like multi-cluster deployment
โ”‚       โ”œโ”€โ”€ __main__.py     # Two-cluster deployment
โ”‚       โ”œโ”€โ”€ clusters/       # Kind cluster management
โ”‚       โ”œโ”€โ”€ infrastructure/ # Ingress, cert-manager, CoreDNS
โ”‚       โ”œโ”€โ”€ lagoon/         # Lagoon core and remote
โ”‚       โ”œโ”€โ”€ registry/       # Harbor installation
โ”‚       โ””โ”€โ”€ tests/          # Unit tests for multi-cluster config (39 tests)
โ”œโ”€โ”€ scripts/                # Shared operational scripts
โ”œโ”€โ”€ tests/                  # Unit and integration tests
โ”œโ”€โ”€ memory-bank/            # Planning and architecture docs
โ”œโ”€โ”€ Makefile                # Top-level automation
โ””โ”€โ”€ README.md              # This file

Architecture

This is a Pulumi dynamic provider written in Python. It communicates with the Lagoon GraphQL API to perform CRUD operations on resources.

Key components:

  • Resource Definitions: User-facing classes (e.g., LagoonProject)
  • Provider Implementations: CRUD logic for each resource type
  • GraphQL Client: Handles API communication
  • Configuration: Manages API credentials and settings

For detailed architecture information, see memory-bank/architecture.md.

Roadmap

Phase 1: MVP (Complete)

  • Project setup and structure
  • GraphQL client implementation
  • Core resources (Project, Environment, Variable)
  • Basic examples with automation scripts
  • Test cluster setup via Pulumi (Kind + Lagoon)
  • Documentation

Phase 2: Deploy Targets & Multi-Cluster (Complete)

  • Comprehensive error handling
  • Unit tests (300+ tests, 95% coverage)
  • Integration test framework
  • CI/CD pipeline (GitHub Actions)
  • DeployTarget resource for Kubernetes cluster management
  • DeployTargetConfig resource for branch-based deployment routing
  • Multi-cluster example (prod/nonprod separation)
  • Two-phase deployment pattern (infrastructure first, then API-dependent resources)
  • CORS and TLS configuration for browser access with self-signed certificates
  • Comprehensive documentation for browser access setup

Phase 3: Production Ready (Current)

  • Additional resources (Group, Notification)
  • Advanced examples
  • PyPI package publishing
  • Community feedback integration

Phase 4: Native Provider (Future)

  • Go implementation
  • Multi-language SDK generation (Python, TypeScript, Go)
  • Enhanced performance

Contributing

This project is in early development. Contributions, feedback, and bug reports are welcome!

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

Apache License 2.0 - See LICENSE for details.

Resources

Support

For issues and questions:

Acknowledgments

Built for the Lagoon community by infrastructure engineers who believe in infrastructure-as-code.

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

pulumi_lagoon-0.1.0.tar.gz (37.3 kB view details)

Uploaded Source

Built Distribution

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

pulumi_lagoon-0.1.0-py3-none-any.whl (38.0 kB view details)

Uploaded Python 3

File details

Details for the file pulumi_lagoon-0.1.0.tar.gz.

File metadata

  • Download URL: pulumi_lagoon-0.1.0.tar.gz
  • Upload date:
  • Size: 37.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pulumi_lagoon-0.1.0.tar.gz
Algorithm Hash digest
SHA256 eb33302120614d65e3f9a7825b5069a1b05cc3135477910e444a466f6978f4d2
MD5 18b6ee57cb29511fa1bd654a9b0dc88b
BLAKE2b-256 a2188f148c6599fdf5eb2787662f256409f1a27100aacfba042ecf8eb5e7dded

See more details on using hashes here.

Provenance

The following attestation bundles were made for pulumi_lagoon-0.1.0.tar.gz:

Publisher: publish.yml on tag1consulting/pulumi-lagoon-provider

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pulumi_lagoon-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pulumi_lagoon-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 38.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pulumi_lagoon-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c57604d7aa1bcded149539128e0872612e00eab8e5e3f6f707d2d5e1506652f9
MD5 bf1bc01da6c2bf33ad5a5f43002fba7b
BLAKE2b-256 953ae5a529557534952d94236748345740efa702de3bf7439d6f84e09013495e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pulumi_lagoon-0.1.0-py3-none-any.whl:

Publisher: publish.yml on tag1consulting/pulumi-lagoon-provider

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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