@@ -76,6 +76,29 @@ module Docker.Client.Types (
76 , HostConfig(..)
76 , HostConfig(..)
77 , defaultHostConfig
77 , defaultHostConfig
78 , NetworkingConfig(..)
78 , NetworkingConfig(..)
85+ , NetworkContainer(..)
90+ , defaultNetworkFilter
92+ , defaultConnectConfig
93+ , DisconnectConfig(..)
94+ , defaultDisconnectConfig
97+ , NetworksDeleted(..)
98+ , EndpointSettings(..)
99+ , defaultEndpointSettings
101+ , defaultIPAMSettings
79 , EndpointConfig(..)
102 , EndpointConfig(..)
80 , Ulimit(..)
103 , Ulimit(..)
81 , ContainerResources(..)
104 , ContainerResources(..)
@@ -100,13 +123,15 @@ module Docker.Client.Types (
100 , MemoryConstraintSize(..)
123 , MemoryConstraintSize(..)
126+import Control.Monad (join)
103import Data.Aeson (FromJSON, ToJSON, genericParseJSON,
127import Data.Aeson (FromJSON, ToJSON, genericParseJSON,
104 genericToJSON, object, parseJSON, toJSON,
128 genericToJSON, object, parseJSON, toJSON,
105 (.!=), (.:), (.:?), (.=))
129 (.!=), (.:), (.:?), (.=))
106import qualified Data.Aeson as JSON
130import qualified Data.Aeson as JSON
107−import Data.Aeson.Types (defaultOptions, fieldLabelModifier)
131+import Data.Aeson.Types (defaultOptions, fieldLabelModifier, omitNothingFields)
108import Data.Char (isAlphaNum, toUpper)
132import Data.Char (isAlphaNum, toUpper)
109import qualified Data.HashMap.Strict as HM
133import qualified Data.HashMap.Strict as HM
134+import Data.Maybe (maybeToList, catMaybes)
110import Data.Monoid ((<>))
135import Data.Monoid ((<>))
111import Data.Scientific (floatingOrInteger)
136import Data.Scientific (floatingOrInteger)
112import Data.Text (Text)
137import Data.Text (Text)
@@ -114,6 +139,7 @@ import qualified Data.Text as T
114import Data.Time.Clock (UTCTime)
139import Data.Time.Clock (UTCTime)
115import qualified Data.Vector as V
140import qualified Data.Vector as V
116import GHC.Generics (Generic)
141import GHC.Generics (Generic)
142+import Numeric (readDec)
117import Prelude hiding (all, tail)
143import Prelude hiding (all, tail)
118import Text.Read (readMaybe)
144import Text.Read (readMaybe)
@@ -139,6 +165,11 @@ data Endpoint =
139 | DeleteImageEndpoint ImageDeleteOpts ImageID
165 | DeleteImageEndpoint ImageDeleteOpts ImageID
140 | CreateNetworkEndpoint CreateNetworkOpts
166 | CreateNetworkEndpoint CreateNetworkOpts
141 | RemoveNetworkEndpoint NetworkID
167 | RemoveNetworkEndpoint NetworkID
168+ | ListNetworksEndpoint NetworkFilter
169+ | InspectNetworkEndpoint NetworkID
170+ | ConnectNetworkEndpoint NetworkID ConnectConfig
171+ | DisconnectNetworkEndpoint NetworkID DisconnectConfig
172+ | PruneNetworksEndpoint PruneFilter
142 deriving (Eq, Show)
173 deriving (Eq, Show)
144-- | We should newtype this
175-- | We should newtype this
@@ -830,12 +861,17 @@ defaultLogOpts = LogOpts { stdout = True
831-- | Options for creating a network
862-- | Options for creating a network
832data CreateNetworkOpts = CreateNetworkOpts
863data CreateNetworkOpts = CreateNetworkOpts
833− { createNetworkName :: Text -- ^ The network's name
864+ { createNetworkName :: Text -- ^ The network's name
834− , createNetworkCheckDuplicate :: Bool -- ^ Check for networks with duplicate names.
865+ , createNetworkCheckDuplicate :: Bool -- ^ Check for networks with duplicate names.
835− , createNetworkDriver :: Text -- ^ Name of the network driver plugin to use.
866+ , createNetworkDriver :: NetworkMode -- ^ Name of the network driver plugin to use.
836− , createNetworkInternal :: Bool -- ^ Restrict external access to the network.
867+ , createNetworkInternal :: Bool -- ^ Restrict external access to the network.
868+ , createNetworkAttachable :: Bool -- ^ Network is manually attachable in swarm mode.
869+ , createNetworkIngress :: Bool -- ^ Network is a swarm-mode network.
870+ , createNetworkIPAM :: IPAM -- ^ Address management configuration
837− , createNetworkEnableIPv6 :: Bool -- ^ Enable IPv6 on the network.
871+ , createNetworkEnableIPv6 :: Bool -- ^ Enable IPv6 on the network.
872+ , createNetworkOptions :: HM.HashMap Text Text -- ^ Options to pass to the driver.
873+ , createNetworkLabels :: [Label] -- ^ Identifying labels for the network.
838− } deriving (Eq, Show)
874+ } deriving (Eq, Show, Generic)
840-- | Sensible defalut for create network options
876-- | Sensible defalut for create network options
841defaultCreateNetworkOpts :: Text -> CreateNetworkOpts
877defaultCreateNetworkOpts :: Text -> CreateNetworkOpts
@@ -843,20 +879,279 @@ defaultCreateNetworkOpts name =
843 CreateNetworkOpts
879 CreateNetworkOpts
844 { createNetworkName = name
880 { createNetworkName = name
845 , createNetworkCheckDuplicate = False
881 , createNetworkCheckDuplicate = False
846− , createNetworkDriver = "bridge"
882+ , createNetworkDriver = NetworkBridge
847 , createNetworkInternal = True
883 , createNetworkInternal = True
884+ , createNetworkAttachable = False
885+ , createNetworkIngress = False
886+ , createNetworkIPAM = defaultIPAM
848 , createNetworkEnableIPv6 = False
887 , createNetworkEnableIPv6 = False
888+ , createNetworkOptions = HM.empty
889+ , createNetworkLabels = []
851instance ToJSON CreateNetworkOpts where
892instance ToJSON CreateNetworkOpts where
852− toJSON opts =
893+ toJSON = genericToJSON defaultOptions
853− object
894+ { fieldLabelModifier = drop 13, omitNothingFields = True }
854− [ "Name" .= createNetworkName opts
895+
855− , "CheckDuplicate" .= createNetworkCheckDuplicate opts
896+data NetworkScope = LocalScope | GlobalScope | SwarmScope deriving (Eq, Show)
856− , "Driver" .= createNetworkDriver opts
897+
857− , "Internal" .= createNetworkInternal opts
898+fromNetworkScope :: NetworkScope -> Text
858− , "EnableIPv6" .= createNetworkEnableIPv6 opts
899+fromNetworkScope LocalScope = "local"
859− ]
900+fromNetworkScope GlobalScope = "global"
901+fromNetworkScope SwarmScope = "swarm"
903+instance ToJSON NetworkScope where
904+ toJSON = JSON.String . fromNetworkScope
906+instance FromJSON NetworkScope where
907+ parseJSON "local" = return LocalScope
908+ parseJSON "global" = return GlobalScope
909+ parseJSON "swarm" = return SwarmScope
910+ parseJSON _ = fail "Failed to parse NetworkScope"
912+data CIDR = CIDR Text Int deriving (Eq, Show, Generic)
914+instance FromJSON CIDR where
915+ parseJSON (JSON.String t) = case T.splitOn "/" t of
916+ [a,p] -> CIDR a <$> parsePrefixLen p
917+ _ -> fail "Failed to parse CIDR"
919+ parsePrefixLen p = case readDec (T.unpack p) of
920+ (n,""):_ -> return n
921+ _ -> fail "Failed to parse CIDR prefix length"
922+ parseJSON _ = fail "Failed to parse CIDR"
924+instance ToJSON CIDR where
925+ toJSON (CIDR addr pref) =
926+ JSON.String $ T.concat [addr, "/", T.pack $ show pref]
928+data IPAMDriver = DefaultIPAMDriver | NamedIPAMDriver Text deriving (Eq, Show, Generic)
930+instance FromJSON IPAMDriver where
931+ parseJSON (JSON.String "default") = return DefaultIPAMDriver
932+ parseJSON (JSON.String t) = return $ NamedIPAMDriver t
933+ parseJSON _ = fail "IPAMDriver is not a string"
935+instance ToJSON IPAMDriver where
936+ toJSON DefaultIPAMDriver = JSON.String "default"
937+ toJSON (NamedIPAMDriver t) = JSON.String t
939+data IPAMConfig = IPAMConfig
940+ { ipamConfigSubnet :: CIDR
941+ , ipamConfigIPRange :: Maybe CIDR
942+ , ipamConfigGateway :: Maybe Text
943+ , ipamConfigAuxAddress :: Maybe Text
944+ } deriving (Eq, Show, Generic)
946+instance FromJSON IPAMConfig where
947+ parseJSON (JSON.Object o) = IPAMConfig
951+ <*> o .:? "AuxAddress"
952+ parseJSON _ = fail "IPAMConfig is not an object"
954+instance ToJSON IPAMConfig where
955+ toJSON = genericToJSON defaultOptions
956+ { fieldLabelModifier = drop 10, omitNothingFields = True }
959+ { ipamDriver :: IPAMDriver
960+ , ipamConfig :: [IPAMConfig]
961+ , ipamOptions :: HM.HashMap Text Text
962+ } deriving (Eq, Show, Generic)
964+instance FromJSON IPAM where
965+ parseJSON (JSON.Object o) = IPAM
966+ <$> o .:? "Driver" .!= DefaultIPAMDriver
967+ <*> o .:? "Config" .!= []
968+ <*> o .:? "Options" .!= HM.empty
969+ parseJSON _ = fail "IPAM is not an object"
971+instance ToJSON IPAM where
972+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 4 }
975+defaultIPAM = IPAM DefaultIPAMDriver [] HM.empty
977+data NetworkContainer = NetworkContainer
978+ { networkContainerName :: ContainerName
979+ , networkContainerEndpointID :: Text
980+ , networkContainerMacAddress :: Text
981+ , networkContainerIPv4Address :: Text
982+ , networkContainerIPv6Address :: Text
983+ } deriving (Eq, Show)
985+instance FromJSON NetworkContainer where
986+ parseJSON (JSON.Object o) = NetworkContainer
988+ <*> o .: "EndpointID"
989+ <*> o .: "MacAddress"
990+ <*> o .: "IPv4Address"
991+ <*> o .: "IPv6Address"
992+ parseJSON _ = fail "NetworkContainer is not an object"
994+data NetworkDetails = NetworkDetails
995+ { networkDetailsName :: Text
996+ , networkDetailsID :: NetworkID
997+ , networkDetailsCreated :: UTCTime
998+ , networkDetailsScope :: NetworkScope
999+ , networkDetailsDriver :: NetworkMode
1000+ , networkDetailsEnableIPv6 :: Bool
1001+ , networkDetailsInternal :: Bool
1002+ , networkDetailsAttachable :: Bool
1003+ , networkDetailsIngress :: Bool
1004+ , networkDetailsIPAM :: IPAM
1005+ , networkDetailsOptions :: HM.HashMap Text Text
1006+ , networkDetailsLabels :: [Label]
1007+ , networkDetailsContainers :: HM.HashMap Text NetworkContainer
1008+ } deriving (Eq, Show)
1010+instance FromJSON NetworkDetails where
1011+ parseJSON v@(JSON.Object o) = NetworkDetails
1017+ <*> o .: "EnableIPv6"
1018+ <*> o .: "Internal"
1019+ <*> o .: "Attachable"
1022+ <*> o .:? "Options" .!= HM.empty
1023+ <*> o .:? "Labels" .!= []
1024+ <*> o .:? "Containers" .!= HM.empty
1025+ parseJSON _ = fail "NetworkDetails is not an object"
1027+data NetworkType = BuiltinNetwork | CustomNetwork deriving (Eq, Show)
1029+fromNetworkType :: NetworkType -> Text
1030+fromNetworkType BuiltinNetwork = "builtin"
1031+fromNetworkType CustomNetwork = "custom"
1033+type NetworkName = Text
1035+instance ToJSON NetworkType where
1036+ toJSON = JSON.String . fromNetworkType
1038+instance FromJSON NetworkType where
1039+ parseJSON (JSON.String "builtin") = return BuiltinNetwork
1040+ parseJSON (JSON.String "custom") = return CustomNetwork
1041+ parseJSON _ = fail "Failed to parse NetworkType"
1043+data NetworkFilter = NetworkFilter
1044+ { networkFilterNames :: [Text]
1045+ , networkFilterIDs :: [NetworkID]
1046+ , networkFilterDrivers :: [NetworkMode]
1047+ , networkFilterScopes :: [NetworkScope]
1048+ , networkFilterTypes :: [NetworkType]
1049+ , networkFilterLabels :: [(Text, (Maybe Text))]
1050+ } deriving (Eq, Show)
1052+instance ToJSON NetworkFilter where
1053+ toJSON nf = object . catMaybes $
1054+ [ "name" .=? networkFilterNames nf
1055+ , "id" .=? (fromNetworkID <$> networkFilterIDs nf)
1056+ , "driver" .=? (fromNetworkMode <$> networkFilterDrivers nf)
1057+ , "scope" .=? (fromNetworkScope <$> networkFilterScopes nf)
1058+ , "type" .=? (fromNetworkType <$> networkFilterTypes nf)
1059+ , "label" .=? (constructLabel <$> networkFilterLabels nf)
1063+ k .=? l = Just $ k .= l
1065+constructLabel :: (Text, Maybe Text) -> Text
1066+constructLabel (k, Just v) = T.concat [k, "=", v]
1067+constructLabel (k, Nothing) = k
1069+defaultNetworkFilter :: NetworkFilter
1070+defaultNetworkFilter = NetworkFilter [] [] [] [] [] []
1072+data ConnectConfig = ConnectConfig
1073+ { connectContainer :: Text
1074+ , connectEndpointConfig :: EndpointSettings
1075+ } deriving (Eq, Show, Generic)
1077+instance ToJSON ConnectConfig where
1078+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 7 }
1080+defaultConnectConfig :: Text -> ConnectConfig
1081+defaultConnectConfig = flip ConnectConfig defaultEndpointSettings
1083+data DisconnectConfig = DisconnectConfig
1084+ { disconnectContainer :: Text
1085+ , disconnectForce :: Bool
1086+ } deriving (Eq, Show, Generic)
1088+instance ToJSON DisconnectConfig where
1089+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 10 }
1091+defaultDisconnectConfig :: Text -> DisconnectConfig
1092+defaultDisconnectConfig = flip DisconnectConfig False
1094+data PruneFilter = PruneFilter
1095+ { pruneFilterUntil :: Maybe Text
1096+ -- ^ Can be a Unix timestamp, a date-formatted timestamp, or a duration,
1097+ -- such as @10m@ or @1h30m@.
1098+ , pruneFilterIncludeLabels :: [(Text, (Maybe Text))]
1099+ , pruneFilterExcludeLabels :: [(Text, (Maybe Text))]
1100+ } deriving (Eq, Show)
1102+instance ToJSON PruneFilter where
1103+ toJSON pf = object . catMaybes $
1104+ [ "until" .=? maybeToList (pruneFilterUntil pf)
1105+ , "label" .=? (constructLabel <$> pruneFilterIncludeLabels pf)
1106+ , "label!" .=? (constructLabel <$> pruneFilterExcludeLabels pf)
1110+ k .=? l = Just $ k .= l
1112+defaultPruneFilter :: PruneFilter
1113+defaultPruneFilter = PruneFilter Nothing [] []
1115+newtype NetworksDeleted = NetworksDeleted [Text]
1116+ deriving (Eq, Show)
1118+instance FromJSON NetworksDeleted where
1119+ parseJSON (JSON.Object o) =
1120+ NetworksDeleted . join . maybeToList <$> o .: "NetworksDeleted"
1121+ parseJSON _ = fail $ "NetworksDeleted is not an object"
1123+data EndpointSettings = EndpointSettings
1124+ { endpointIPAMConfig :: IPAMSettings
1125+ , endpointLinks :: [Text]
1126+ , endpointAliases :: [Text]
1127+ , endpointNetworkID :: Maybe Text
1128+ , endpointEndpointID :: Maybe Text
1129+ , endpointGateway :: Maybe Text
1130+ , endpointIPAddress :: Maybe Text
1131+ , endpointIPPrefixLen :: Maybe Int
1132+ , endpointIPv6Gateway :: Maybe Text
1133+ , endpointGlobalIPv6Address :: Maybe Text
1134+ , endpointGlobalIPv6PrefixLen :: Maybe Int
1135+ , endpointMacAddress :: Maybe Text
1136+ } deriving (Eq, Show, Generic)
1138+instance ToJSON EndpointSettings where
1139+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 8 }
1141+defaultEndpointSettings :: EndpointSettings
1142+defaultEndpointSettings = EndpointSettings defaultIPAMSettings [] [] Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1144+data IPAMSettings = IPAMSettings
1145+ { ipamIPv4Address :: Maybe Text
1146+ , ipamIPv6Address :: Maybe Text
1147+ , ipamLinkLocalIPs :: [Text]
1148+ } deriving (Eq, Show, Generic)
1150+instance ToJSON IPAMSettings where
1151+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 4 }
1153+defaultIPAMSettings :: IPAMSettings
1154+defaultIPAMSettings = IPAMSettings Nothing Nothing []
861-- TOOD: Add support for SELinux Volume labels (eg. "ro,z" or "ro/Z")
1156-- TOOD: Add support for SELinux Volume labels (eg. "ro,z" or "ro/Z")
862-- | Set permissions on volumes that you mount in the container.
1157-- | Set permissions on volumes that you mount in the container.
@@ -1027,11 +1322,14 @@ instance FromJSON NetworkMode where
1027 parseJSON (JSON.String n) = return $ NetworkNamed n
1322 parseJSON (JSON.String n) = return $ NetworkNamed n
1028 parseJSON _ = fail "Unknown NetworkMode"
1323 parseJSON _ = fail "Unknown NetworkMode"
1325+fromNetworkMode :: NetworkMode -> Text
1326+fromNetworkMode NetworkBridge = "bridge"
1327+fromNetworkMode NetworkHost = "host"
1328+fromNetworkMode NetworkDisabled = "none"
1329+fromNetworkMode (NetworkNamed n) = n
1030instance ToJSON NetworkMode where
1331instance ToJSON NetworkMode where
1031− toJSON NetworkBridge = JSON.String "bridge"
1332+ 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
1334newtype NetworkID = NetworkID Text
1037 deriving (Eq, Show)
1335 deriving (Eq, Show)