module Propellor.Property.Network where
import Propellor.Base
import Propellor.Property.File
import Data.Char
type Interface = String
type InterfaceOptions = [(String, String)]
type InterfaceStanza = ([String], InterfaceOptions)
ifUp :: Interface -> Property DebianLike
ifUp :: Interface -> Property DebianLike
ifUp Interface
iface = Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
forall (p :: * -> *) (untightened :: [MetaType])
(tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets (Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike)
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
forall a b. (a -> b) -> a -> b
$ Interface
-> [Interface]
-> UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
cmdProperty Interface
"ifup" [Interface
iface]
UncheckedProperty
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Result
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
MadeChange
cleanInterfacesFile :: Property DebianLike
cleanInterfacesFile :: Property DebianLike
cleanInterfacesFile = Interface -> [Interface] -> InterfaceOptions -> Property DebianLike
interfaceFileContains Interface
interfacesFile
[ Interface
"source-directory interfaces.d"
, Interface
""
, Interface
"# The loopback network interface"
, Interface
"auto lo"
, Interface
"iface lo inet loopback"
]
[]
Property DebianLike -> Interface -> Property DebianLike
forall p. IsProp p => p -> Interface -> p
`describe` (Interface
"clean " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
interfacesFile)
dhcp :: Interface -> Property DebianLike
dhcp :: Interface -> Property DebianLike
dhcp Interface
iface = Interface -> InterfaceOptions -> Property DebianLike
dhcp' Interface
iface InterfaceOptions
forall a. Monoid a => a
mempty
dhcp' :: Interface -> InterfaceOptions -> Property DebianLike
dhcp' :: Interface -> InterfaceOptions -> Property DebianLike
dhcp' Interface
iface InterfaceOptions
options = Interface -> [Interface] -> InterfaceOptions -> Property DebianLike
interfaceFileContains (Interface -> Interface
interfaceDFile Interface
iface)
[ Interface
"auto " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface
, Interface
"iface " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
" inet dhcp"
] InterfaceOptions
options
Property DebianLike -> Interface -> Property DebianLike
forall p. IsProp p => p -> Interface -> p
`describe` (Interface
"dhcp " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface)
Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
interfacesDEnabled
newtype Gateway = Gateway IPAddr
static :: Interface -> IPAddr -> Maybe Gateway -> Property DebianLike
static :: Interface -> IPAddr -> Maybe Gateway -> Property DebianLike
static Interface
iface IPAddr
addr Maybe Gateway
gateway = Interface
-> IPAddr
-> Maybe Gateway
-> InterfaceOptions
-> Property DebianLike
static' Interface
iface IPAddr
addr Maybe Gateway
gateway InterfaceOptions
forall a. Monoid a => a
mempty
static' :: Interface -> IPAddr -> Maybe Gateway -> InterfaceOptions -> Property DebianLike
static' :: Interface
-> IPAddr
-> Maybe Gateway
-> InterfaceOptions
-> Property DebianLike
static' Interface
iface IPAddr
addr Maybe Gateway
gateway InterfaceOptions
options =
Interface
-> [(IPAddr, Maybe Gateway, InterfaceOptions)]
-> Property DebianLike
static'' Interface
iface [(IPAddr
addr, Maybe Gateway
gateway, InterfaceOptions
options)]
static'' :: Interface -> [(IPAddr, Maybe Gateway, InterfaceOptions)] -> Property DebianLike
static'' :: Interface
-> [(IPAddr, Maybe Gateway, InterfaceOptions)]
-> Property DebianLike
static'' Interface
iface [(IPAddr, Maybe Gateway, InterfaceOptions)]
confs =
Interface -> [InterfaceStanza] -> Property DebianLike
interfaceFileContains' (Interface -> Interface
interfaceDFile Interface
iface) [InterfaceStanza]
stanzas
Property DebianLike -> Interface -> Property DebianLike
forall p. IsProp p => p -> Interface -> p
`describe` (Interface
"static IP address for " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface)
Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
interfacesDEnabled
where
stanzas :: [InterfaceStanza]
stanzas = ((IPAddr, Maybe Gateway, InterfaceOptions) -> InterfaceStanza)
-> [(IPAddr, Maybe Gateway, InterfaceOptions)] -> [InterfaceStanza]
forall a b. (a -> b) -> [a] -> [b]
map (IPAddr, Maybe Gateway, InterfaceOptions) -> InterfaceStanza
stanza [(IPAddr, Maybe Gateway, InterfaceOptions)]
confs
stanza :: (IPAddr, Maybe Gateway, InterfaceOptions) -> InterfaceStanza
stanza (IPAddr
addr, Maybe Gateway
gateway, InterfaceOptions
options) = (IPAddr -> [Interface]
headerlines IPAddr
addr, IPAddr -> Maybe Gateway -> InterfaceOptions -> InterfaceOptions
forall t.
ConfigurableValue t =>
t -> Maybe Gateway -> InterfaceOptions -> InterfaceOptions
options' IPAddr
addr Maybe Gateway
gateway InterfaceOptions
options)
headerlines :: IPAddr -> [Interface]
headerlines IPAddr
addr =
[ Interface
"auto " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface
, Interface
"iface " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
" " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ (IPAddr -> Interface
inet IPAddr
addr) Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
" static"
]
options' :: t -> Maybe Gateway -> InterfaceOptions -> InterfaceOptions
options' t
addr Maybe Gateway
gateway InterfaceOptions
options = [Maybe (Interface, Interface)] -> InterfaceOptions
forall a. [Maybe a] -> [a]
catMaybes
[ (Interface, Interface) -> Maybe (Interface, Interface)
forall a. a -> Maybe a
Just ((Interface, Interface) -> Maybe (Interface, Interface))
-> (Interface, Interface) -> Maybe (Interface, Interface)
forall a b. (a -> b) -> a -> b
$ (Interface
"address", t -> Interface
forall t. ConfigurableValue t => t -> Interface
val t
addr)
, case Maybe Gateway
gateway of
Just (Gateway IPAddr
gaddr) ->
(Interface, Interface) -> Maybe (Interface, Interface)
forall a. a -> Maybe a
Just (Interface
"gateway", IPAddr -> Interface
forall t. ConfigurableValue t => t -> Interface
val IPAddr
gaddr)
Maybe Gateway
Nothing -> Maybe (Interface, Interface)
forall a. Maybe a
Nothing
] InterfaceOptions -> InterfaceOptions -> InterfaceOptions
forall a. [a] -> [a] -> [a]
++ InterfaceOptions
options
inet :: IPAddr -> Interface
inet IPAddr
addr = case IPAddr
addr of
IPv4 Interface
_ -> Interface
"inet"
IPv6 Interface
_ -> Interface
"inet6"
preserveStatic :: Interface -> Property DebianLike
preserveStatic :: Interface -> Property DebianLike
preserveStatic Interface
iface = Property DebianLike -> Property DebianLike
forall (p :: * -> *) (untightened :: [MetaType])
(tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets (Property DebianLike -> Property DebianLike)
-> Property DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$
IO Bool -> Property DebianLike -> Property DebianLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Interface -> IO Bool
doesFileExist Interface
f) Property DebianLike
setup
Property DebianLike -> Interface -> Property DebianLike
forall p. IsProp p => p -> Interface -> p
`describe` Interface
desc
Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
interfacesDEnabled
where
f :: Interface
f = Interface -> Interface
interfaceDFile Interface
iface
desc :: Interface
desc = Interface
"static " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface
setup :: Property DebianLike
setup :: Property DebianLike
setup = Interface
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
-> Propellor Result)
-> Property DebianLike
forall k (metatypes :: k).
SingI metatypes =>
Interface
-> (OuterMetaTypesWitness metatypes -> Propellor Result)
-> Property (MetaTypes metatypes)
property' Interface
desc ((OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
-> Propellor Result)
-> Property DebianLike)
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
-> Propellor Result)
-> Property DebianLike
forall a b. (a -> b) -> a -> b
$ \OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
o -> do
[Interface]
ls <- IO [Interface] -> Propellor [Interface]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [Interface] -> Propellor [Interface])
-> IO [Interface] -> Propellor [Interface]
forall a b. (a -> b) -> a -> b
$ Interface -> [Interface]
lines (Interface -> [Interface]) -> IO Interface -> IO [Interface]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Interface -> [Interface] -> IO Interface
readProcess Interface
"ip"
[Interface
"-o", Interface
"addr", Interface
"show", Interface
iface, Interface
"scope", Interface
"global"]
[Interface]
stanzas <- IO [Interface] -> Propellor [Interface]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [Interface] -> Propellor [Interface])
-> IO [Interface] -> Propellor [Interface]
forall a b. (a -> b) -> a -> b
$ [[Interface]] -> [Interface]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Interface]] -> [Interface])
-> IO [[Interface]] -> IO [Interface]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Interface -> IO [Interface]) -> [Interface] -> IO [[Interface]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Interface -> IO [Interface]
mkstanza [Interface]
ls
OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Propellor Result
forall (inner :: [MetaType]) (outer :: [MetaType]).
EnsurePropertyAllowed inner outer =>
OuterMetaTypesWitness outer
-> Property (MetaTypes inner) -> Propellor Result
ensureProperty OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
o (Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Propellor Result)
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Propellor Result
forall a b. (a -> b) -> a -> b
$ Interface
-> [Interface]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
hasContent Interface
f ([Interface]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
-> [Interface]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall a b. (a -> b) -> a -> b
$ (Interface
"auto " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface) Interface -> [Interface] -> [Interface]
forall a. a -> [a] -> [a]
: [Interface]
stanzas
mkstanza :: Interface -> IO [Interface]
mkstanza Interface
ipline = case Interface -> [Interface]
words Interface
ipline of
(Interface
_:Interface
iface':Interface
"inet":Interface
addr:[Interface]
_) | Interface
iface' Interface -> Interface -> Bool
forall a. Eq a => a -> a -> Bool
== Interface
iface -> do
Maybe Interface
gw <- IO (Maybe Interface)
getgateway
[Interface] -> IO [Interface]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Interface] -> IO [Interface]) -> [Interface] -> IO [Interface]
forall a b. (a -> b) -> a -> b
$ [Maybe Interface] -> [Interface]
forall a. [Maybe a] -> [a]
catMaybes
[ Interface -> Maybe Interface
forall a. a -> Maybe a
Just (Interface -> Maybe Interface) -> Interface -> Maybe Interface
forall a b. (a -> b) -> a -> b
$ Interface
"iface " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
iface Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
" inet static"
, Interface -> Maybe Interface
forall a. a -> Maybe a
Just (Interface -> Maybe Interface) -> Interface -> Maybe Interface
forall a b. (a -> b) -> a -> b
$ Interface
"\taddress " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
addr
, (Interface
"\tgateway " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++) (Interface -> Interface) -> Maybe Interface -> Maybe Interface
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Interface
gw
]
[Interface]
_ -> [Interface] -> IO [Interface]
forall (m :: * -> *) a. Monad m => a -> m a
return []
getgateway :: IO (Maybe Interface)
getgateway = do
[Interface]
rs <- Interface -> [Interface]
lines (Interface -> [Interface]) -> IO Interface -> IO [Interface]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Interface -> [Interface] -> IO Interface
readProcess Interface
"ip"
[Interface
"route", Interface
"show", Interface
"scope", Interface
"global", Interface
"dev", Interface
iface]
Maybe Interface -> IO (Maybe Interface)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Interface -> IO (Maybe Interface))
-> Maybe Interface -> IO (Maybe Interface)
forall a b. (a -> b) -> a -> b
$ case Interface -> [Interface]
words (Interface -> [Interface]) -> Maybe Interface -> Maybe [Interface]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Interface] -> Maybe Interface
forall a. [a] -> Maybe a
headMaybe [Interface]
rs of
Just (Interface
"default":Interface
"via":Interface
gw:[Interface]
_) -> Interface -> Maybe Interface
forall a. a -> Maybe a
Just Interface
gw
Maybe [Interface]
_ -> Maybe Interface
forall a. Maybe a
Nothing
ipv6to4 :: Property DebianLike
ipv6to4 :: Property DebianLike
ipv6to4 = Property DebianLike -> Property DebianLike
forall (p :: * -> *) (untightened :: [MetaType])
(tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets (Property DebianLike -> Property DebianLike)
-> Property DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$ Interface -> [Interface] -> InterfaceOptions -> Property DebianLike
interfaceFileContains (Interface -> Interface
interfaceDFile Interface
"sit0")
[ Interface
"auto sit0"
, Interface
"iface sit0 inet6 static"
]
[ (Interface
"address", Interface
"2002:5044:5531::1")
, (Interface
"netmask", Interface
"64")
, (Interface
"gateway", Interface
"::192.88.99.1")
]
Property DebianLike -> Interface -> Property DebianLike
forall p. IsProp p => p -> Interface -> p
`describe` Interface
"ipv6to4"
Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
interfacesDEnabled
Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Interface -> Property DebianLike
ifUp Interface
"sit0"
interfacesFile :: FilePath
interfacesFile :: Interface
interfacesFile = Interface
"/etc/network/interfaces"
interfaceDFile :: Interface -> FilePath
interfaceDFile :: Interface -> Interface
interfaceDFile Interface
i = Interface
"/etc/network/interfaces.d" Interface -> Interface -> Interface
</> Interface -> Interface
escapeInterfaceDName Interface
i
escapeInterfaceDName :: Interface -> FilePath
escapeInterfaceDName :: Interface -> Interface
escapeInterfaceDName = (Char -> Bool) -> Interface -> Interface
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
c -> Char -> Bool
isAscii Char
c Bool -> Bool -> Bool
&& (Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> Interface -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Interface
"_-"))
interfacesDEnabled :: Property DebianLike
interfacesDEnabled :: Property DebianLike
interfacesDEnabled = Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
forall (p :: * -> *) (untightened :: [MetaType])
(tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets (Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike)
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
forall a b. (a -> b) -> a -> b
$
Interface
-> Interface
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
containsLine Interface
interfacesFile Interface
"source-directory interfaces.d"
Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Interface
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall p. IsProp p => p -> Interface -> p
`describe` Interface
"interfaces.d directory enabled"
interfaceFileContains :: FilePath -> [String] -> InterfaceOptions -> Property DebianLike
interfaceFileContains :: Interface -> [Interface] -> InterfaceOptions -> Property DebianLike
interfaceFileContains Interface
f [Interface]
headerlines InterfaceOptions
options =
Interface -> [InterfaceStanza] -> Property DebianLike
interfaceFileContains' Interface
f [([Interface]
headerlines, InterfaceOptions
options)]
interfaceFileContains' :: FilePath -> [InterfaceStanza] -> Property DebianLike
interfaceFileContains' :: Interface -> [InterfaceStanza] -> Property DebianLike
interfaceFileContains' Interface
f [InterfaceStanza]
stanzas = Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
forall (p :: * -> *) (untightened :: [MetaType])
(tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets (Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike)
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
-> Property DebianLike
forall a b. (a -> b) -> a -> b
$ Interface
-> [Interface]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
hasContent Interface
f ([Interface]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
-> [Interface]
-> Property
(MetaTypes
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
forall a b. (a -> b) -> a -> b
$
Interface
warning Interface -> [Interface] -> [Interface]
forall a. a -> [a] -> [a]
: (InterfaceStanza -> [Interface])
-> [InterfaceStanza] -> [Interface]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap InterfaceStanza -> [Interface]
stanza [InterfaceStanza]
stanzas
where
stanza :: InterfaceStanza -> [Interface]
stanza ([Interface]
headerlines, InterfaceOptions
options) = [Interface]
headerlines [Interface] -> [Interface] -> [Interface]
forall a. [a] -> [a] -> [a]
++ ((Interface, Interface) -> Interface)
-> InterfaceOptions -> [Interface]
forall a b. (a -> b) -> [a] -> [b]
map (Interface, Interface) -> Interface
fmt InterfaceOptions
options
fmt :: (Interface, Interface) -> Interface
fmt (Interface
k, Interface
v) = Interface
"\t" Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
k Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
" " Interface -> Interface -> Interface
forall a. [a] -> [a] -> [a]
++ Interface
v
warning :: Interface
warning = Interface
"# Deployed by propellor, do not edit."