This document shows various ways in which you may interact with a charm or a bundle.
Query Charmhub for available charms / bundles
To query Charmhub for the charms / bundles that deliver a given application, run the find
command followed by a suitable keyword. For example, to find out the charms and/or bundles that deliver WordPress:
juju find wordpress
See more:
juju find
To query Charmhub for the charms / bundles on python-libjuju, you can use the find
method on the CharmHub
object that’s built-in on each Model
object:
await model.charmhub.find('wordpress')
View details about a Charmhub charm / bundle
To view details about a particular Charmhub charm / bundle, run the info
command followed by the name of the charm / bundle. For example:
juju info postgresql
See more:
juju info
For comprehensive information about the charm, including charm documentation, it is always best to see the charm’s page on Charmhub.
To view details about a particular Charmhub charm / bundle on python-libjuju, you can use the info
method on the CharmHub
object that’s built-in on each Model
object:
await model.charmhub.info('wordpress')
Find out the resources available for a charm
See: How to manage charm resources > Find out the resources available for a charm
Download a Charmhub charm
This is relevant for air-gapped deployments.
To download a Charmhub charm, run the download
command followed by the name of the charm. For example:
juju download postgresql
See more:
juju download
Python-libjuju doesn’t support this, please use the juju
client to download a Charmhub charm.
Deploy a charm / bundle
To deploy a charm / bundle from Charmhub / your local filesystem, use the deploy
command followed by the name of the charm / bundle / the path to the local <charm>.charm
/ <bundle>.yaml
file:
juju deploy <charm | charm bundle> | <path to the local charm or bundle>
Example: Deploy a Charmhub charm
juju deploy mysql
Example: Deploy a Charmhub bundle
To get a summary of the deployment steps (without actually deploying), add the --dry-run
flag. Note: This flag is only supported for bundles, not charms.
juju deploy kubeflow
Example: Deploy a local charm
juju deploy ./mini_ubuntu-20.04-amd64.charm
Example: Deploy a local charm with a resource
If your charm’s metadata.yaml
specifies a resource, you must also explicitly pass the resource. For example:
juju deploy ./demo-api-charm_ubuntu-22.04-amd64.charm --resource \
demo-server-image=ghcr.io/beliaev-maksim/api_demo_server:0.0.9
Example: Deploy a local bundle
juju deploy ./mediawiki-model-bundle.yaml
Example: Deploy a local bundle as an overlay
To deploy a local bundle as an overlay, run the deploy
command with the --overlay
flag followed by the path to the overlay. To add an overlay to a model later, export the contents of the model to a bundle and deploy that bundle with the overlay.
See more: How to compare and export the contents of a model to a bundle
Generic example
Suppose you want to deploy mediawiki
and also apply an overlay bundle called custom-wikimedia.yaml
. Run the deploy
command followed by mediawiki
and the --overlay
flag followed by the local path to your overlay bundle yaml
:
juju deploy mediawiki \
--overlay ./custom-mediawiki.yaml
Suppose now that have a model where you’ve already deployed mediawiki
. You’ve also made some other changes in your model. Finally, you’d like to apply an overlay bundle custom-mediawiki.yaml
. In that case:
- Export the contents of your model to a bundle (below,
mediawiki-bundle.yaml
):
juju export-bundle --filename mediawiki-model-bundle.yaml
- Deploy the new bundle and during deploy apply the overlay:
juju deploy ./mediawiki-model-bundle.yaml \
--overlay ./custom-mediawiki.yaml
OpenStack example
Suppose you want to deploy an OpenStack cloud. This is done by deploying a base bundle defining the cloud with an overlay bundle, to make the bundle deployable within the local environment, and – optionally – any other number of bundles, to override / add parameters in / to the existing bundle, e.g., storage or constraints. Run the deploy
command followed by the base bundle and then repeat the --overlay
flag followed by the path to the overlay for as many overlays as you want. For example, below we deploy an OpenStack Yoga cloud running on Focal nodes (our base bundle), ensure it can run in a MAAS environment (the first, mandatory, overlay) and that it has Shared filesystem services (the second overlay):
juju deploy ./bundle-focal-yoga.yaml \
--overlay ./overlay-focal-yoga-mymaas.yaml
--overlay ./overlay-focal-yoga-mymaas-shared-filesystem.yaml
Suppose now that have a model where you’ve already deployed all of the above. You’ve maybe also made some other changes in your model. And you’d like to add manual zone Swift services by applying another overlay.
- Export the contents of your model to a bundle (below,
exported-bundle-focal-yoga-2022-06-07.yaml
):
juju export-bundle --filename exported-bundle-focal-yoga-2022-06-07.yaml
- Deploy the new bundle and during deploy apply the overlay:
juju deploy ./exported-bundle-focal-yoga-2022-06-07.yaml \
--overlay ./overlay-focal-yoga-mymaas-manual-swift.yaml
Example: Deploy a bundle to existing machines
To have a bundle use a model’s existing machines, as opposed to creating new machines, the --map-machines=existing
option is used. In addition, to specify particular machines for the mapping, comma-separated values of the form ‘bundle-id=existing-id’ can be passed where the bundle-id and the existing-id refer to top level machine IDs.
For example, consider a bundle whose YAML file is configured with machines 1, 2, 3, and 4, and a model containing machines 1, 2, 3, 4, and 5. The following deployment would use existing machines 1 and 2 for bundle machines 1 and 2 but use existing machine 4 for bundle machine 3 and existing machine 5 for bundle machine 4:
juju deploy some-bundle --map-machines=existing,3=4,4=5
Depending on the cloud substrate that your controller is running on, the above command will allocate a machine (physical, virtual, LXD container) or a Kubernetes pod and then proceed to deploy the contents of the charm / bundle.
Depending on your use case, you may alternatively opt to provision a set of machines in advance via the juju add-machine
command.
In this case, when running the above juju deploy
command, Juju will detect that the model contains machines with no applications assigned to them and automatically deploy the application to one of those machines instead of spinning up a new machine.
The command also allows you to add another argument to specify a custom name (alias) for your deployed application (charms only). You can also take advantage of the rich set of flags to specify a charm channel or revision, a machine base, a machine constraint (e.g., availability zone), the number of application units you want (clusterised), a space binding, a placement directive (e.g., to deploy to a LXD container), a specific storage instance, a specific machine, etc., and even to trust the application with the current credential – in case the application requires access to the backing cloud in order to fulfil its purpose (e.g., stojrage-related tasks).
When deploying, if Juju fails to provision a subset of machines for some reason (e.g. machine quota limits on the cloud provider) the command juju retry-provisioning
can be used to retry the provisioning of specific machine numbers.
Expand to view examples of using a placement directive to deploy to specific targets
See also: Placement directive
# Deploy to a new lxd-type container on new machine:
juju deploy mariadb --to lxd
# Deploy to a new container on existing machine 25:
juju deploy mongodb --to lxd:25
# Deploy to existing lxd-type container 3 on existing machine 24:
juju deploy nginx --to 24/lxd/3
# Deploy to zone us-east-1a on AWS:
juju deploy mysql --to zone=us-east-1a
# Dploy to a specific machine on MAAS:
juju deploy mediawiki --to node1.maas
# Deploy to a specific machine on LXD:
juju deploy mariadb --to node1.lxd
For a Kubernetes-backed cloud, a Kubernetes node can be targeted based on matching labels. The label can be either built-in or one that is user-defined and added to the node. For example:
# Deploy to a specific Kubernetes node (using either a built-in or a user-defined label):
juju deploy mariadb-k8s --to kubernetes.io/hostname=somehost
See more:
juju deploy
The Terraform Provider for Juju does not support deploying a local charm.
To deploy a Charmhub charm, in your Terraform plan add a juju_application
resource, specifying the target model and the charm:
resource "juju_application" "this" {
model = juju_model.development.name
charm {
name = "hello-kubecon"
}
}
See more:
juju_application
(resource)
To deploy a Charmhub charm / bundle using python-libjuju, you can use the deploy
method on the Model
object:
m = model.Model()
await m.connect()
# deploy a charm
await m.deploy('mysql')
# deploy a bundle
await m.deploy('kubeflow')
# deploy a local charm
await m.deploy('./mini_ubuntu-20.04-amd64.charm')
# deploy a local charm with a resource
await m.deploy('./demo-api-charm_ubuntu-22.04-amd64.charm', resources={'demo-server-image=ghcr.io/beliaev-maksim/api_demo_server':'0.0.9'})
# deploy a local bundle
await m.deploy('./mediawiki-model-bundle.yaml')
# deploy a bundle with an overlay
await m.deploy('mediawiki', overlays=['./custom-mediawiki.yaml'])
# generic openstack example
await m.deploy('./bundle-focal-yoga.yaml', overlays=['./overlay-focal-yoga-mymaas.yaml', './overlay-focal-yoga-mymaas-shared-filesystem.yaml'])
See more:
Model.deploy()
Update a charm
Updating a charm to the latest revision always involves the refresh
command, but the exact way to use it differs a little bit depending on whether you are dealing with a Charmhub charm or rather a local charm.
Update a Charmhub charm
Because of the way charm channels work, ‘updating’ doesn’t have to mean ‘upgrading’ – you can switch to any charm revision, no matter if it’s newer or older. The instructions below reflect this.
However, as newer versions typically contain improvements, Juju will notify you if a new version exists: Juju polls Charmhub once a day to check for updates and, if an update is found, the poll will cause juju status
to indicate that a newer charm version is available.
-
If you don’t know your current channel: Run
status
and check the App > Channel column. -
If you don’t know which channel you want to update to / would like to find out all the available channels: Run
info
followed by the charm name. -
Run
refresh
followed by the charm name and the desired newchannel
.
Expand to view an example featuring the machine charm for PostgreSQL
# Find out the current channel (see App > Channel):
$ juju status
Model Controller Cloud/Region Version SLA Timestamp
welcome-lxd lxd localhost/localhost 3.1.6 unsupported 14:58:37+01:00
App Version Status Scale Charm Channel Rev Exposed Message
postgresql waiting 0/1 postgresql 14/stable 351 no agent initialising
Unit Workload Agent Machine Public address Ports Message
postgresql/0* waiting allocating 2 10.122.219.3 agent initialising
Machine State Address Inst id Base AZ Message
2 started 10.122.219.3 juju-f25b73-2 ubuntu@22.04 Running
# Find out all the available channels:
$ juju info postgresql
name: postgresql
publisher: Canonical Data Platform
summary: Charmed PostgreSQL VM operator
description: |
Charm to operate the PostgreSQL database on machines.
store-url: https://charmhub.io/postgresql
charm-id: ChgcZB3RhaDOnhkAv9cgRg52LhjBbDt8
supports: ubuntu@22.04
tags: databases
subordinate: false
relations:
provides:
cos-agent: cos_agent
database: postgresql_client
db: pgsql
db-admin: pgsql
requires:
certificates: tls-certificates
s3-parameters: s3
channels: |
14/stable: 351 2024-01-03 (351) 29MB amd64 ubuntu@22.04
14/candidate: 363 2024-01-31 (363) 33MB amd64 ubuntu@22.04
14/beta: 363 2024-01-31 (363) 33MB amd64 ubuntu@22.04
14/edge: 365 2024-02-02 (365) 33MB amd64 ubuntu@22.04
latest/stable: initial-reactive-278-ge3f064a 2023-11-09 (345) 7MB amd64 ubuntu@16.04, ubuntu@18.04, ubuntu@20.04, ubuntu@22.04
latest/candidate: ↑
latest/beta: ↑
latest/edge: ↑
# Update the charm to revision `365` by switching to the `14/edge` channel:
$ juju refresh postgresql --channel 14/edge
Added charm-hub charm "postgresql", revision 365 in channel 14/edge, to the model
no change to endpoints in space "alpha": certificates, cos-agent, database, database-peers, db, db-admin, restart, s3-parameters, upgrade
# Verify that the charm has been updated (see App > Channel):
$ juju status
Model Controller Cloud/Region Version SLA Timestamp
welcome-lxd lxd localhost/localhost 3.1.6 unsupported 15:05:16+01:00
App Version Status Scale Charm Channel Rev Exposed Message
postgresql 14.9 active 1 postgresql 14/edge 365 no
Unit Workload Agent Machine Public address Ports Message
postgresql/0* active executing 2 10.122.219.3 5432/tcp (config-changed)
Machine State Address Inst id Base AZ Message
2 started 10.122.219.3 juju-f25b73-2 ubuntu@22.04 Running
See more:
juju status
,juju info
,juju refresh
Update a local charm
To upgrade a local charm, run the refresh
command followed by the name of the charm and the local path to the charm:
juju refresh juju-test --path ./path/to/juju-test
The command offers many other options, for example, the possibility to replace a charm completely with another charm by using the --switch
option followed by a different path (a process known as ‘crossgrading’). (Note: --path
and --switch
are mutually exclusive. Use --switch
if you want to replace your existing charm with a completely new charm.)
See more:
juju refresh
To update a charm, in the application’s resource definition, in the charm attribute, use a sub-attribute specifying a different revision or channel. For example:
resource "juju_application" "this" {
model = juju_model.development.name
charm {
name = "hello-kubecon"
revision = 19
}
}
See more:
juju_application
>charm
> nested schema
To update a charm on python-libjuju, you can use the upgrade_charm
(aliased as refresh
) method on the Application
object:
# upgrade to latest revision on the channel
await my_app.upgrade_charm()
# upgrade to the latest revision on a given channel
await my_app.upgrade_charm(channel='latest/edge')
# upgrade to a particular revision
await my_app.upgrade_charm(revision=3)
# upgrade with a local charm
await my_app.upgrade_charm(path='./path/to/juju-test')
# replace a charm completely with another charm
await my_app.upgrade_charm(switch='./path/to/juju-test')
# Note that the path and switch parameters are mutually exclusive.
See more:
Application.upgrade_charm()
Remove a charm / bundle
As a charm / bundle is just the means by which (an) application(s) are deployed, there is no way to remove the charm / bundle. What you can do, however, is remove the application / model.
See more: How to remove an application, How to destroy a model
Contributors: @aflynn, @hmlanigan, @tmihoc