Skip to main content

The Python library behind great charms

Project description

The ops library

CI Status Publish

The ops library is a Python framework for developing and testing Kubernetes and machine charms. While charms can be written in any language, ops defines the latest standard, and charmers are encouraged to use Python with ops for all charms. The library is an official component of the Charm SDK, itself a part of the Juju universe.

Juju Learn how to quickly deploy, integrate, and manage charms on any cloud with Juju.
It's as simple as juju deploy foo, juju integrate foo bar, and so on -- on any cloud.
Charmhub Sample our existing charms on Charmhub.
A charm can be a cluster (OpenStack, Kubernetes), a data platform (PostgreSQL, MongoDB, etc.), an observability stack (Canonical Observability Stack), an MLOps solution (Kubeflow), and so much more.
👉 Charm SDK Write your own charm!
Juju is written in Go, but our SDK supports easy charm development in Python.

Give it a try

Let's use ops to build a Kubernetes charm:

Set up

See Charm SDK | Set up an Ubuntu charm-dev VM with Multipass.
Choose the MicroK8s track.

Write your charm

On your Multipass VM, create a charm directory and use Charmcraft to initialise your charm file structure:

mkdir ops-example
cd ops-example
charmcraft init

This has created a standard charm directory structure:

$ ls -R
.:
CONTRIBUTING.md  README.md        pyproject.toml    src    tox.ini
LICENSE          charmcraft.yaml  requirements.txt  tests

./src:
charm.py

./tests:
integration  unit

./tests/integration:
test_charm.py

./tests/unit:
test_charm.py

Things to note:

  • The charmcraft.yaml file shows that what we have is an example charm called ops-example, which uses an OCI image resource httpbin from kennethreitz/httpbin.

  • The requirements.txt file lists the version of ops to use.

  • The src/charm.py file imports ops and uses ops constructs to create a charm class OpsExampleCharm, observe Juju events, and pair them to event handlers:

import ops

class OpsExampleCharm(ops.CharmBase):
    """Charm the service."""

    def __init__(self, *args):
        super().__init__(*args)
        self.framework.observe(self.on['httpbin'].pebble_ready, self._on_httpbin_pebble_ready)
        self.framework.observe(self.on.config_changed, self._on_config_changed)

    def _on_httpbin_pebble_ready(self, event: ops.PebbleReadyEvent):
        """Define and start a workload using the Pebble API.

        Change this example to suit your needs. You'll need to specify the right entrypoint and
        environment configuration for your specific workload.

        Learn more about interacting with Pebble at at https://juju.is/docs/sdk/pebble.
        """
        # Get a reference the container attribute on the PebbleReadyEvent
        container = event.workload
        # Add initial Pebble config layer using the Pebble API
        container.add_layer("httpbin", self._pebble_layer, combine=True)
        # Make Pebble reevaluate its plan, ensuring any services are started if enabled.
        container.replan()
        # Learn more about statuses in the SDK docs:
        # https://juju.is/docs/sdk/constructs#heading--statuses
        self.unit.status = ops.ActiveStatus()

See more: ops.PebbleReadyEvent

  • The tests/unit/test_charm.py file imports ops.testing and uses it to set up a testing harness:
import ops.testing

class TestCharm(unittest.TestCase):
    def setUp(self):
        self.harness = ops.testing.Harness(OpsExampleCharm)
        self.addCleanup(self.harness.cleanup)
        self.harness.begin()

    def test_httpbin_pebble_ready(self):
        # Expected plan after Pebble ready with default config
        expected_plan = {
            "services": {
                "httpbin": {
                    "override": "replace",
                    "summary": "httpbin",
                    "command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
                    "startup": "enabled",
                    "environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
                }
            },
        }
        # Simulate the container coming up and emission of pebble-ready event
        self.harness.container_pebble_ready("httpbin")
        # Get the plan now we've run PebbleReady
        updated_plan = self.harness.get_container_pebble_plan("httpbin").to_dict()
        # Check we've got the plan we expected
        self.assertEqual(expected_plan, updated_plan)
        # Check the service was started
        service = self.harness.model.unit.get_container("httpbin").get_service("httpbin")
        self.assertTrue(service.is_running())
        # Ensure we set an ActiveStatus with no message
        self.assertEqual(self.harness.model.unit.status, ops.ActiveStatus())

See more: ops.testing.Harness

Explore further, start editing the files, or skip ahead and pack the charm:

charmcraft pack

If you didn't take any wrong turn or simply left the charm exactly as it was, this has created a file called ops-example_ubuntu-22.04-amd64.charm (the architecture bit may be different depending on your system's architecture). Use this name and the resource from the metadata.yaml to deploy your example charm to your local MicroK8s cloud:

juju deploy ./ops-example_ubuntu-22.04-amd64.charm --resource httpbin-image=kennethreitz/httpbin

Congratulations, you’ve just built your first Kubernetes charm using ops!

Clean up

See Charm SDK | Clean up.

Next steps

Learn more

Chat with us

Read our Code of conduct and:

File an issue

Make your mark

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

ops-2.14.1.tar.gz (446.2 kB view details)

Uploaded Source

Built Distribution

ops-2.14.1-py3-none-any.whl (165.7 kB view details)

Uploaded Python 3

File details

Details for the file ops-2.14.1.tar.gz.

File metadata

  • Download URL: ops-2.14.1.tar.gz
  • Upload date:
  • Size: 446.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for ops-2.14.1.tar.gz
Algorithm Hash digest
SHA256 2fc5b6aa63efb71b510a946f764c9321acec5e30b9ddc64ce88c6cd4f753a19c
MD5 3902cee51a6c1ebbdefd17104c44c4ca
BLAKE2b-256 3fd7a7a118cd6246f0f7dfac75dfdc26e8fccc12548977748103e97073cc7bd9

See more details on using hashes here.

File details

Details for the file ops-2.14.1-py3-none-any.whl.

File metadata

  • Download URL: ops-2.14.1-py3-none-any.whl
  • Upload date:
  • Size: 165.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for ops-2.14.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2ae45bf2442a0c814d1abffa25b103097088582b4fba4ea2c1d313828e278948
MD5 6ee11fa345e6214d1c4d90d60a936155
BLAKE2b-256 db3a7c78eaf6f25bb5c2a2cae2c85f11430352835340ffc3fa74dc82a15ce81b

See more details on using hashes here.

Supported by

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