How to manage resources¶
Implement the feature¶
In your charm’s src/charm.py
file, use ops
to fetch the path to the resource and then manipulate it as needed.
For example, suppose your charmcraft.yaml
file contains this simple resource definition:
resources:
my-resource:
type: file
filename: somefile.txt
description: test resource
In your charm’s src/charm.py
you can now use Model.resources.fetch(<resource_name>)
to get the path to the resource, then manipulate it as needed. For example:
# ...
import logging
import ops
# ...
logger = logging.getLogger(__name__)
def _on_config_changed(self, event):
# Get the path to the file resource named 'my-resource'
try:
resource_path = self.model.resources.fetch("my-resource")
except ops.ModelError as e:
self.unit.status = ops.BlockedStatus(
"Something went wrong when claiming resource 'my-resource; "
"run `juju debug-log` for more info'"
)
# might actually be worth it to just reraise this exception and let the charm error out;
# depends on whether we can recover from this.
logger.error(e)
return
except NameError as e:
self.unit.status = ops.BlockedStatus(
"Resource 'my-resource' not found; "
"did you forget to declare it in charmcraft.yaml?"
)
logger.error(e)
return
# Open the file and read it
with open(resource_path, "r") as f:
content = f.read()
# do something
The fetch()
method will raise a NameError
if the resource does not exist, and returns a Python Path
object to the resource if it does.
Note: During development, it may be useful to specify the resource at deploy time to facilitate faster testing without the need to publish a new charm/resource in between minor fixes. In the below snippet, we create a simple file with some text content, and pass it to the Juju controller to use in place of any published my-resource
resource:
echo "TEST" > /tmp/somefile.txt
charmcraft pack
juju deploy ./my-charm.charm --resource my-resource=/tmp/somefile.txt
Test the feature¶
See first: How to write unit tests for a charm
If your charm requires access to resources, you can make them available to it
through State.resources
. For example, to make a foo
resource that is a
path to an OCI image available:
import pathlib
from ops import testing
ctx = testing.Context(MyCharm, meta={'name': 'julie', 'resources': {'foo': {'type': 'oci-image'}}})
resource = testing.Resource(name='foo', path='/path/to/resource.tar')
with ctx(ctx.on.start(), testing.State(resources={resource})) as mgr:
path = mgr.charm.model.resources.fetch('foo')
assert path == pathlib.Path('/path/to/resource.tar')