con un clic
adding-actions
Implementing Juju actions for operational tasks in charms
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Implementing Juju actions for operational tasks in charms
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Known-good Juju bundle shapes (COS Lite, 12-Factor + COS, Identity Platform, Charmed Kubeflow) — canonical app lists and relation edges
Implementing Juju actions for operational tasks in charms. WHEN: add Juju actions to a charm, implement backup / rotate-credentials / restore actions, declare actions in charmcraft.yaml, write action handlers, test actions with Scenario, run actions with juju run.
Adding and validating charm configuration options. WHEN: add charm configuration options, declare config in charmcraft.yaml, validate config values in config-changed, apply config to a Pebble layer, apply config to a machine charm, write Scenario tests for config.
End-to-end workflow for building ops-framework charms for custom applications (K8s and machine). WHEN: build a custom Juju charm, write src/charm.py with Pebble, write a machine charm with systemd, decide K8s vs machine substrate, scaffold a non-paas-charm with charmcraft init, customise the ops framework charm lifecycle.
Workflow for charming infrastructure software (databases, caches, message brokers, proxies, monitoring). WHEN: charm infrastructure software, charm a database / cache / message broker / proxy / monitoring system, implement peer relations, leader election, primary/replica failover, backup and restore actions, clustering.
Expert guidance for developing, building, testing, and publishing Juju charms using charmcraft. WHEN: edit charmcraft.yaml, run charmcraft pack, run charmcraft init, manage charm libraries, publish a charm to Charmhub, set up multi-base builds, configure relations / config options, set up storage or containers.
| name | adding-actions |
| description | Implementing Juju actions for operational tasks in charms |
| globs | ["actions.yaml","charmcraft.yaml","metadata.yaml","src/charm.py","src/**/charm.py"] |
Juju actions are operator-triggered tasks — think "backup the database", "rotate credentials", or "dump debug info". They run on demand and return structured results.
juju run <unit> <action>Create or edit charmcraft.yaml to declare actions:
actions:
backup:
description: Create a backup of the application data.
params:
path:
type: string
description: Destination path for the backup file.
default: /var/backups
required: [path]
rotate-credentials:
description: Rotate database credentials and update all connected applications.
get-admin-password:
description: Retrieve the current admin password.
Juju action parameters use JSON Schema types:
string — text valuesinteger — whole numbersnumber — floating-point numbersboolean — true/falsearray — lists (with items specifying element type)object — nested structuresimport ops
class MyCharm(ops.CharmBase):
def __init__(self, framework: ops.Framework):
super().__init__(framework)
self.framework.observe(self.on.backup_action, self._on_backup)
self.framework.observe(
self.on.rotate_credentials_action,
self._on_rotate_credentials,
)
self.framework.observe(
self.on.get_admin_password_action,
self._on_get_admin_password,
)
def _on_backup(self, event: ops.ActionEvent):
path = event.params["path"]
try:
backup_id = self._perform_backup(path)
event.set_results({
"backup-id": backup_id,
"path": path,
"status": "success",
})
except FileNotFoundError:
event.fail(f"Backup path does not exist: {path}")
def _on_rotate_credentials(self, event: ops.ActionEvent):
if not self.unit.is_leader():
event.fail("Credential rotation must run on the leader unit.")
return
new_password = self._rotate_db_password()
event.set_results({"status": "rotated"})
def _on_get_admin_password(self, event: ops.ActionEvent):
password = self._get_stored_password()
event.set_results({"password": password})
For actions that take time, use progress logging:
def _on_backup(self, event: ops.ActionEvent):
event.log("Starting backup...")
# Phase 1
self._dump_database(event.params["path"])
event.log("Database dumped, compressing...")
# Phase 2
archive = self._compress_backup(event.params["path"])
event.log("Backup complete.")
event.set_results({"archive": str(archive)})
# Run with default parameters.
juju run my-charm/0 backup
# Run with parameters.
juju run my-charm/0 backup path=/mnt/backups
# Run on the leader.
juju run my-charm/leader get-admin-password
from ops import testing
def test_backup_action():
ctx = testing.Context(MyCharm)
state = testing.State()
out = ctx.run(ctx.on.action("backup", params={"path": "/data"}), state)
assert out.action_results["status"] == "success"
assert "backup-id" in out.action_results
def test_backup_action_invalid_path():
ctx = testing.Context(MyCharm)
state = testing.State()
out = ctx.run(ctx.on.action("backup", params={"path": "/nonexistent"}), state)
assert out.action_failure # Action called event.fail()
Actions are for operator-initiated tasks. Do not use actions for things that should happen automatically (use events/hooks for those).
Return structured results. Use event.set_results() with clear key-value pairs. Callers parse these programmatically.
Fail explicitly. Call event.fail("reason") with a descriptive message when an action cannot complete. Do not silently succeed.
Leader-only actions. Some actions (like credential rotation) should only run on the leader. Check self.unit.is_leader() and fail with a clear message if not.
Use hyphens in action names (e.g., rotate-credentials). Juju converts hyphens to underscores for the Python event name (rotate_credentials_action).
Document parameters clearly in the charmcraft.yaml actions section. Operators rely on juju actions my-charm to understand what is available.
my-action → self.on.my_action_action) and the requirement that every handler call event.set_results() or event.fail() are checked deterministically by charmlint (rules ACT006 and ACT007). Run charmlint to surface these — the skill body no longer recites them.