@@ -76,6 +76,27 @@ module Docker.Client.Types (
76 , HostConfig(..)
76 , HostConfig(..)
77 , defaultHostConfig
77 , defaultHostConfig
78 , NetworkingConfig(..)
78 , NetworkingConfig(..)
84+ , NetworkContainer(..)
90+ , defaultConnectConfig
91+ , DisconnectConfig(..)
92+ , defaultDisconnectConfig
95+ , NetworksDeleted(..)
96+ , EndpointSettings(..)
97+ , defaultEndpointSettings
99+ , defaultIPAMSettings
79 , EndpointConfig(..)
100 , EndpointConfig(..)
80 , Ulimit(..)
101 , Ulimit(..)
81 , ContainerResources(..)
102 , ContainerResources(..)
@@ -100,6 +121,7 @@ module Docker.Client.Types (
100 , MemoryConstraintSize(..)
121 , MemoryConstraintSize(..)
124+import Control.Monad (join)
103import Data.Aeson (FromJSON, ToJSON, genericParseJSON,
125import Data.Aeson (FromJSON, ToJSON, genericParseJSON,
104 genericToJSON, object, parseJSON, toJSON,
126 genericToJSON, object, parseJSON, toJSON,
105 (.!=), (.:), (.:?), (.=))
127 (.!=), (.:), (.:?), (.=))
@@ -107,6 +129,7 @@ import qualified Data.Aeson as JSON
107import Data.Aeson.Types (defaultOptions, fieldLabelModifier)
129import Data.Aeson.Types (defaultOptions, fieldLabelModifier)
108import Data.Char (isAlphaNum, toUpper)
130import Data.Char (isAlphaNum, toUpper)
109import qualified Data.HashMap.Strict as HM
131import qualified Data.HashMap.Strict as HM
132+import Data.Maybe (maybeToList, catMaybes)
110import Data.Monoid ((<>))
133import Data.Monoid ((<>))
111import Data.Scientific (floatingOrInteger)
134import Data.Scientific (floatingOrInteger)
112import Data.Text (Text)
135import Data.Text (Text)
@@ -114,6 +137,7 @@ import qualified Data.Text as T
114import Data.Time.Clock (UTCTime)
137import Data.Time.Clock (UTCTime)
115import qualified Data.Vector as V
138import qualified Data.Vector as V
116import GHC.Generics (Generic)
139import GHC.Generics (Generic)
140+import Numeric (readDec)
117import Prelude hiding (all, tail)
141import Prelude hiding (all, tail)
118import Text.Read (readMaybe)
142import Text.Read (readMaybe)
@@ -139,6 +163,11 @@ data Endpoint =
139 | DeleteImageEndpoint ImageDeleteOpts ImageID
163 | DeleteImageEndpoint ImageDeleteOpts ImageID
140 | CreateNetworkEndpoint CreateNetworkOpts
164 | CreateNetworkEndpoint CreateNetworkOpts
141 | RemoveNetworkEndpoint NetworkID
165 | RemoveNetworkEndpoint NetworkID
166+ | ListNetworksEndpoint [NetworkFilter]
167+ | InspectNetworkEndpoint NetworkID
168+ | ConnectNetworkEndpoint NetworkID ConnectConfig
169+ | DisconnectNetworkEndpoint NetworkID DisconnectConfig
170+ | PruneNetworksEndpoint PruneFilter
142 deriving (Eq, Show)
171 deriving (Eq, Show)
144-- | We should newtype this
173-- | We should newtype this
@@ -858,6 +887,242 @@ instance ToJSON CreateNetworkOpts where
858 , "EnableIPv6" .= createNetworkEnableIPv6 opts
887 , "EnableIPv6" .= createNetworkEnableIPv6 opts
890+data NetworkScope = LocalScope | GlobalScope | SwarmScope deriving (Eq, Show)
892+fromNetworkScope :: NetworkScope -> Text
893+fromNetworkScope LocalScope = "local"
894+fromNetworkScope GlobalScope = "global"
895+fromNetworkScope SwarmScope = "swarm"
897+instance ToJSON NetworkScope where
898+ toJSON = JSON.String . fromNetworkScope
900+instance FromJSON NetworkScope where
901+ parseJSON "local" = return LocalScope
902+ parseJSON "global" = return GlobalScope
903+ parseJSON "swarm" = return SwarmScope
904+ parseJSON _ = fail "Failed to parse NetworkScope"
906+data CIDR = CIDR Text Int deriving (Eq, Show)
908+instance FromJSON CIDR where
909+ parseJSON (JSON.String t) = case T.splitOn "/" t of
910+ [a,p] -> CIDR a <$> parsePrefixLen p
911+ _ -> fail "Failed to parse CIDR"
913+ parsePrefixLen p = case readDec (T.unpack p) of
914+ (n,""):_ -> return n
915+ _ -> fail "Failed to parse CIDR prefix length"
916+ parseJSON _ = fail "Failed to parse CIDR"
918+data IPAMDriver = DefaultIPAMDriver | NamedIPAMDriver Text deriving (Eq, Show)
920+instance FromJSON IPAMDriver where
921+ parseJSON (JSON.String "default") = return DefaultIPAMDriver
922+ parseJSON (JSON.String t) = return $ NamedIPAMDriver t
923+ parseJSON _ = fail "IPAMDriver is not a string"
925+data IPAMConfig = IPAMConfig
926+ { ipamConfigSubnet :: CIDR
927+ , ipamConfigIPRange :: Maybe CIDR
928+ , ipamSubnetGateway :: Maybe Text
929+ , ipamConfigAuxAddress :: Maybe Text
930+ } deriving (Eq, Show)
932+instance FromJSON IPAMConfig where
933+ parseJSON (JSON.Object o) = IPAMConfig
937+ <*> o .:? "AuxAddress"
938+ parseJSON _ = fail "IPAMConfig is not an object"
941+ { ipamDriver :: IPAMDriver
942+ , ipamConfig :: [IPAMConfig]
943+ , ipamOptions :: HM.HashMap Text Text
944+ } deriving (Eq, Show)
946+instance FromJSON IPAM where
947+ parseJSON (JSON.Object o) = IPAM
948+ <$> o .:? "Driver" .!= DefaultIPAMDriver
949+ <*> o .:? "Config" .!= []
950+ <*> o .:? "Options" .!= HM.empty
951+ parseJSON _ = fail "IPAM is not an object"
953+data NetworkContainer = NetworkContainer
954+ { networkContainerName :: ContainerName
955+ , networkContainerEndpointID :: Text
956+ , networkContainerMacAddress :: Text
957+ , networkContainerIPv4Address :: Text
958+ , networkContainerIPv6Address :: Text
959+ } deriving (Eq, Show)
961+instance FromJSON NetworkContainer where
962+ parseJSON (JSON.Object o) = NetworkContainer
964+ <*> o .: "EndpointID"
965+ <*> o .: "MacAddress"
966+ <*> o .: "IPv4Address"
967+ <*> o .: "IPv6Address"
968+ parseJSON _ = fail "NetworkContainer is not an object"
970+data NetworkDetails = NetworkDetails
971+ { networkDetailsName :: Text
972+ , networkDetailsID :: NetworkID
973+ , networkDetailsCreated :: UTCTime
974+ , networkDetailsScope :: NetworkScope
975+ , networkDetailsDriver :: NetworkMode
976+ , networkDetailsEnableIPv6 :: Bool
977+ , networkDetailsInternal :: Bool
978+ , networkDetailsAttachable :: Bool
979+ , networkDetailsIngress :: Bool
980+ , networkDetailsIPAM :: IPAM
981+ , networkDetailsOptions :: HM.HashMap Text Text
982+ , networkDetailsLabels :: HM.HashMap Text Text
983+ , networkDetailsContainers :: HM.HashMap Text NetworkContainer
984+ } deriving (Eq, Show)
986+instance FromJSON NetworkDetails where
987+ parseJSON v@(JSON.Object o) = NetworkDetails
993+ <*> o .: "EnableIPv6"
995+ <*> o .: "Attachable"
998+ <*> o .:? "Options" .!= HM.empty
999+ <*> o .:? "Labels" .!= HM.empty
1000+ <*> o .:? "Containers" .!= HM.empty
1001+ parseJSON _ = fail "NetworkDetails is not an object"
1003+data NetworkType = BuiltinNetwork | CustomNetwork deriving (Eq, Show)
1005+fromNetworkType :: NetworkType -> Text
1006+fromNetworkType BuiltinNetwork = "builtin"
1007+fromNetworkType CustomNetwork = "custom"
1009+type NetworkName = Text
1011+instance ToJSON NetworkType where
1012+ toJSON = JSON.String . fromNetworkType
1014+instance FromJSON NetworkType where
1015+ parseJSON (JSON.String "builtin") = return BuiltinNetwork
1016+ parseJSON (JSON.String "custom") = return CustomNetwork
1017+ parseJSON _ = fail "Failed to parse NetworkType"
1020+ = NetworkFilterName Text
1021+ | NetworkFilterID NetworkID
1022+ | NetworkFilterLabel Text
1023+ | NetworkFilterDriver NetworkMode
1024+ | NetworkFilterScope NetworkScope
1025+ | NetworkFilterType NetworkType
1026+ deriving (Eq, Show)
1028+instance {-# OVERLAPPING #-} ToJSON [NetworkFilter] where
1029+ toJSON = object . fmap toKV
1031+ toKV (NetworkFilterName n) = "name" .= [n]
1032+ toKV (NetworkFilterID i) = "id" .= [fromNetworkID i]
1033+ toKV (NetworkFilterLabel l) = "label" .= [l]
1034+ toKV (NetworkFilterDriver d) = "driver" .= [fromNetworkMode d]
1035+ toKV (NetworkFilterScope s) = "scope" .= [fromNetworkScope s]
1036+ toKV (NetworkFilterType t) = "type" .= [fromNetworkType t]
1038+data ConnectConfig = ConnectConfig
1039+ { connectContainer :: Text
1040+ , connectEndpointConfig :: EndpointSettings
1041+ } deriving (Eq, Show, Generic)
1043+instance ToJSON ConnectConfig where
1044+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 7 }
1046+defaultConnectConfig :: Text -> ConnectConfig
1047+defaultConnectConfig = flip ConnectConfig defaultEndpointSettings
1049+data DisconnectConfig = DisconnectConfig
1050+ { disconnectContainer :: Text
1051+ , disconnectForce :: Bool
1052+ } deriving (Eq, Show, Generic)
1054+instance ToJSON DisconnectConfig where
1055+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 10 }
1057+defaultDisconnectConfig :: Text -> DisconnectConfig
1058+defaultDisconnectConfig = flip DisconnectConfig False
1060+data PruneFilter = PruneFilter
1061+ { pruneFilterUntil :: Maybe Text
1062+ -- ^ Can be a Unix timestamp, a date-formatted timestamp, or a duration,
1063+ -- such as @10m@ or @1h30m@.
1064+ , pruneFilterIncludeLabels :: [(Text, (Maybe Text))]
1065+ , pruneFilterExcludeLabels :: [(Text, (Maybe Text))]
1066+ } deriving (Eq, Show)
1068+instance ToJSON PruneFilter where
1069+ toJSON pf = object . catMaybes $
1070+ [ "until" .=? maybeToList (pruneFilterUntil pf)
1071+ , "label" .=? (constructLabel <$> pruneFilterIncludeLabels pf)
1072+ , "label!" .=? (constructLabel <$> pruneFilterExcludeLabels pf)
1076+ k .=? l = Just $ k .= l
1078+constructLabel :: (Text, Maybe Text) -> Text
1079+constructLabel (k, Just v) = T.concat [k, "=", v]
1080+constructLabel (k, Nothing) = k
1082+defaultPruneFilter :: PruneFilter
1083+defaultPruneFilter = PruneFilter Nothing [] []
1085+newtype NetworksDeleted = NetworksDeleted [Text]
1086+ deriving (Eq, Show)
1088+instance FromJSON NetworksDeleted where
1089+ parseJSON (JSON.Object o) =
1090+ NetworksDeleted . join . maybeToList <$> o .: "NetworksDeleted"
1091+ parseJSON _ = fail $ "NetworksDeleted is not an object"
1093+data EndpointSettings = EndpointSettings
1094+ { endpointIPAMConfig :: IPAMSettings
1095+ , endpointLinks :: [Text]
1096+ , endpointAliases :: [Text]
1097+ , endpointNetworkID :: Maybe Text
1098+ , endpointEndpointID :: Maybe Text
1099+ , endpointGateway :: Maybe Text
1100+ , endpointIPAddress :: Maybe Text
1101+ , endpointIPPrefixLen :: Maybe Int
1102+ , endpointIPv6Gateway :: Maybe Text
1103+ , endpointGlobalIPv6Address :: Maybe Text
1104+ , endpointGlobalIPv6PrefixLen :: Maybe Int
1105+ , endpointMacAddress :: Maybe Text
1106+ } deriving (Eq, Show, Generic)
1108+instance ToJSON EndpointSettings where
1109+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 8 }
1111+defaultEndpointSettings :: EndpointSettings
1112+defaultEndpointSettings = EndpointSettings defaultIPAMSettings [] [] Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1114+data IPAMSettings = IPAMSettings
1115+ { ipamIPv4Address :: Maybe Text
1116+ , ipamIPv6Address :: Maybe Text
1117+ , ipamLinkLocalIPs :: [Text]
1118+ } deriving (Eq, Show, Generic)
1120+instance ToJSON IPAMSettings where
1121+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 4 }
1123+defaultIPAMSettings :: IPAMSettings
1124+defaultIPAMSettings = IPAMSettings Nothing Nothing []
861-- TOOD: Add support for SELinux Volume labels (eg. "ro,z" or "ro/Z")
1126-- TOOD: Add support for SELinux Volume labels (eg. "ro,z" or "ro/Z")
862-- | Set permissions on volumes that you mount in the container.
1127-- | Set permissions on volumes that you mount in the container.
863data VolumePermission = ReadWrite | ReadOnly deriving (Eq, Show, Generic)
1128data VolumePermission = ReadWrite | ReadOnly deriving (Eq, Show, Generic)
@@ -1027,11 +1292,14 @@ instance FromJSON NetworkMode where
1027 parseJSON (JSON.String n) = return $ NetworkNamed n
1292 parseJSON (JSON.String n) = return $ NetworkNamed n
1028 parseJSON _ = fail "Unknown NetworkMode"
1293 parseJSON _ = fail "Unknown NetworkMode"
1295+fromNetworkMode :: NetworkMode -> Text
1296+fromNetworkMode NetworkBridge = "bridge"
1297+fromNetworkMode NetworkHost = "host"
1298+fromNetworkMode NetworkDisabled = "none"
1299+fromNetworkMode (NetworkNamed n) = n
1030instance ToJSON NetworkMode where
1301instance ToJSON NetworkMode where
1031− toJSON NetworkBridge = JSON.String "bridge"
1302+ toJSON = JSON.String . fromNetworkMode
1032− toJSON NetworkHost = JSON.String "host"
1033− toJSON NetworkDisabled = JSON.String "none"
1034− toJSON (NetworkNamed n) = JSON.String n
1036newtype NetworkID = NetworkID Text
1304newtype NetworkID = NetworkID Text
1037 deriving (Eq, Show)
1305 deriving (Eq, Show)