Juju documentation

Interfaces

One of the best aspects of juju is how dead-simple it is to write a charm. You write a handful of hooks in your favorite language and then go to town. However, there's a subtle hump in the charming learning curve... interfaces.

Interface names are what juju checks when trying to determine if two services can be related. For example, wordpress's metadata.yaml contains:

requires:
  database:
    interface: mysql

which is a statement that wordpress has a relation that's locally named "database" which is an implementation of the "mysql" interface.

Mysql's metadata.yaml contains a not-too-surprising:

provides:
  db:
    interface: mysql

When services are related, Juju decides which hooks to call within each charm based on this local relation name. When wordpress is related to mysql, the "database-relation-joined, database-relation-changed, etc" hooks are called on the wordpress end. Corresponding hooks will be called on the mysql end "db-relation-joined, db-relation-changed" (based on the mysql relation names).

Juju decides which services can be related based on the interface names only. They have to match.

At the end of the day, what's a juju interface? Simply a name.

Now, having gotten that out of the way, there is an _implicit_ notion of an interface that charmers have to pay attention to in addition to just matching names.

In some sense, relations are two-way channels of communications between services. They're not actually talking directly, the agents communicate via the state server, but it helps to think of it as direct communication between the services. Relation hooks can call tools such as relation-get and relation-set to pass information back and forth between the service endpoints.

For example, wordpress and mysql might have a conversation like the following:

wordpress:
  I'm here and my service name is "wordpress"

mysql:
  I'm here, let me create a db for you
  your database/schema name is "wordpress"
  your credentials are "admin/pass1234"
  you access the db on "my.host.addr:port"

wordpress:
  cool, let me write the wordpress config files needed to access that database (and bounce the server to pick up those changes)
  later

mysql:
  cool, later

We'll go over some more detailed versions of this, but this is the high-level conversation that occurs between two services when they are related in a relation implementing the mysql interface.

At first glance, it would appear that the interface called mysql might be defined simply by the set of variables that get passed along the channel. Something like:

interface:
  name: mysql
  variables_set:
    - service_name
    - database_host
    - database_port
    - database_name
    - database_user
    - database_password

but really, that's not complete. In fact, it's not even enough information to implement hooks for a new service that needs to talk to mysql. The timing and sequencing are critical components of this conversation! They can't be left out.

So let's dig a little deeper into this interface. Consider only the relation-joined and relation-changed hooks for now. The remaining broken and departed hooks are covered elsewhere.

Actually, if we start from provisioning, the hooks that are called for wordpress are

# juju deploy wordpress

install
config-changed
start

# juju add-relation wordpress mysql

database-relation-joined

database-relation-changed

similarly, for mysql

# juju deploy mysql

install
config-changed
start

# juju add-relation wordpress mysql

db-relation-joined

db-relation-changed

and we can fill in a little of what the relation hooks are doing

# wordpress

database-relation-joined
  <no-op>

database-relation-changed
  relation-get database_name, creds, host/port
  write config for wordpress
  bounce wordpress
# mysql

db-relation-joined
  relation-get service-name
  create db, creds
  relation-set db, creds, host/port

database-relation-changed
  <no-op>

This conversation is the actual interface.

Interface Documentation

Although we have described above that interfaces arrive by convention, there are several well-used interfaces which have enough implementations to define a defacto standard.

Below is a list of the interfaces for which we have compiled documentation and reference implementations.

  • mysql - the database interface used by MySQL and client services.