Open Container Interface Support
The OCI Layer
The OCI module contains abstract interfaces for dealing with the container ecosystem. OciImage represents an image that can be pushed to a registry. OciContainer represents a single container. While an OciContainer is a Machine, and a full OS environment including ssh can run on such a container, that is atypical. Instead it is more common to set oci_command and run a single application.
- class carthage.oci.OciContainer(*, readonly=None, **kwargs)
- exposed_ports()
Return a sequence of
OciExposedPortfor any container ports that should be exposed.By default, instantiate all OciExposedPort instances in the injector.
- mounts()
Sequence of
OciMountobjects to be mounted to the container.By default instantiate OciMount objects in the injector hierarchy.
- oci_command()
Override the container command if non-None. Defaults to checking on the model
- oci_interactive = False
Should stdin be kept open?
- oci_tty = False
Allocate a tty for stdio
- class carthage.oci.OciEnviron(assignment: 'str', scope: 'str' = 'all')
- default_instance_injection_key()
Called when an instance of an injectable is used to add a dependency provider bby the single argument form of
Injectable.add_provider()
- class carthage.oci.OciExposedPort(container_port: 'int', host_ip: 'str' = '0.0.0.0', host_port: 'int' = '', proto: 'str' = 'tcp')
- default_instance_injection_key()
Called when an instance of an injectable is used to add a dependency provider bby the single argument form of
Injectable.add_provider()
- class carthage.oci.OciImage(*, oci_image_tag=None, id=None, **kwargs)
- classmethod default_class_injection_key()
Called by
Injector.add_provider()in the single argument form to get the injection key to use when this class is added to provide a dependency.
- property deployable_names
Uses each of self.deployable_name_prefixes as a name_type for self.name and self.id.
- classmethod supplementary_injection_keys(k)
Returns an iteration of
InjectionKeysthat should be added to an injector when this class is added. The current injection key is taken as an argument so that constraints applied can modify what keys are added.
- class carthage.oci.OciManaged(*, readonly=None, **kwargs)
- property deployable_names
Uses each of self.deployable_name_prefixes as a name_type for self.name and self.id.
- async find()
Returns falsy if the object does not exist. Ideally returns the creation time in unix time, otherwise returns True if the creation time cannot be determined.
- class carthage.oci.OciMount(destination: str, source: str = None, options: str = '', mount_type: str = 'volume')
Represents a mount for a container.
If source is a string, config and environment variables will be substituted in it.
If source is an InjectionKey, it will be instantiated.
Container implementations may permit a source to be a managed object. For example
carthage.podman.PodmanContainerpermits source to be acarthage.podman.PodmanVolume.
- classmethod default_class_injection_key()
Called by
Injector.add_provider()in the single argument form to get the injection key to use when this class is added to provide a dependency.
- default_instance_injection_key()
Called when an instance of an injectable is used to add a dependency provider bby the single argument form of
Injectable.add_provider()
- class carthage.oci.OciPod(name=None, id=None, **kwargs)
- exposed_ports()
Return a sequence of
OciExposedPortfor any container ports that should be exposed.By default, instantiate all OciExposedPort instances in the injector.
- id: str = None
the ID of the pod
- name: str = None
The name of the pod
- carthage.oci.oci_container_image = InjectionKey('oci/container_image')
This key provides a string whose result is the container image name to pull or an image ID that is locally available. Examples include
docker.io/library/debian:latestordebian:unstable
Podman
Podman is a container frontend that will realize OCI containers on a single system. Currently Carthage only supports Podman running on the local system through LocalPodmanContainerHost. Long term, support is expected for remote Podman as well.
- class carthage.podman.ContainerfileImage(container_context=None, **kwargs)
Build an image using
podman buildfrom a context directory with aContainerfile.- Parameters:
container_context – A directory with a Containerfile and potentially other files used by the Containerfile. This can be specified either in a call to the constructor or in a subclass definition. In the constructor, this is resolved relative to the current directory. In a subclass, this is resolved relative to the package (or module) in which the class is defined.
build_args – A dictionary; keys will be the name of ARGs and
the value will be the value passed in with
--build-arg. The dictionary will be run through resolve_deferred. As a special case, if one of the values is anOciImage, then value of the build_arg will be the image tag of that image. This can be used for handling base images.This class does respect
OciMountandOciEnvironin the injector hierarchy.- async find()
Returns falsy if the object does not exist. Ideally returns the creation time in unix time, otherwise returns True if the creation time cannot be determined.
- podman_options = ()
Options to pass to podman
- property stamp_subdir
The part of
stamp_path()after config.stamp_dir. For example for a podman container calledexample.comthis might bepodman/containers/example.com
- class carthage.podman.ContainerfileImageModel(container_context=None, **kwargs)
- class carthage.podman.LocalPodmanContainerHost(**kwargs)
- filesystem_access(*args)
Gain filesystem access to a podman resource. Arguments are passed to podman; for things to work needs to be a container or volume mount. If both filesystem_access_container and filesystem_access_volume are defined (and do not call this method), subclasses need not implement this method.
- tar_volume_context(volume)
An asynchronous context manager that tars up a volume and provides a path to that tar file usable in
podman import. Typical usage:async with container_host.tar_volume_context(container_image) as path: await container_host.podman('import', path)
On local systems this manages temporary directories. For remote container hosts, this manages to get the tar file to the remote system and clean up later.
- class carthage.podman.LocalPodmanSocket(**kwargs)
Use the podman socket in /run/podman.sock or $XDG_RUNTIME_DIR. Requires that containers have a sftp server installed, but avoids the need for podman unshare.
- filesystem_access_container(container_name)
an asynchronous context for accessing the filesystem of a container.
- filesystem_access_volume(volume_name)
An asynchronous context manager for accessing the filesystem of a volume
- class carthage.podman.PodmanContainer(**kwargs)
An OCI container implemented using
podman. While it is possible to set up a container to be accessible via ssh and to meet all the interfaces ofSshMixin, this is relatively uncommon. Such containers often have an entry point that is not a full init, and only run one service or program. Typicallycontainer_exec()is used to execute an additional command in the scope of a container rather than usingssh().- check_stamp(stamp, raise_on_error=False)
- Returns:
a tuple containing the unix time of the stamp and the text contents of the stamp. The first element of the tuple is False if the stamp does not exist
- container_exec(*args, _user=None, _fg=False)
‘Execute a command in a running container and return stdout. This function intentionally has a differentname than
carthage.container.Container.container_command()because that method does not expect the container to be running.
- filesystem_access(user='root')
An asynchronous context manager that makes the filesystem of the Machine available on a local path.
- Returns:
Path at which the filesystem can be accessed while in the context.
- async find()
Returns falsy if the object does not exist. Ideally returns the creation time in unix time, otherwise returns True if the creation time cannot be determined.
- async is_machine_running()
- Returns:
Whether the machine is running
Probe whether the machine is running and set self.running appropriately. It is most important that running be set accurately when
start_machine()andstop_machine()can start or stop the machine. ForBareMetalMachineit is reasonable to assume that the machine is running. This interface point should not callssh_online()or confirm the machine is on the network.
- machine_running_ssh_online: bool = False
Should machine_running default to calling ssh_online
- podman_options()
Extra options to be passed into podman create as a list
- podman_restart = 'no'
restart containers (no, always, on-failure)
- rsync_uses_filesystem_access: bool = True
If true, use self.filesystem_access for rsync, otherwise use ssh.
- run_command(*args, _user=None, _fg=False)
‘Execute a command in a running container and return stdout. This function intentionally has a differentname than
carthage.container.Container.container_command()because that method does not expect the container to be running.
- shell(*args, _user=None, _fg=False)
‘Execute a command in a running container and return stdout. This function intentionally has a differentname than
carthage.container.Container.container_command()because that method does not expect the container to be running.
- ssh_port: int
The port on which to connect to for ssh
- stamp_subdir()
The part of
stamp_path()after config.stamp_dir. For example for a podman container calledexample.comthis might bepodman/containers/example.com
- async start_machine()
Must be overridden. Start the machine.
- async stop_machine()
Must be overridden; stop the machine.
- stop_timeout = 10
Timeout in seconds to wait when stopping a container
- class carthage.podman.PodmanFromScratchImage(**kwargs)
- class carthage.podman.PodmanImage(**kwargs)
Represents an OCI container image and provides facilities for building the image.
customizationscan be turned into image layers using theimage_layer_customization()function. Note thatsetup_tasksare only run when images are actually built. By default, the image is only built if it does not exist, although seeshould_build()to override.- async async_ready()
This may need to be overridden, but is provided as a default
- async delete()
Try deleting an image. If we get an error (probably because it is in use by a container), untag instead.
- async deploy()
Bring image to ready, and if nonlocal and pushable, push.
- async find()
Returns falsy if the object does not exist. Ideally returns the creation time in unix time, otherwise returns True if the creation time cannot be determined.
- async find_or_create()
See if image exists otherwise rebuild the image. Note that this is not a
setup_task()even though it is in the parent. This is always run fromasync_ready()
- image_layer_context(commit_message='')
Generate a container to produce a new image layer:
The image of the container will be either self.last_layer or self.base_image if last_layer is not set.
The container will be a
PodmanImageBuilderContainer, and as such will simply pause when started so thatcontainer_exec()can be used to run commands in the container.
Usage:
async with self.image_layer_context() as layer_container: # Apply customizations/run commands in layer_container #Now, self.last_layer is the image ID of the new layer
- async should_build()
If the image exists, this is called. If it returns True, then the image will be rebuilt even though it exists. If a caller wants to force a rebuild,
build_image()can also be called.Local images that exist are not rebuilt by default. Remote images are rebuilt under the assumption that if building is enabled at all, the goal is to build and push a new image.
Images may overide if they have a good way to tell if an image is out of date.
- stamp_subdir()
The part of
stamp_path()after config.stamp_dir. For example for a podman container calledexample.comthis might bepodman/containers/example.com
- classmethod supplementary_injection_keys(k)
Returns an iteration of
InjectionKeysthat should be added to an injector when this class is added. The current injection key is taken as an argument so that constraints applied can modify what keys are added.
- class carthage.podman.PodmanImageModel(**kwargs)
Like a
PodmanImageexcetp:This is an
InjectableModelso modeling language constructs can be usedAny
FilesystemCustomizationorContainerCustomizationthat are registered with the injector are automatically treated as image layers after any explicit setup_tasks.
- class carthage.podman.PodmanPod(**kwargs)
- async find()
Returns falsy if the object does not exist. Ideally returns the creation time in unix time, otherwise returns True if the creation time cannot be determined.
- podman_pod_options = []
A list of extra options to pass to pod create
- class carthage.podman.PodmanPodModel(**kwargs)
A container that can group a number of
MachineModelsrepresenting Podman containers.By default,
machine_implementation_keywithin aPodmanPodModelisPodmanContainer.By default, when added to an enclosing injector, this model does not provide
PodmanPodin that context, although it does providePodmanPodwithin its own injector. An example illustrates:class Layout(CarthageLayout): #Even though this layout includes PodmanPods, PodmanPod is not provided in the injector of the layout. That means containers outside of a PodmanPodModel will not be associated with a pod by default class pod1(PodmanPodModel): # These containers are within pod1 and because within its own scope pod1 provides PodmanPod, the containers will be added to the pod. class container1(MachineModel): pass class container2(MachineModel): pass # But this container is not in a pod. class container3(MachineModel): pass
In contrast to using PodmanPodModel,
PodmanPodcan be used along side containers in another modeling grouping. When used this wayPodmanPoddoes providePodmanPodin the enclosing injector:class layout(CarthageLayout): class group1(ModelGroup): # Everything in this group is pod1 class pod1(PodmanPod): name = 'pod1' class container1(MachineModel): pass
- async resolve_networking(force: bool = False)
Like
carthage.machine.NetworkedModel.resolve_networking()except that it looks foroci_container_network_config. If that key is present, that network config is used instead ofInjectionKey(NetworkConfig). Doing so allows containers that are lexically contained in their host to have their own NetworkConfig.
- classmethod supplementary_injection_keys(k)
Returns an iteration of
InjectionKeysthat should be added to an injector when this class is added. The current injection key is taken as an argument so that constraints applied can modify what keys are added.
- class carthage.podman.PodmanVolume(name: str = None, **kwargs)
- filesystem_access()
Like
carthage.Machine.filesystem_access()except gains access to a podman volume.Usage:
async with volume.filesystem_access() as path: # Path points to a mount for the volume inside the context manager.
- async find()
Returns falsy if the object does not exist. Ideally returns the creation time in unix time, otherwise returns True if the creation time cannot be determined.
- stamp_subdir()
The part of
stamp_path()after config.stamp_dir. For example for a podman container calledexample.comthis might bepodman/containers/example.com
- class carthage.podman.RemotePodmanHost(machine, user=None, **kwargs)
- property extra_args
Tell Ansible about container_host
- filesystem_access(*args)
Gain filesystem access to a podman resource. Arguments are passed to podman; for things to work needs to be a container or volume mount. If both filesystem_access_container and filesystem_access_volume are defined (and do not call this method), subclasses need not implement this method.
- async find()
Return True if self.machine is found as a deployable.
- async podman_nosocket(*args, _log=True, **kwargs)
Run podman directly on the container host rather than using a podman socket. Used for example for container commits because for example podman 4.9 does not appear to understand the commit results from podman 4.6.
- tar_volume_context(volume)
An asynchronous context manager that tars up a volume and provides a path to that tar file usable in
podman import. Typical usage:async with container_host.tar_volume_context(container_image) as path: await container_host.podman('import', path)
On local systems this manages temporary directories. For remote container hosts, this manages to get the tar file to the remote system and clean up later.
- carthage.podman.image_layer_task(customization)
Wrap a
BaseCustomizationas a layer in aPodmanImage.