A full description of the charm, can be multiple lines.
maintainers []string
-
nil
List of maintainers in the formation “First Last ”.
terms []string
-
nil
List of terms a charm user must agree with.
min-juju-version string
proposed: deprecation
nil
Version (e.g. “2.6.10”) that represents the earliest version of juju this charm can be deployed to.
series []string
proposed: deprecation
nil
List of supported charm base platforms/versions. In the form of “focal”, “bionic”, “centos7” etc. Deprecation: to be supplemented by containers/bases.
assumes []string
-
nil
List of capabilities that must be present in order for the charm to operate correctly.
tags []string
-
nil
List of short tags used by the charm store.
categories []string
-
nil
List of categories used by the charm store.
subordinate bool
-
false
True if the charm is meant to be deployed as a subordinate to a principal charm.
provides map[string]Relation
-
nil
Relations provided by this charm. Key represents the Relation name.
requires map[string]Relation
-
nil
Relations required by this charm. Key represents the Relation name.
peers map[string]Relation
-
nil
Mutual relations between units/peers of this charm. Key represents the peer Relation name.
extra-bindings map[string]nil
-
nil
Extra bindings for the charm, for example binding extra network interfaces. Key only map.Value must be none. Key represents the binding name.
storage map[string]Storage
-
nil
Storage requests for the charm. Key represents the Storage name.
devices map[string]Device
-
nil
Device requests for the charm, e.g. GPU. Key represents the Device name.
containers map[string]Container
proposed
nil
Map of containers to be created adjacent to the charm. On kubernetes these are sidecars. Other platforms the behaviour is to be determined and will likely be fulfilled by a container runtime like LXD, containerd, Docker. Adjacency control is likely to arrive in a future revision (such as charm running on machine-0 and container-1 running on machine-1 etc.) The key represents the container name.
deployment Deployment
proposed: deprecation
nil
Deployment information for legacy Kubernetes charms. The presence of this field in metadata determined to be version 2 will be considered an error.
resources map[string]Resource
-
nil
Resources to accompany the charm. The key represents the resource name.
Type: Manifest
Serialized location: /manifest.yaml (generated by charmcraft)
Field
Since
Default
Description
bases []Base
proposed
required
List of systems (OS, version and architectures) this charm supports. Has no impact on the workload containers, only the charm itself.
Type: Relation
Field
Since
Default
Description
interface string
-
required
The interface schema this relation conforms to.
limit int
-
nil
Maximum number of connections to this relation endpoint.
scope RelationScope
-
“global”
Scope of the relation.
Type: Storage
Field
Since
Default
Description
type StorageType
-
required
Type of storage requested.
description string
-
nil
Description of the storage requested.
shared bool
-
false
True indicates all units of the application share the storage.
read-only bool
-
false
True indicates the storage should be made read-only where possible.
multiple StorageCount
-
nil
Determines the number of storage instances to be requested.
minimum-size string
-
nil
Size in the forms 1.0G, 1GiB, 1.0GB. Size multipliers are M, G, T, P, E, Z or Y. If no multiplier is supplied, M is implied.
location string
-
nil
Location is the mount location for filesystem stores. For multi-stores, the location acts as the parent directory for each mounted store.
properties []string
-
nil
List of properties. Currently only supported value is “transient”.
Type: StorageCount
Field
Since
Default
Description
range int/string
-
nil
int: exact number of storage instances string: in the form of m-n or m+ or m- where m and n are integers
Name of the OS e.g. ubuntu, centos, windows, osx, opensuse or genericlinux.
channel string
proposed
Channel of the OS (track/risk/branch) such as used for Snaps e.g. 18.04/stable or 20.04/stable/fips.
architectures []string
proposed
List of architectures that this particular charm build can run on.
Type: Container
Field
Since
Default
Description
resource string
proposed
nil
Reference for on entry in the resources field, indicating a specific container image. Must not be present if a base/channel is specified
bases []Base
proposed
nil
A list of bases in descending order of preference for use in resolving a container image. Must not be present if resource is specified. These bases are listed as base (instead of name) and channel as in the Base definition, as an unnamed top-level object list.
mounts []Mount
proposed
nil
List of mounted storage for this container.
Type: Mount
Field
Since
Default
Description
storage string
proposed
required
Name of storage to mount from the charm storage.
location string
proposed
nil
Location is the mount location for filesystem stores. For multi-stores, the location acts as the parent directory for each mounted store.
Type: Deployment
Field
Since
Default
Description
type DeploymentType
proposed: deprecation
“stateful”
Type of deployment in kubernetes.
mode DeploymentMode
proposed: deprecation
“workload”
Type of charm runtime location.
service ServiceType
proposed: deprecation
nil
Type of kubernetes service to create.
min-version string
proposed: deprecation
nil
Minimum version of kubernetes this charm supports.
Type: Resource
Field
Since
Default
Description
type ResourceType
-
“file”
Type of the resource.
filename string
-
nil
Name of the file resource.
description string
-
nil
Description of the resource.
Enumeration: RelationScope
Value
Since
Description
“global”
-
“container”
-
Enumeration: StorageType
Value
Since
Description
“block”
-
Block device storage.
“filesystem”
-
Filesystem storage.
Enumeration: DeploymentType
Value
Since
Description
“stateful”
proposed: deprecation
Stateful deployment in kubernetes.
“stateless”
proposed: deprecation
Stateless deployment in kubernetes.
“daemon”
proposed: deprecation
Node daemon deployment in kubernetes.
Enumeration: DeploymentMode
Value
Since
Description
“operator”
proposed: deprecation
Charm has no more than one unit which is collocated on the operator.
“workload”
proposed: deprecation
Charm has one or more units located in separate kubernetes pods.
Enumeration: ServiceType
Value
Since
Description
“cluster”
proposed: deprecation
Kubernetes service with a cluster IP address.
“loadbalancer”
proposed: deprecation
Kubernetes service with a possible external or internal load balancer.
“external”
proposed: deprecation
Kubernetes service that points to an external name (DNS/IP).
At the moment System:resource references a declared Resource which must have a ResourceType of “oci-image” (agree “oci” would be better).
If in the future a different image format or ResourceType can be used in a System, it can be swapped in by updating the type of the single resources: entry for the System:resource reference.
By changing System:resource to System:oci wouldn’t you lose that flexibility, and have to introduce a different System:new-format for each new resource type that can be used by System?
Hmm, yeah, I’d say “oci-image” is probably best then to be super clear what it means.
Kind of related, in the Resource type definition…
… I was wondering whether it should accommodate a “tag” field or similar (I’m not sure what the proper name should be here) that specifies the image rather than relying on the resource’s reference?
Basically, if the “file” ResourceType needs a filename, should the “oci-image” ResourceType also use some specific tag/url/whatnot that can be changed in the resources section without updating all the places it is referenced?
I’m not super familiar with k8s, so if that resource reference used in the containers section is really just the name given to the “Application” (in Juju speak) and the actual image version etc is managed elsewhere, just ignore me!
The current oci-image resource type takes the ‘docker url’ to the image. Which can include tags, etc. So it is still allowing a tag, but also allows you to point to a different docker hub registry.
I’m assuming that you could use focal/stable or just focal to reference a series or are we telling people to use the version number exclusively?
Also I’m assuming that the order still has the same order as the now deprecated series in metadata.yaml - it will pick the first one and correctly use that? I would expect that we should explain that ordering of given arrays/slices matter.
I think this will make it a little easier to digest for new charmers, along with an example of a more full featured metadata.yaml
First draft below, keen for review before publishing with the SDK docs. Perhaps @manadart and/or @jameinel
Spec:
# (Required) The name of the charm. Determines URL in Charmhub and the name administrators
# will ultimately use to deploy the charm. E.g. `juju deploy <name>`
name: <name>
# (Required) A short, one-line description of the charm
summary: <summary>
# (Required) A full description of the configuration layer
description: |
<description>
# (Optional) A list of maintainers in the format "First Last <email>"
maintainers:
- <maintainer>
# (Optional) A list of terms that any charm user must agree with
terms:
- <term>
# (Optional) A list of capabilities that must be present in order for the charm
# to function as expected
assumes:
- <capability>
# (Optional) A short list of tags to annotate the charm with
tags:
- <tag>
# (Optional) A list of categories to classify the charm under
categories:
- <category>
# (Optional) True if the charm is meant to be deployed as a subordinate to a
# principal charm
subordinate: true | false
# (Optional) A map of containers to be created adjacent to the charm. This field
# is required when the charm is targetting Kubernetes, where each of the specified
# containers will be created as sidecars to the charm in the same pod.
containers:
# Each key represents the name of the container
<container name>:
# Note: One of either resource or bases must be specified.
# (Optional) Reference for an entry in the resources field. Specifies
# the oci-image resource used to create the container. Must not be
# present if a base/channel is specified
resource: <resource name>
# (Optional) A list of bases in descending order of preference for use
# in resolving a container image. Must not be present if resource is
# specified. These bases are listed as base (instead of name) and
# channel as in the Base definition, as an unnamed top-level object list
bases:
# Name of the OS. For example ubuntu/centos/windows/osx/opensuse
- name: <base name>
# Channel of the OS in format "track[/risk][/branch]" such as used by
# Snaps. For example 20.04/stable or 18.04/stable/fips
channel: <track[/risk][/branch]>
# List of architectures that this particular charm can run on
architectures:
- <architecture>
# (Optional) List of mounted storages for this container
mounts:
# (Required) Name of the storage to mount from the charm storage
- name: <storage name>
# (Optional) In the case of filesystem storages, the location to
# mount the storage. For multi-stores, the location acts as the
# parent directory for each mounted store.
location: <path>
# (Optional) Additional resources that accompany the charm
resources:
# Each key represents the name of the resource
<resource name>:
# (Required) The type of the resource
type: file | oci-image
# (Optional) Description of the resource and its purpose
description: <description>
# (Required: when type:file) The filename of the resource as it should
# appear in the filesystem
filename: <filename>
# (Optional) Map of relations provided by this charm
provides:
# Each key represents the name of the relation as known by this charm
<relation name>:
# (Required) The interface schema that this relation conforms to
interface: <interface name>
# (Optional) Maximum number of supported connections to this relation
# endpoint. This field is an integer
limit: <n>
# (Optional) Defines if the relation is required. Informational only.
optional: true | false
# (Optional) The scope of the relation. Defaults to "global"
scope: global | container
# (Optional) Map of relations required by this charm
requires:
# Each key represents the name of the relation as known by this charm
<relation name>:
# (Required) The interface schema that this relation conforms to
interface: <interface name>
# (Optional) Maximum number of supported connections to this relation
# endpoint. This field is an integer
limit: <n>
# (Optional) Defines if the relation is required. Informational only.
optional: true | false
# (Optional) The scope of the relation. Defaults to "global"
scope: global | container
# (Optional) Mutual relations between units/peers of this charm
peer:
# Each key represents the name of the relation as known by this charm
<relation name>:
# (Required) The interface schema that this relation conforms to
interface: <interface name>
# (Optional) Maximum number of supported connections to this relation
# endpoint. This field is an integer
limit: <n>
# (Optional) Defines if the relation is required. Informational only.
optional: true | false
# (Optional) The scope of the relation. Defaults to "global"
scope: global | container
# (Optional) Storage requests for the charm
storage:
# Each key represents the name of the storage
<storage name>:
# (Required) Type of the requested storage
type: filesystem | block
# (Optional) Description of the storage requested
description: <description>
# (Optional) The mount location for filesystem stores. For multi-stores
# the location acts as the parent directory for each mounted store.
location: <location>
# (Optional) Indicates if all units of the application share the storage
shared: true | false
# (Optional) Indicate if the storage should be made read-only (where possible)
read-only: true | false
# (Optional) The number of storage instances to be requested
multiple: <n> | <n>-<m> | <n>- | <n>+
# (Optional) Minimum size of requested storage in forms G, GiB, GB. Size
# multipliers are M, G, T, P, E, Z or Y. With no multiplier supplied, M
# is implied.
minimum-size: <n>| <n><multiplier>
# (Optional) List of properties, only supported value is "transient"
properties:
- transient
# (Optional) Device requests for the charm, for example a GPU
devices:
# Each key represents the name of the device
<device name>:
# (Required) The type of device requested
type: gpu | nvidia.com/gpu | amd.com/gpu
# (Optional) Description of the requested device
description: <description>
# (Optional) Minimum number of devices required
countmin: <n>
# (Optional) Maximum number of devices required
countmax: <n>
# (Optional) Extra bindings for the charm. For example binding extra network
# interfaces. Key only map, value must be blank. Key represents the name
extra-bindings:
# Key only map; key represents the name of the binding
<binding name>:
Example:
name: super-charm
summary: a really great charm
description: |
This is a really great charm, whose metadata is suitably complete so as to
demonstrate as many of the fields as possible.
maintainers:
- Joe Bloggs <joe.bloggs@email.com>
categories:
- web-applications
tags:
- nodejs
- express
- awesome
terms:
- https://supercorp.com/terms-and-conditions
containers:
super-app:
resource: super-app-image
mounts:
- name: logs
location: /logs
super-app-helper:
bases:
- name: ubuntu
channel: ubuntu/20.04
architectures:
- amd64
- arm64
resources:
super-app-image:
type: oci-image
description: OCI image for the Super App (hub.docker.com/_/super-app)
definitions:
type: file
description: A small SQLite3 database of definitions needed by super app
filename: definitions.db
provides:
super-worker:
interface: super-worker
requires:
ingress:
interface: ingress
optional: true
limit: 1
peer:
super-replicas:
interface: super-replicas
storage:
logs:
type: filesystem
location: /logs
description: Storage mount for application logs
shared: true
devices:
gpu:
type: nvidia-gpu
description: CUDA-capable GPU used by super-app
One thing I’ve not seen is a concrete example of extra-bindings being used. Would appreciate some input on how best to demonstrate or explain this better
extra-bindings is meant for the case where you want to represent the concept of something that needs network binding/routing information, but doesn’t represent a relation. It is a bit of a wart, and something we’d rather people avoid if possible. Openstack charms use it because of a need to have multiple possible networks for internal vs public vs administrative aspects of their applications, and the fact that relations are more about sharing configuration data than defining connectivity.
Given that the end goal is to have universal charms, I would like to propose splitting the assumes section into an all_of and a any_of block (the individual sections can be omitted if not used) where each block references a list of feature names.
In order for Juju to deploy the charm, every feature in the all_of block must be supported by the controller whereas at least one of the features in the any_of block must be supported.
signal that a charm can work both as a containerized workload and as a regular workload deployed to a physical/virtual machine (juju or the op framework will figure out the suitable binary/image to deploy based on the substrate).
request a particular set of (pebble and/or Juju) features to be available regardless of the deployment target.
Thoughts?
(I have also added the proposal as a comment in the relevant spec doc)