Skip to content

How-to manage integrations

Integrations are a core part of Juju, allowing charms to connect and share data with each other. Here we cover how you can use goops to manage integrations.

1. Declare the relation endpoint

To integrate with another charm, declare the relations in your charm’s charmcraft.yaml file. Define a provides or requires endpoint including an interface name. By convention, the interface name should be unique in the ecosystem. Each relation must have an endpoint, which your charm will use to refer to the relation.

For example, to declare a relation with a PostgreSQL database, you can add the following to your charmcraft.yaml:

requires:
  db:
    interface: postgresql_client
    limit: 1

Note

For more information on the charmcraft.yaml charm definition, read the official charmcraft documentation.

2. Read and write relation data

You can manage relation data in two ways: directly using goops functions or indirectly using Charm Libraries.

In most cases, charms should not directly read and write to relation data. Instead, they should do so indirectly using Charm Libraries, which encapsulate the relation logic.

package charm

import (
    "github.com/gruyaume/charm-libraries/postgresql"
)

func GetDatabaseURL(relationName string) (string, error) {
    i := &postgresql.Integration{
        RelationName: relationName,
    }

    return i.GetDatabaseURL()
}

Option 2: Directly

goops provides functions to manage relations, allowing you to get relation IDs, list relation units, and set or get relation data. Those are the same functions that Juju exposes through hook commands.

For example, to get the database URL from a relation named db, you can use the following code:

package charm

import (
    "fmt"

    "github.com/gruyaume/goops"
)

func GetDatabaseURL(relationName string) (string, error) {
    relationIDs, err := goops.GetRelationIDs(relationName)
    if err != nil {
        return "", fmt.Errorf("could not get relation IDs: %w", err)
    }

    if len(relationIDs) == 0 {
        return "", fmt.Errorf("no relation IDs found for %s", relationName)
    }

    relationID := relationIDs[0]

    relationUnits, err := goops.ListRelationUnits(relationID)
    if err != nil {
        return "", fmt.Errorf("could not get relation list: %w", err)
    }

    if len(relationUnits) == 0 {
        return "", fmt.Errorf("no relation units found for ID: %s", relationID)
    }

    relationData, err := goops.GetAppRelationData(relationID, relationUnits[0])
    if err != nil {
        goops.LogDebugf("Could not get relation data: %s", err.Error())
        return "", fmt.Errorf("could not get relation data for ID %s: %w", relationID, err)
    }

    endpoints, ok := relationData["endpoints"]
    if !ok {
        return "", fmt.Errorf("no endpoints found in relation data for ID %s", relationID)
    }

    return endpoints, nil
}

Info

Learn more about relation management in charms: