<commit_before>{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Docker.Client.Types (
      Endpoint(..)
    , URL
    , ApiVersion
    , ContainerID
    , fromContainerID
    , toContainerID
    , ImageID
    , fromImageID
    , toImageID
    , Timeout(..)
    , StatusCode(..)
    , Signal(..)
    , ContainerDetails(..)
    , DockerClientOpts(..)
    , defaultClientOpts
    , ListOpts(..)
    , defaultListOpts
    , DockerVersion(..)
    , ContainerPortInfo(..)
    , Container(..)
    , ContainerState(..)
    , Status(..)
    , Digest
    , Label(..)
    , Tag
    , Image(..)
    , Entrypoint(..)
    , dropImagePrefix
    , CreateOpts(..)
    , BuildOpts(..)
    , defaultBuildOpts
    , defaultCreateOpts
    , DetachKeys(..)
    , StartOpts(..)
    , defaultStartOpts
    , DeleteOpts(..)
    , defaultDeleteOpts
    , Timestamp
    , TailLogOpt(..)
    , LogOpts(..)
    , defaultLogOpts
    , VolumePermission(..)
    , Bind(..)
    , Volume(..)
    , Device(..)
    , ContainerName
    , VolumeFrom(..)
    , Link(..)
    , LogDriverType(..)
    , LogDriverOption(..)
    , LogDriverConfig(..)
    , NetworkMode(..)
    , PortType(..)
--    , NetworkInterface(..)
    , Network(..)
    , NetworkSettings(..)
    , NetworkOptions(..)
    , Mount(..)
    , PortBinding(..)
    , HostPort(..)
    , RetryCount
    , RestartPolicy(..)
    , Isolation(..)
    , UTSMode(..)
    , HostConfig(..)
    , defaultHostConfig
    , Ulimit(..)
    , ContainerResources(..)
    , defaultContainerResources
    , Port
    , Name
    , Value
    , EnvVar(..)
    , ContainerConfig(..)
    , defaultContainerConfig
    , ExposedPort(..)
    , DeviceWeight(..)
    , DeviceRate(..)
    , addPortBinding
    , addExposedPort
    , addBind
    , setCmd
    , addLink
    , addVolume
    , addVolumeFrom
    , MemoryConstraint(..)
    , MemoryConstraintSize(..)
    ) where

import           Data.Aeson          (FromJSON, ToJSON, genericParseJSON,
                                      genericToJSON, object, parseJSON, toJSON,
                                      (.!=), (.:), (.:?), (.=))
import qualified Data.Aeson          as JSON
import           Data.Aeson.Types    (defaultOptions, fieldLabelModifier)
import           Data.Char           (isAlphaNum, toUpper)
import qualified Data.HashMap.Strict as HM
import           Data.Monoid         ((<>))
import           Data.Scientific     (floatingOrInteger)
import           Data.Text           (Text)
import qualified Data.Text           as T
import           Data.Time.Clock     (UTCTime)
import qualified Data.Vector         as V
import           GHC.Generics        (Generic)
import           Prelude             hiding (all, tail)
import           Text.Read           (readMaybe)

-- | List of Docker Engine API endpoints
data Endpoint =
        VersionEndpoint
      | ListContainersEndpoint ListOpts
      | ListImagesEndpoint ListOpts
      | CreateContainerEndpoint CreateOpts (Maybe ContainerName)
      | StartContainerEndpoint StartOpts ContainerID
      | StopContainerEndpoint Timeout ContainerID
      | WaitContainerEndpoint ContainerID
      | KillContainerEndpoint Signal ContainerID
      | RestartContainerEndpoint Timeout ContainerID
      | PauseContainerEndpoint ContainerID
      | UnpauseContainerEndpoint ContainerID
      | ContainerLogsEndpoint LogOpts Bool ContainerID -- ^ Second argument (Bool) is whether to follow which is currently hardcoded to False.
      -- See note in 'Docker.Client.Api.getContainerLogs' for explanation why.
      | DeleteContainerEndpoint DeleteOpts ContainerID
      | InspectContainerEndpoint ContainerID
      | BuildImageEndpoint BuildOpts FilePath
      | CreateImageEndpoint T.Text Tag (Maybe T.Text) -- ^ Either pull an image from docker hub or imports an image from a tarball (or URL)
    deriving (Eq, Show)

-- | We should newtype this
type URL = Text

-- | We should newtype this
type ApiVersion = Text


-- | ID of a contianer
newtype ContainerID = ContainerID Text
    deriving (Eq, Show)

-- | Used for extracting the id of the container from the newtype
fromContainerID :: ContainerID -> Text
fromContainerID (ContainerID t) = t

-- | Used for parsing a Text value into a ContainerID. We apply some basic
-- validation here.
toContainerID :: Text -> Maybe ContainerID
toContainerID t =
    if T.all (\c -> isAlphaNum c || c == ':') t then -- Note: Can we improve this whitelist?
        Just $ ContainerID t
    else
        Nothing

-- ID of an image.
newtype ImageID = ImageID Text
    deriving (Eq, Show)

-- | Used for extracting the id of the image from the newtype.
fromImageID :: ImageID -> Text
fromImageID (ImageID t) = t

-- | Helper function used for parsing a Text value into an ImageID. For now
-- just basic validation is used.
toImageID :: Text -> Maybe ImageID
toImageID t =
    if T.all (\c -> isAlphaNum c || c == ':') t then -- Note: Can we improve this whitelist?
        Just $ ImageID t
    else
        Nothing

-- | Timeout used for stopping a container. DefaultTimeout is 10 seconds.
data Timeout = Timeout Integer | DefaultTimeout deriving (Eq, Show)

data StatusCode = StatusCode Int

instance ToJSON StatusCode where
    toJSON (StatusCode c) = object ["StatusCode" .= c]

instance FromJSON StatusCode where
    parseJSON (JSON.Object o) = do
        c <- o .: "StatusCode"
        if c >= 0 && c <= 255 then
          return (StatusCode c)
        else
          fail "Unknown exit code"
    parseJSON _ = fail "Unknown exit code"

-- TODO: Add more Signals or use an existing lib
-- | Signal used for sending to the process running in the container.
-- The default signal is SIGTERM.
data Signal = SIGHUP
            | SIGINT
            | SIGQUIT
            | SIGSTOP
            | SIGTERM
            | SIGUSR1
            | SIG Integer
            | SIGKILL deriving (Eq, Show)

instance FromJSON Signal where
    parseJSON (JSON.String "SIGTERM") = return SIGTERM
    parseJSON (JSON.String "SIGHUP")  = return SIGHUP -- Note: Guessing on the string values for these.
    parseJSON (JSON.String "SIGINT")  = return SIGINT
    parseJSON (JSON.String "SIGQUIT") = return SIGQUIT
    parseJSON (JSON.String "SIGSTOP") = return SIGSTOP
    parseJSON (JSON.String "SIGUSR1") = return SIGUSR1
    parseJSON _                       = fail "Unknown Signal"

instance ToJSON Signal where
    toJSON SIGHUP  = "SIGHUP"
    toJSON SIGINT  = "SIGINT"
    toJSON SIGQUIT = "SIGQUIT"
    toJSON SIGSTOP = "SIGSTOP"
    toJSON SIGTERM = "SIGTERM"
    toJSON SIGUSR1 = "SIGUSR1"
    toJSON (SIG i) = toJSON i
    toJSON SIGKILL = "SIGKILL"

data ContainerDetails = ContainerDetails {
      appArmorProfile            :: Text
    , args                       :: [Text]
    , containerDetailsConfig     :: ContainerConfig
    , created                    :: UTCTime
    , driver                     :: Text
    -- , execIDs -- Not sure what this is in 1.24 spec.
    , containerDetailsHostConfig :: HostConfig
    , hostnamePath               :: FilePath
    , hostsPath                  :: FilePath
    , logPath                    :: FilePath
    , containerDetailsId         :: ContainerID
    , containerDetailsImage      :: ImageID
    , mountLabel                 :: Text
    , name                       :: Text
    , networkSettings            :: NetworkSettings
    , path                       :: FilePath
    , processLabel               :: Text
    , resolveConfPath            :: FilePath
    , restartCount               :: Int
    , state                      :: ContainerState
    , mounts                     :: [Mount]
    }
    deriving (Eq, Show, Generic)

-- | Data type used for parsing the mount information from a container
-- list.
data Mount = Mount {
      mountName        :: Text
    , mountSource      :: FilePath
    , mountDestination :: FilePath
    , mountDriver      :: Text
    , mountMode        :: Maybe VolumePermission -- apparently this can be null
    , mountRW          :: Bool
    , mountPropogation :: Text<commit_msg>Make "Name" attribute on mounts optional<commit_after>{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Docker.Client.Types (
      Endpoint(..)
    , URL
    , ApiVersion
    , ContainerID
    , fromContainerID
    , toContainerID
    , ImageID
    , fromImageID
    , toImageID
    , Timeout(..)
    , StatusCode(..)
    , Signal(..)
    , ContainerDetails(..)
    , DockerClientOpts(..)
    , defaultClientOpts
    , ListOpts(..)
    , defaultListOpts
    , DockerVersion(..)
    , ContainerPortInfo(..)
    , Container(..)
    , ContainerState(..)
    , Status(..)
    , Digest
    , Label(..)
    , Tag
    , Image(..)
    , Entrypoint(..)
    , dropImagePrefix
    , CreateOpts(..)
    , BuildOpts(..)
    , defaultBuildOpts
    , defaultCreateOpts
    , DetachKeys(..)
    , StartOpts(..)
    , defaultStartOpts
    , DeleteOpts(..)
    , defaultDeleteOpts
    , Timestamp
    , TailLogOpt(..)
    , LogOpts(..)
    , defaultLogOpts
    , VolumePermission(..)
    , Bind(..)
    , Volume(..)
    , Device(..)
    , ContainerName
    , VolumeFrom(..)
    , Link(..)
    , LogDriverType(..)
    , LogDriverOption(..)
    , LogDriverConfig(..)
    , NetworkMode(..)
    , PortType(..)
--    , NetworkInterface(..)
    , Network(..)
    , NetworkSettings(..)
    , NetworkOptions(..)
    , Mount(..)
    , PortBinding(..)
    , HostPort(..)
    , RetryCount
    , RestartPolicy(..)
    , Isolation(..)
    , UTSMode(..)
    , HostConfig(..)
    , defaultHostConfig
    , Ulimit(..)
    , ContainerResources(..)
    , defaultContainerResources
    , Port
    , Name
    , Value
    , EnvVar(..)
    , ContainerConfig(..)
    , defaultContainerConfig
    , ExposedPort(..)
    , DeviceWeight(..)
    , DeviceRate(..)
    , addPortBinding
    , addExposedPort
    , addBind
    , setCmd
    , addLink
    , addVolume
    , addVolumeFrom
    , MemoryConstraint(..)
    , MemoryConstraintSize(..)
    ) where

import           Data.Aeson          (FromJSON, ToJSON, genericParseJSON,
                                      genericToJSON, object, parseJSON, toJSON,
                                      (.!=), (.:), (.:?), (.=))
import qualified Data.Aeson          as JSON
import           Data.Aeson.Types    (defaultOptions, fieldLabelModifier)
import           Data.Char           (isAlphaNum, toUpper)
import qualified Data.HashMap.Strict as HM
import           Data.Monoid         ((<>))
import           Data.Scientific     (floatingOrInteger)
import           Data.Text           (Text)
import qualified Data.Text           as T
import           Data.Time.Clock     (UTCTime)
import qualified Data.Vector         as V
import           GHC.Generics        (Generic)
import           Prelude             hiding (all, tail)
import           Text.Read           (readMaybe)

-- | List of Docker Engine API endpoints
data Endpoint =
        VersionEndpoint
      | ListContainersEndpoint ListOpts
      | ListImagesEndpoint ListOpts
      | CreateContainerEndpoint CreateOpts (Maybe ContainerName)
      | StartContainerEndpoint StartOpts ContainerID
      | StopContainerEndpoint Timeout ContainerID
      | WaitContainerEndpoint ContainerID
      | KillContainerEndpoint Signal ContainerID
      | RestartContainerEndpoint Timeout ContainerID
      | PauseContainerEndpoint ContainerID
      | UnpauseContainerEndpoint ContainerID
      | ContainerLogsEndpoint LogOpts Bool ContainerID -- ^ Second argument (Bool) is whether to follow which is currently hardcoded to False.
      -- See note in 'Docker.Client.Api.getContainerLogs' for explanation why.
      | DeleteContainerEndpoint DeleteOpts ContainerID
      | InspectContainerEndpoint ContainerID
      | BuildImageEndpoint BuildOpts FilePath
      | CreateImageEndpoint T.Text Tag (Maybe T.Text) -- ^ Either pull an image from docker hub or imports an image from a tarball (or URL)
    deriving (Eq, Show)

-- | We should newtype this
type URL = Text

-- | We should newtype this
type ApiVersion = Text


-- | ID of a contianer
newtype ContainerID = ContainerID Text
    deriving (Eq, Show)

-- | Used for extracting the id of the container from the newtype
fromContainerID :: ContainerID -> Text
fromContainerID (ContainerID t) = t

-- | Used for parsing a Text value into a ContainerID. We apply some basic
-- validation here.
toContainerID :: Text -> Maybe ContainerID
toContainerID t =
    if T.all (\c -> isAlphaNum c || c == ':') t then -- Note: Can we improve this whitelist?
        Just $ ContainerID t
    else
        Nothing

-- ID of an image.
newtype ImageID = ImageID Text
    deriving (Eq, Show)

-- | Used for extracting the id of the image from the newtype.
fromImageID :: ImageID -> Text
fromImageID (ImageID t) = t

-- | Helper function used for parsing a Text value into an ImageID. For now
-- just basic validation is used.
toImageID :: Text -> Maybe ImageID
toImageID t =
    if T.all (\c -> isAlphaNum c || c == ':') t then -- Note: Can we improve this whitelist?
        Just $ ImageID t
    else
        Nothing

-- | Timeout used for stopping a container. DefaultTimeout is 10 seconds.
data Timeout = Timeout Integer | DefaultTimeout deriving (Eq, Show)

data StatusCode = StatusCode Int

instance ToJSON StatusCode where
    toJSON (StatusCode c) = object ["StatusCode" .= c]

instance FromJSON StatusCode where
    parseJSON (JSON.Object o) = do
        c <- o .: "StatusCode"
        if c >= 0 && c <= 255 then
          return (StatusCode c)
        else
          fail "Unknown exit code"
    parseJSON _ = fail "Unknown exit code"

-- TODO: Add more Signals or use an existing lib
-- | Signal used for sending to the process running in the container.
-- The default signal is SIGTERM.
data Signal = SIGHUP
            | SIGINT
            | SIGQUIT
            | SIGSTOP
            | SIGTERM
            | SIGUSR1
            | SIG Integer
            | SIGKILL deriving (Eq, Show)

instance FromJSON Signal where
    parseJSON (JSON.String "SIGTERM") = return SIGTERM
    parseJSON (JSON.String "SIGHUP")  = return SIGHUP -- Note: Guessing on the string values for these.
    parseJSON (JSON.String "SIGINT")  = return SIGINT
    parseJSON (JSON.String "SIGQUIT") = return SIGQUIT
    parseJSON (JSON.String "SIGSTOP") = return SIGSTOP
    parseJSON (JSON.String "SIGUSR1") = return SIGUSR1
    parseJSON _                       = fail "Unknown Signal"

instance ToJSON Signal where
    toJSON SIGHUP  = "SIGHUP"
    toJSON SIGINT  = "SIGINT"
    toJSON SIGQUIT = "SIGQUIT"
    toJSON SIGSTOP = "SIGSTOP"
    toJSON SIGTERM = "SIGTERM"
    toJSON SIGUSR1 = "SIGUSR1"
    toJSON (SIG i) = toJSON i
    toJSON SIGKILL = "SIGKILL"

data ContainerDetails = ContainerDetails {
      appArmorProfile            :: Text
    , args                       :: [Text]
    , containerDetailsConfig     :: ContainerConfig
    , created                    :: UTCTime
    , driver                     :: Text
    -- , execIDs -- Not sure what this is in 1.24 spec.
    , containerDetailsHostConfig :: HostConfig
    , hostnamePath               :: FilePath
    , hostsPath                  :: FilePath
    , logPath                    :: FilePath
    , containerDetailsId         :: ContainerID
    , containerDetailsImage      :: ImageID
    , mountLabel                 :: Text
    , name                       :: Text
    , networkSettings            :: NetworkSettings
    , path                       :: FilePath
    , processLabel               :: Text
    , resolveConfPath            :: FilePath
    , restartCount               :: Int
    , state                      :: ContainerState
    , mounts                     :: [Mount]
    }
    deriving (Eq, Show, Generic)

-- | Data type used for parsing the mount information from a container
-- list.
data Mount = Mount {
      mountName        :: Maybe Text -- this is optional
    , mountSource      :: FilePath
    , mountDestination :: FilePath
    , mountDriver      :: Text
    , mountMode        :: Maybe VolumePermission -- apparently this can be null
    , mountRW          :: Bool
    , mountPropogation :: Text
{'fraction_non_alphanumeric': 0.09674418604651162, 'fraction_numerical': 0.0017364341085271318, 'mean_word_length': 2.0215476859658983, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2236753', 'n_tokens_mistral': 4592, 'n_tokens_neox': 4524, 'n_words': 1344}