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 before landing. Community charms have been shared by members of the community, but were not submitted by and have not been vetted by Juju Charmers.

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 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 histories 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 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

Sharing is independent of promulgating (making public as the recommended charm) to the Charm Store.

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

Promulgate your charm

When you have released your charm (or bundle) and you want to make it available to others as the recommended charm you will need to make a promulgation request. This is informally done via the “Charms and Charming” category on the Juju Discourse forum.

The ‘#juju’ IRC channel on Freenode and the above Discourse forum remain excellent resources for questions and comments regarding charm development and charm promulgation.

Promulgation notes

  • The Charm promulgation page contains information on what happens once the request is made.
  • It is the responsibility of the charm author (and maintainer) to test their charm to ensure it is of good quality and is secure.
  • Promulgation to the top level namespace of the Charm Store does not imply an endorsement by Canonical.
  • Charm authors are encouraged to use their personal or group namespace.

Can you add an example of publishing a new charm with a resource?

"Charm login" fails with 404 Error!

Tried with “charm logout & charm login”, but still the same error.

sk@dev:~$ charm login
ERROR cannot retrieve the authentication macaroon: unexpected response status from server: 404 NOT FOUND

sk@dev:~$ charm login --debug
ERROR cannot retrieve the authentication macaroon: unexpected response status from server: 404 NOT FOUND
04:27:41 DEBUG cmd supercommand.go:537 error stack:
/build/charm/parts/charmstore-client/go/pkg/mod/github.com/juju/charmrepo/v6@v6.0.0-20200817155725-120bd7a8b1ed/csclient/csclient.go:1162: unexpected response status from server: 404 NOT FOUND
/build/charm/parts/charmstore-client/go/pkg/mod/github.com/juju/charmrepo/v6@v6.0.0-20200817155725-120bd7a8b1ed/csclient/csclient.go:1048:
/build/charm/parts/charmstore-client/go/pkg/mod/github.com/juju/charmrepo/v6@v6.0.0-20200817155725-120bd7a8b1ed/csclient/csclient.go:1222: cannot retrieve the authentication macaroon

Do you need charmstore or is charmhub ok?

I use charmstore till now, but based on this FAQ, I persume to use charmhub to release the charms.

1 Like

Totally. I can try help you to get it right if you need. I haven’t tried adding a resource yet, but publishing should work.

It is still a tricky method to add docs for a published charm, so that part requires some walk thru. (Hope we can resolve this down the road)

@tmihoc and @facundo and @pedroleaoc are people you might also engage.

Thanks Erik,

What is the expectation of an already published charm in charmstore for the new revision? Observed that, ‘charmcraft names’ failed to list all the charms published to a team, but it list charms published under my user name.

@tmihoc @facundo @pedroleaoc

2 Likes

Hi there,

You can (and should) use charmcraft to upload new revisions to any charm, even those that existed in charmstore. Ownership was transferred when we did the migration.

I don’t know if charmcraft names will show you charms you’re a collaborator to (i.e. not the owner, but collaborators still have write privileges on charms). But, if you sign into https://charmhub.io and then go to https://charmhub.io/charms you will see the list of all the charms you own or are a collaborator to.

  • Daniel
3 Likes

Agree that, I could see the status with ‘charmcraft status namespace-CHARM

But I presume, I should change the structure of the charm too for building & uploading new revisions, (ex: reactive charms need to be under ‘src/’ now).

Also observed, “charmcraft build” has a dependency on LXD. I will have to upgrade that too( LXD ‘3.0.3’ does not meet the minimum required version ‘4.0’.)

You don’t need to modify your reactive charm to packing. See this doc about packing reactive charms.

You can always run charmcraft pack using --destructive-mode (which will change your system, though, so it’s better if you create an instance using your old LXD and run everything inside). But yes, it’s better to have an updated system and let charmcraft manage it automagically.

2 Likes

Hi there,

charm pack --destructive-mode works!

And I am able to release the charm now, without adding any structural changes(reactive charm) by adding the below piece in charmcraft.yaml, but I should keep the flattened charm name in the metadata.yaml file.

parts:
  charm:
    source: .
    plugin: reactive
    build-snaps: [charm]
1 Like