{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

module Docker.API.Client.Internal.Types where

import Control.Monad.Except
import qualified Data.Text as T
import Docker.API.Client.Images (tagImageIfMissing)
import GHC.Generics (Generic)

-- | Alias for the system type returned by System.Info.os
newtype OS = OS String

-- | This type describes common errors the docker client might encounter
data DockerClientError
  = -- | The request to create a new container failed
    ContainerCreationFailedError String
  | -- | The docker engine API responded with something we didn't expect
    UnrecognizedJSONResponseError String
  | -- | The docker engine API responded with an error status code when getting a container archive
    GetContainerArchiveError String
  | -- | The container exited with a nonzero exit code
    NonZeroExitCode String
  | -- | The docker engine API responded with an error when we attempted to get a container's logs
    GetContainerLogsError String
  | -- | The docker engine API responded with an error when we attempted to pull an image
    ImagePullError String
  deriving (Int -> DockerClientError -> ShowS
[DockerClientError] -> ShowS
DockerClientError -> String
(Int -> DockerClientError -> ShowS)
-> (DockerClientError -> String)
-> ([DockerClientError] -> ShowS)
-> Show DockerClientError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DockerClientError] -> ShowS
$cshowList :: [DockerClientError] -> ShowS
show :: DockerClientError -> String
$cshow :: DockerClientError -> String
showsPrec :: Int -> DockerClientError -> ShowS
$cshowsPrec :: Int -> DockerClientError -> ShowS
Show, (forall x. DockerClientError -> Rep DockerClientError x)
-> (forall x. Rep DockerClientError x -> DockerClientError)
-> Generic DockerClientError
forall x. Rep DockerClientError x -> DockerClientError
forall x. DockerClientError -> Rep DockerClientError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DockerClientError x -> DockerClientError
$cfrom :: forall x. DockerClientError -> Rep DockerClientError x
Generic)

-- | Wrapper for composing operations which return an Either DockerClientError a
type ClientErrorMonad a = ExceptT DockerClientError IO a

-- | Describes a docker container to be created with runContainer. Use defaultContainerSpec to
-- get a default value.
data ContainerSpec = ContainerSpec
  { -- | The image name with an optional tag or digest field (e.g. "python:3.6")
    ContainerSpec -> Text
image :: T.Text,
    -- | The container's command. If empty will default to the image default.
    ContainerSpec -> [Text]
cmd :: [T.Text],
    -- | Optional user ID to use in the container. If empty will default to the image default.
    ContainerSpec -> Text
user :: T.Text,
    -- | Optional working directory in the container. If empty will default to the image default.
    ContainerSpec -> Text
workingDir :: T.Text,
    -- | Optional list of environment variables of format "FOO=BAR".
    ContainerSpec -> [Text]
envVars :: [T.Text],
    -- | Optional list of host volumes to mount to the container as bind mounts. Must follow
    -- the format specied here: https://docs.docker.com/storage/bind-mounts/
    ContainerSpec -> [Text]
hostVolumes :: [T.Text]
  }
  deriving (Int -> ContainerSpec -> ShowS
[ContainerSpec] -> ShowS
ContainerSpec -> String
(Int -> ContainerSpec -> ShowS)
-> (ContainerSpec -> String)
-> ([ContainerSpec] -> ShowS)
-> Show ContainerSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ContainerSpec] -> ShowS
$cshowList :: [ContainerSpec] -> ShowS
show :: ContainerSpec -> String
$cshow :: ContainerSpec -> String
showsPrec :: Int -> ContainerSpec -> ShowS
$cshowsPrec :: Int -> ContainerSpec -> ShowS
Show, (forall x. ContainerSpec -> Rep ContainerSpec x)
-> (forall x. Rep ContainerSpec x -> ContainerSpec)
-> Generic ContainerSpec
forall x. Rep ContainerSpec x -> ContainerSpec
forall x. ContainerSpec -> Rep ContainerSpec x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ContainerSpec x -> ContainerSpec
$cfrom :: forall x. ContainerSpec -> Rep ContainerSpec x
Generic)

-- | Constructs a simple default ContainerSpec for a docker image which uses the image's default
-- values for all other aguments.
defaultContainerSpec ::
  -- | The container's Docker Image. May optionally include a tag or digest field (e.g. "python:3.6").
  -- If neither a tag or digest is specified the image will default to the `latest` tag.
  T.Text ->
  ContainerSpec
defaultContainerSpec :: Text -> ContainerSpec
defaultContainerSpec Text
img =
  ContainerSpec :: Text -> [Text] -> Text -> Text -> [Text] -> [Text] -> ContainerSpec
ContainerSpec
    { image :: Text
image = Text -> Text
tagImageIfMissing Text
img,
      cmd :: [Text]
cmd = [],
      user :: Text
user = Text
"",
      workingDir :: Text
workingDir = Text
"",
      envVars :: [Text]
envVars = [],
      hostVolumes :: [Text]
hostVolumes = []
    }

data ContainerLogType = Stdout | StdErr | Both

-- | Possible types of streams returned by the Docker Engine API attach and logs endpoints. Used only internally
-- for parsing the stream metadata returned by docker.
data DockerStreamType = DockerStreamStdIn | DockerStreamStdOut | DockerStreamStdErr