The Juju Charm Store

Juju includes a charm store where charms and bundles can be uploaded, released (published), and optionally shared with other users.

The charm store is broken down into two main sections: Recommended and Community. Recommended charms have been vetted and reviewed by a Juju Charmer and all updates to the charm are also vetted prior to landing. Community charms have been shared by members of the community, but were not submitted by and have not been vetted by Juju Charmers.

Note: In order to interact with the charm store you will need the latest charm command, an Ubuntu SSO account, and you must have logged in to Launchpad at least once.

Log in to the store

It is required that you first log in to the Charmstore before you attempt to log in via charm login. After logging in via your browser, you can use the charm command line tool.

Most charm commands require authentication in order to operate. You can log in or log out of the store at any time by issuing charm login or charm logout respectively. During login you will be prompted for the following information:

  • Username - typically the email address used to access Ubuntu SSO
  • Password - Ubuntu SSO password
  • Two-factor auth - If enabled, enter two-factor authentication (2FA) information. Otherwise Return for None

Also note, if your group memberships change on Launchpad, you'll need to log out and log in via a browser to the Charmstore before those membership changes are recognized.

Entities explained

When a charm or bundle, referred to as entity from this point forward, is pushed for the first time to the store, the entity is named version 0 in the unreleased (unpublished) channel. Every revision of an entity lives in the unreleased channel. Subsequent pushes of different content to the store will automatically increment this number. So if an entity is changed and pushed 4 times, the revision history would look like this:

entity: 0---1---2---3

Channels group entity revisions into named streams. There are currently four released channels: edge, beta, candidate, and stable. Each channel also tracks history of revisions. When a revision is released to a channel, that channel pointer is changed and the history for the channel is updated.

Building on the previous example, when a user released revision 2 to the stable channel, the history would look like this:

                  stable (2)
                 /
entity: 0---1---2---3

If, then, revision 3 is released to the edge channel the history would look like this:

                  stable (2)
                 /
entity: 0---1---2---3
                     \
                      edge (3)

During this time, more revisions can be pushed to the default, unreleased channel. This represents general development iterations. As iterations are pushed during development, the stable and other channels are not updated.

                  stable (2)
                 /
entity: 0---1---2---3---4---5---6
                     \
                      edge (3)

The author can, at any time, release a revision to a channel. Revisions can also exist in the same channel at the same time. For example, the author chooses to release revision 3 to the stable channel without updating the edge channel:

                      stable (3, 2)
                     /
entity: 0---1---2---3---4---5---6
                     \
                      edge (3)

In doing so, the stable channel is updated to point to revision 3 and revision 3 is added to the channel history. The author can continue to push and release. Since revisions are a constant stream there are scenarios where the stable channel may be pointed to a higher revision even though edge revision is actually newer.

In the following example revision 8 is edge, a bug is found in the latest stable revision (5) so a hot fix is applied and pushed as 9. That revision is then released to the stable channel, like this:

                                              stable (9, 5, 3, 2)
                                             /
entity: 0---1---2---3---4---5---6---7---8---9
                                         \
                                          edge (8, 3)

While authors can release older versions to the channels it is not encouraged. For example, an author could mistakenly release revision 10 to the stable channel and not edge, then the author could re-release revision 9 to stable:

                                              stable (9, 10, 9, 5, 3, 2)
                                             /
entity: 0---1---2---3---4---5---6---7---8---9---10
                                         \
                                          edge (8, 3)

If a user managed to deploy that first mistaken revision during the time it was available, they would later be notified of an "upgrade" by Juju which will effectively downgrade the charm back to revision 9.

Pushing to the store

After building a charm or bundle, navigate to it's directory on disk and push it to the store.

cd src/charms/foobar
charm push .

The charm push command will return the full ID for the pushed item. Since this is the first time foobar was pushed, the output of the command is:

cs:~USER/foobar-0

If a charm or bundle id is not provided, they will default to cs:~USER/NAME where USER is the User from the output of charm whoami and NAME is the metadata.yaml name for charms and directory basename for bundles.

To define a series or different bundle name an id can be provided during push. The following is a set of different support permutations given the following charm whoami output:

User: kirk
Group membership: charm-examples

User kirk can perform the following operations:

charm push .
charm push . charm-name
charm push . bundle/bundle-name
charm push . ~charm-examples/charm-name
charm push . cs:~charm-examples/charm-name

Push will always increment the charm version in the unreleased channel.

Releasing to channels

The charm store supports four released channels: edge, beta, candidate, and stable. Revisions are associated with channels by using the release charm command. Release is executed against an existing revision and places that revision as the channel pointer.

Given the following example:

$ charm push . foo
cs:~kirk/foo-9

The author could release foo-9 to either the stable or edge channel as follows, showing the commands for stable and edge respectively:

charm release cs:~kirk/foo-9
charm release cs:~kirk/foo-9 --channel edge

After running both commands, revision 9 exists in both the stable channel and the edge channel.

Sharing charms and bundles

All channels have read and write ACLs. By default, only the owner of the entity exists in these ACLs.

To update the ACL for an entity you must grant users an ACL to the channel you want them to access. By default, if you do not supply an entity when granting access, the recipient will receive only read access to the stable channel, as in this example where we grant james access to the stable channel of the cs:~kirk/foo entity.

charm grant cs:~kirk/foo james

If, instead you wanted to give write access to the edge channel to lars, you would issue the following command:

charm grant cs:~kirk/foo --channel edge --acl write lars

Finally, to make the entity available for all to consume, there is a special everyone user you can use to make an entity available to the general public.

charm grant cs:~kirk/foo everyone