Many charms use resources to enable deployments to proceed without access to the Internet. For example, the ~containers/kubernetes-worker
charm uses snap to install kubectl
, kubelet
and other necessary software.
This pattern is not limited to snaps, however. Resources allow source code to be updated and managed independently from charm upgrades.
Reactive charms
Using charms.reactive
, this process is relatively straightforward. The charm author defines layer.yaml
, that includes a description of the snap(s) to be downloaded by the charm:
# layer.yaml
includes:
- layer:basic
- layer:snap
options:
snap:
kubectl:
channel: stable
Within the charm’s metadata.yaml
, parallel resources are defined:
# metadata.yaml
resources:
kubectl:
type: file
filename: kubectl.snap
description: kubectl snap
Operator Framework
Within the Operator Framework, the ideal process is still being worked through. While the design decisions are still being made, we can mimic the behaviour of the snap layer within our own charm:
# src/charm.py
# ...
res_path = resource_get(snapname)
if res_path is False:
install_from_the_charmstore(snapname)
else:
install_from_the_resource(res_path)
To get this to work, a few helper functions are required:
from pathlib import Path
from subprocess import run
def resource_get(resource_name:str) -> Path:
result = run(['resource-get', resource_name], output=True, text=True)
return Path(result.stdout.strip())
def install_from_the_resource(path:Path):
return run(['snap', 'install', '--dangerous', path])
# --dangerous is required because the snap's
# asserts are not available
def install_from_the_charmstore(snap, channel='stable'):
return run(['snap', 'install', f'--channel={channel}', snap])