Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
The podman
library provides a simple interface for interacting with a podman API.
Use this library to validate the API and integrate podman in Haskell applications.
This tutorial introduces how to use the podman
library to write Haskell scripts.
In another terminal, ensure the API is running:
$ podman --log-level=debug system service --time=0 /var/run/podman.sock
Synopsis
Introduction
To start using this library you need a haskell toolchain, on fedora run:
$ sudo dnf install -y ghc cabal-install && cabal update
Then get a copy of the library by running:
$ git clone https://github.com/softwarefactory-project/podman-haskell $ cd podman-haskell
Install the library by running:
$ cabal install --lib podman
Validate the library is correctly installed by running:
$ ghci Prelude> import Podman Prelude Podman> :set prompt "> " > :set -XOverloadedStrings > withClient "http+unix://var/run/podman.sock" getVersion Right (Version {_versionApiVersion = "1.40", _versionVersion = "3.1.0-dev"})
Create the client
Most functions require an existing PodmanClient
which carries the
endpoint url and the http client manager.
The only way to get the client is through the withClient
function, which
uses a callback function. To make this easier to use in ghci, create this
helper:
> let c = withClient "http+unix://var/run/podman.sock" > c $ \client -> getVersion client
Call endpoint
API functions operate with Haskell record, e.g.: InspectContainerResponse
.
Each field is a function that can be used with the record:
> :type _inspectContainerResponseImageName _inspectContainerResponseImageName :: InspectContainerResponse -> Text
For example, to inspect a container named "podman-demo", use containerInspect
:
> Right res <- c $ \client -> containerInspect client (ContainerName "podman-demo") False > :t res res :: InspectContainerResponse > _inspectContainerResponseImageName res "registry.access.redhat.com/ubi8/ubi"
When an API endpoint has complex arguments, the library function also use records:
- When all the fields are optional, the library provides a default record, e.g.
defaultContainerListQuery
. - When some fields are required, the library provides a smart constructor, e.g.
mkSpecGenerator
.
Then the default fields can be modified using the record update syntax:
> let myListQuery = defaultContainerListQuery { _containerListQueryall = Just True } > c $ \client -> containerList client myListQuery Right [ListContainer {...}, ...]
The field name can be used in a mapping function, for example, to get the name of all the containers:
> (fmap . fmap . fmap $ _listContainerNames) <$> c $ \client -> containerList client myListQuery Right ["podman-demo", "rootless-cni-infra", "..."]
Note that we use multiple fmap
to penetrate each layer, e.g. MonadIO, Result, and List.
Copy files
The send and get files expect tar
files, so first import the library and define a utility function:
> import qualified Codec.Archive.Tar as Tar > import qualified Codec.Archive.Tar.Entry as Tar > let tar = mapM (\(path, content) -> Tar.fileEntry <$> Tar.toTarPath False path <*> pure content)
Send files with containerSendFiles
:
> let Right tarball = tar [("test.dat", "test-content")] > c $ \client -> containerSendFiles client (ContainerName "demo-haskell") tarball "/tmp/test" Nothing
Get files with containerGetFiles
:
> c $ \client -> containerGetFiles client (ContainerName "demo-haskell") "/tmp/test" Right (Next (Entry {entryTarPath = "test", entryContent = Directory, ..}))
Use interactive session
The interactive functions expect a callback, for example, to get a container log with containerLogs
:
> c $ \client -> containerLogs client (ContainerName "demo-haskell") LogBoth (defaultLogsQuery {_logsQueryfollow = Just follow}) print Stdout "container output" Stdout "..."
The containerAttach
function provides a ContainerConnection
handler that can be used to read and write.
Checkout the podman-demo script for more detailed examples.