Early draft: The wording in this piece is quite loose and I need to confirm a few details.
This is the conceptual process that charms go though when a charm is deployed. In reality, the flow is not linear. Nor is behaviour consistent between charms, as charm authors ultimately have some discretion about what happens and when.
juju deploy is executed, the controller takes on responsibility to ensure that the charm is deployed.
The controller will work to satisfy several conditions, irrespective of the model’s current state.
- A machine is available that satisfies the placement directive and any constraints placed
- A machine agent is operational on the machine
- A unit agent (
jujud unit) is operational on the machine
This process is resilient to many errors in the underlying infrastructure, such as the machine becoming inaccessible. Juju is not able to recover from all errors though. If the credentials delegated to the controller become invalid, Juju will be unable to proceed.
At this point, the controller downloads the charm’s contents from the charm store, then uploads the charm’s contents into the machine.
The code within the charm is responsible for:
- Installing its own dependencies (charms can depend on a base installation being available)
- Installing the workload and its dependencies. Charms are often responsible for multiple applications that are visible as operating system processes.
Sidebar: where is a charm?:
There is no process identifier (PID) that represents a charm.
There is however a “unit agent” per unit of an application. Unit agents appear with the process name “
jujud unit [...]”. Unit agents are responsible for monitoring the state of the system and executing their charm’s hooks when the situation demands it.
“Live” charms are virtual entities that are available via the
juju status command as “applications”. There is a 1:1 mapping between charm and application (in the Juju sense of the word). In object-oriented terminology, an application is an instance of a charm.
At this point, the charm is installed. Generally though, that’s not sufficient to start it successfully. Charms typically need data to enable them to write configuration file(s) and then to write a
systemd unit description file:
Successfully starting a charm (an application) may involve waiting for:
- Data provided by the user (
- Data provided by other charms via relations (
- Extra permissions (
- Explicit agreement to terms and conditions (
When a charm is waiting for something that’s necessary for you to provide, its application will show as being in the “blocked” state within
When a charm is waiting for data from a relation, it may show as “blocked” or “waiting”. “Blocked” means that you need to add a relation (& potentially deploy) an additional charm. “Waiting” means that the charm is waiting on other charms. No intervention is required.
Sidebar: what do you mean by the phrase data provided by other charms via relations?:
Juju provides a mechanism for charms to automatically negotiate their configuration: the relation. Within the charm’s source code, charms can send and receive values.
Sending a value involves invoking an executable “relation-set =”. That executable is a symbolic link to the unit agent and is one of several hook tools provided by the Juju system. The unit agent then sends the data to the controller. The controller then forwards that data on to any other charms that may later request it via the “relation-get ” hook tool.
A common example is needing to have a database to connect to before starting up a web application. The charm for the web application asks the database charm “please create database table webapp”. Once the database charm has established the table, it then sends back the access credentials to the requesting charm (via the controller).
The process of managing the application lifecycle of any processes that were installed by the charm is typically deferred to systemd. This usually involves filling in a templated configuration file with valid values and a systemd unit file.