========= Playbooks ========= Playbooks — called **Deployment Books** in the codebase — are the central automation mechanism in Eyrie. A Deployment Book is a serializable sequence of steps that interact with APIs, clusters, and other infrastructure to carry out operations like deploying, pausing, backing up, or restoring a deployment. What is a Deployment Book? ========================== A Deployment Book (``eyrie.deployment.book``) is a named, versioned record containing an ordered list of steps. Books are module-data friendly — they can be shipped as XML/CSV data in Odoo modules and updated through the normal module upgrade path. Key fields on a book: - **name** — human-readable label. - **version** — semver-style string. Changing the version auto-clones the previous version to preserve history. - **deployment_group_type** / **deployment_type** — filters which books are available for which group or deployment types. - **should_notify** — whether jobs created from this book send bus notifications. Books and Steps =============== Each book has ordered ``eyrie.deployment.book.step`` records. A step has: - **name** / **description** — for display in the portal job viewer. - **sequence** — determines execution order. - **step_type**: - ``none`` (Manual) — a placeholder or human-acknowledged step. - ``python_compute`` — executes the Python code in the ``python_compute`` field. - **estimated_duration** — seconds (``0`` = unknown). Overridden by historical averages during job serialization. - **estimated_duration_over_stop** — multiplier before a running step is considered timed out (default: 10×). Step Data Serialization ======================= A step can define ``python_serialize_job_step_data`` — Python code evaluated at job-creation time that populates a ``data`` dict. This data dict is then available to the step when it runs. Available variables during serialization: - ``self`` — the book step record. - ``job`` — the job being serialized. - ``data`` — a mutable dict; the step should set keys on this dict. - ``deployment``, ``deployment_group``, ``cluster`` — the scoped resources. - ``_logger``, ``datetime``, ``UserError`` — utilities. Step Applicability ================== The ``python_job_applies`` field contains a Python expression evaluated against the ``job`` variable. If it returns a falsy value, the step is skipped for that job. This lets you write conditional books — for example, skip a DNS step when no subdomain is configured. Nesting and Composability ========================= A step can point to a **child_book_id** (and optionally a **child_book_step_id**), effectively *calling* another book. When the job runner reaches such a step, it inlines the child book's steps into the current job. This is the primary composition mechanism: - **Example**: A "deploy" book should first pause the deployment via the pause book. So ``deploy_book.step_1.child_book_id = pause_book``. - **Encouragement**: Build small, reusable books and compose them into larger workflows. A backup book can be called from a deploy book, a restore book, or a scheduled cron — all without duplication. Versioning ========== When you change a book's ``version`` field, Eyrie automatically clones the previous version. The clone retains all steps and their configuration, giving you a full history of book revisions. Jobs reference the book at the version that was current when the job was created. Named Book Slots on Deployments ================================ Each deployment has named book slots that determine which book runs for each lifecycle action: - ``deployment_book_id`` — general-purpose book. - ``deployment_deploy_book_id`` — runs on **Deploy**. - ``deployment_pause_book_id`` — runs on **Pause**. - ``deployment_backup_book_id`` — runs on **Backup**. - ``deployment_restore_book_id`` — runs on **Restore**. - ``deployment_sync_ingress_book_id`` — runs on **Sync Ingress**. - ``deployment_upgrade_book_id`` — runs on **Upgrade**. - ``deployment_drop_book_id`` — runs on **Drop**. - ``deployment_config_scope_book_id`` — runs on scope configuration changes. The Principal ============= Playbooks and their steps become **serialized with scoped resources** — a cluster, deployment, or deployment group — in context. This scoping is what allows a single book to adapt its behavior across environments: steps can check which cluster they are running against, whether the deployment is in a production scope, or whether a feature flag is set, and branch accordingly. To that end, it is useful and encouraged to "call" other books as steps so that you can **compose playbooks out of other playbooks**. The result is a library of small, tested books that snap together into arbitrarily complex workflows.