Skip to main content

Cally

A config as infrastructure foundation for your Internal Developer Platform

Why

To provide a powerful, but consisent configuration, and CLI to common Platform Engineering tasks

Features

  • Multi layered configuration provided by Dyanconf
  • Built-in testing harness
  • Unit testing for your IaC
  • Abstraction of the CDK for Terraform
  • Build Terraform JSON, for consumption by OpenTofu or Terraform

Concepts

Cally isn't intended to be consumed directly, but rather as a dependency of your internal IDP tool.

Python Packaging

To give a consistent experience across your Developers/Engineers/CI/CD, packaging your tooling, and providers, should be vailable via your internal python registry.

Internal Registry options

This pyproject.toml example from our minimal example, is enough to produce an empty stack, or run our hello world exampe command.

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "minimal-idp"
version = "0.1.0"

dependencies = ["cally"]

requires-python = ">=3.8"
authors = [
  {name = "Example Org"},
]
description = "Example Cally Extension"

[tool.setuptools.packages.find]
include=["cally.*"]

[project.scripts]
minimal-idp = "cally.cli:cally"

[project.optional-dependencies]
test = [
  "black",
  "build",
  "mypy",
  "pytest",
  "pytest-black",
  "pytest-mypy",
  "pytest-ruff<0.3",  # 0.3 + 0.3.1 are currently not working
  "ruff",
]

[tool.black]
skip-string-normalization = true

[tool.pytest.ini_options]
testpaths = "tests"
addopts = "-p no:cacheprovider --black --mypy --ruff"
filterwarnings = [
    "ignore",
    "default:::cally.*",
    "default:::tests.*"
]

[tool.ruff]
preview = true

[tool.ruff.lint]
select = [
    # flake8
    "A", "ARG", "B", "BLE", "C4", "PIE", "RET", "SIM", "S",
    "F",  # pyflakes
    "N",  # pep8-nameing
    "PL", # pylint
    "E",  # error
    "W",  # warning
    "PTH", # pathlib
    "RUF", # ruff
]

Project Structure

Cally relies heavily on Python namespacing, and expects a structure following this convention:

├── cally
│   └── idp
│       ├── commands
│       │   ├── example.py
│       │   └── __init__.py
│       ├── defaults.py
│       ├── __init__.py
│       ├── py.typed
│       ├── resources
│       │   ├── __init__.py
│       │   └── random.py
│       └── stacks
│           ├── __init__.py
│           └── pets.py
├── cally.yaml
├── pyproject.toml
├── README.md
└── tests
    ├── __init__.py
    ├── test_cli.py
    ├── testdata
    │   └── random-pets.json
    └── test_stacks.py

Configuration

Cally is built on top of Dynaconf, with an opinionated loader. This can of course be overriden, however the default is intended to provide a robust, but flexible interface. By default it will load a cally.yaml in your current working directory, but is only necessary if you wish to pass configuration to your services.

Service

When configuring a service, you can pass in the service name via --service name or via the environment variable CALLY_SERVICE

Environment

When configuring a service, you can pass in the service name via --environment name or via the environment variable CALLY_ENVIRONMENT

Example cally.yaml

This is the expected layout of a cally.yaml. The layers have a resolution order, from left to right, with the last winning. Objects are combined as per Dynaconf's merging strategy.

defaults:
    provider:
        random:
            alias: foo
development:
    provider:
        random:
            alias: bar
    services:
        test-service:
            provider:
                random:
                    alias: this-wins
            stack_type: CallyStack
            stack_vars:
                example: variable

The output of test service would look like

$ cally config print-service --environment development --service test-service
ENVIRONMENT: development
NAME: test-service
PROVIDER:
  random:
    alias: this-wins
STACK_TYPE: CallyStack
STACK_VARS:
  example: variabl

As a contrived example, this is what a tf print would output

{
  "//": {
    "metadata": {
      "backend": "local",
      "stackName": "test-service",
      "version": "0.20.5"
    },
    "outputs": {
    }
  },
  "terraform": {
    "backend": {
      "local": {
        "path": "state/development/test-service"
      }
    }
  }
}

Defaults

The cally loader will attempt to load your projects defaults, from the DEFAULTS key, from the defaults namespace in your project.

From the earlier example project layout, a defaults.py with the following contents

DEFAULTS = {
    "providers": {
        'random': {
            'alias': 'minimal'
        }
    }
}

Would result in the random provider being configured with an alias default of minimal

Notes

This project is still in its early stages, documentation will be the next focal point, along with any bugs/oversights not found during early development.

Release files for cally 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cally 0.6.0
File Size Uploaded
cally-0.6.0.tar.gz 31.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cally 0.6.0
File Interpreter ABI Platform
cally-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 66.3 kB

Release files / cally-0.6.0.tar.gz

Download URL cally-0.6.0.tar.gz
Size 31.9 kB
Tags Source
SHA-256 checksum
How to use checksums
0bf754da7807033ae0a3a2350fd8a99341ba18c89023211ed668183e0f749976
BLAKE2b-256 checksum
How to use checksums
8257668ecbb47140ee50897686497569d943ed6d6aedc61967d9d106bc2d50d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.1.1 CPython/3.12.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 1, 2024.

Transparency log

Release files / cally-0.6.0-py3-none-any.whl

Download URL cally-0.6.0-py3-none-any.whl
Size 34.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9692cab7a1b339dbba85a09b2b41e76252a1ee68f841be964892552a683ae019
BLAKE2b-256 checksum
How to use checksums
c6ce97bf69a823aa8de7362ece5028cc8e2eb3aacda7b38b412773c281597cb1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.1.1 CPython/3.12.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 1, 2024.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page