Obtain all associated revisions via store's API

In CI we sometimes need to obtain a mapping of released charms and associated resources, for example: obtaining artifacts for air-gapped deployments. This can be accomplished using charmcraft or the store’s API directly.

Using charmcraft status --format=json is fine, but:

  • the schema of charmcraft’s output is different from the official charmhub schema;
  • to be able to use this in CI you still need to login/provide credentials, so it’s not too different from using the store’s API directly.

Using the store’s API directly

Following the Self-service creation of tracks guide, first save credentials to file:

charmcraft login --export charmhub-creds.dat
export CHARMHUB_MACAROON_HEADER="Authorization: Macaroon $(base64 -d charmhub-creds.dat | jq -r .v)"

And now you can use curl to query revisions per channel and base:

curl -s -H'Content-type: application/json' \
  -H "$CHARMHUB_MACAROON_HEADER" \
  https://api.charmhub.io/v1/charm/grafana-agent-k8s/releases \
  | jq '."channel-map" | .[]' \
  | jq 'select(.channel == "latest/edge")' \
  | jq 'select(.base.channel == "22.04")' \
  | jq 'select(.base.architecture == "amd64")' \
  | jq '{revision, resources: (.resources | map({(.name): (.revision)}) | add)}'
{
  "revision": 64,
  "resources": {
    "agent-image": 38
  }
}

The same query for a multi-workload charm (grafana-k8s):

curl -s -H'Content-type: application/json' \
  -H "$CHARMHUB_MACAROON_HEADER" \
  https://api.charmhub.io/v1/charm/grafana-k8s/releases \
  | jq '."channel-map" | .[]' \
  | jq 'select(.channel == "latest/edge")' \
  | jq 'select(.base.channel == "20.04")' \
  | jq 'select(.base.architecture == "amd64")' \
  | jq '{revision, resources: (.resources | map({(.name): (.revision)}) | add)}'
{
  "revision": 106,
  "resources": {
    "grafana-image": 68,
    "litestream-image": 43
  }
}

Note: all the jq calls can be consolidated into a single query:

jq '."channel-map" | .[] | select(.channel == "latest/edge" and .base.channel == "22.04" and .base.architecture == "amd64") | {revision, resources: (.resources | map({(.name): (.revision)}) | add)}'

Update: using Juju, no auth is needed

(h/t Andy Wu)

Using juju, it is possible to obtain all the above information without charmcraft login:

juju info grafana-k8s --channel=edge --format=json \
  | jq  '.channels.latest.edge'
[
  {
    "track": "latest",
    "risk": "edge",
    "version": "106",
    "revision": 106,
    "released-at": "2024-03-14T14:55:10.180329+00:00",
    "size": 22711488,
    "architectures": [
      "amd64"
    ],
    "bases": [
      {
        "name": "ubuntu",
        "channel": "20.04"
      }
    ]
  }
]
juju charm-resources grafana-k8s --channel=edge --format=json \
  | jq 'map({(.name): .revision}) | add'
{
  "grafana-image": 68,
  "litestream-image": 43
}

However, there is a slight risk for a race if a release took place in between the two queries above.

4 Likes