{-# LANGUAGE LambdaCase #-}
module Propellor.Property.Hostname where
import Propellor.Base
import qualified Propellor.Property.File as File
import Propellor.Types.Container
import Utility.Split
import Data.List
sane :: Property UnixLike
sane :: Property UnixLike
sane = ExtractDomain -> Property UnixLike
sane' ExtractDomain
extractDomain
sane' :: ExtractDomain -> Property UnixLike
sane' :: ExtractDomain -> Property UnixLike
sane' ExtractDomain
extractdomain = Desc
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike
forall {k} (metatypes :: k).
SingI metatypes =>
Desc
-> (OuterMetaTypesWitness metatypes -> Propellor Result)
-> Property (MetaTypes metatypes)
property' (Desc
"sane hostname") ((OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike)
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike
forall a b. (a -> b) -> a -> b
$ \OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
w ->
OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Property UnixLike -> Propellor Result
forall (inner :: [MetaType]) (outer :: [MetaType]).
EnsurePropertyAllowed inner outer =>
OuterMetaTypesWitness outer
-> Property (MetaTypes inner) -> Propellor Result
ensureProperty OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
w (Property UnixLike -> Propellor Result)
-> (Desc -> Property UnixLike) -> Desc -> Propellor Result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtractDomain -> Desc -> Property UnixLike
setTo' ExtractDomain
extractdomain (Desc -> Propellor Result) -> Propellor Desc -> Propellor Result
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Host -> Desc) -> Propellor Desc
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Host -> Desc
hostName
setTo :: HostName -> Property UnixLike
setTo :: Desc -> Property UnixLike
setTo = ExtractDomain -> Desc -> Property UnixLike
setTo' ExtractDomain
extractDomain
setTo' :: ExtractDomain -> HostName -> Property UnixLike
setTo' :: ExtractDomain -> Desc -> Property UnixLike
setTo' ExtractDomain
extractdomain Desc
hn = Desc -> Props UnixLike -> Property UnixLike
forall {k} (metatypes :: k).
SingI metatypes =>
Desc
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties Desc
desc (Props UnixLike -> Property UnixLike)
-> Props UnixLike -> Property UnixLike
forall a b. (a -> b) -> a -> b
$ [Property UnixLike] -> Props UnixLike
forall {k} (metatypes :: k).
[Property (MetaTypes metatypes)] -> Props (MetaTypes metatypes)
toProps
[ Desc
"/etc/hostname" Desc -> [Desc] -> Property UnixLike
`File.hasContent` [Desc
basehost]
, [(Desc, [Desc])] -> Property UnixLike
hostslines ([(Desc, [Desc])] -> Property UnixLike)
-> [(Desc, [Desc])] -> Property UnixLike
forall a b. (a -> b) -> a -> b
$ [Maybe (Desc, [Desc])] -> [(Desc, [Desc])]
forall a. [Maybe a] -> [a]
catMaybes
[ if Desc -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Desc
domain
then Maybe (Desc, [Desc])
forall a. Maybe a
Nothing
else (Desc, [Desc]) -> Maybe (Desc, [Desc])
forall a. a -> Maybe a
Just (Desc
"127.0.1.1", [Desc
hn, Desc
basehost])
, (Desc, [Desc]) -> Maybe (Desc, [Desc])
forall a. a -> Maybe a
Just (Desc
"127.0.0.1", [Desc
"localhost"])
]
, Propellor Bool -> Property UnixLike -> Property UnixLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check Propellor Bool
safetochange (Property UnixLike -> Property UnixLike)
-> Property UnixLike -> Property UnixLike
forall a b. (a -> b) -> a -> b
$
Desc -> [Desc] -> UncheckedProperty UnixLike
cmdProperty Desc
"hostname" [Desc
basehost]
UncheckedProperty UnixLike -> Result -> Property UnixLike
forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
NoChange
]
where
desc :: Desc
desc = Desc
"hostname " Desc -> ExtractDomain
forall a. [a] -> [a] -> [a]
++ Desc
hn
basehost :: Desc
basehost = (Char -> Bool) -> ExtractDomain
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') Desc
hn
domain :: Desc
domain = ExtractDomain
extractdomain Desc
hn
safetochange :: Propellor Bool
safetochange = Propellor [ContainerCapability]
forall v. IsInfo v => Propellor v
askInfo Propellor [ContainerCapability]
-> ([ContainerCapability] -> Propellor Bool) -> Propellor Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> Propellor Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Propellor Bool)
-> ([ContainerCapability] -> Bool)
-> [ContainerCapability]
-> Propellor Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
[] -> Bool
True
[ContainerCapability]
caps -> ContainerCapability
HostnameContained ContainerCapability -> [ContainerCapability] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ContainerCapability]
caps
hostslines :: [(Desc, [Desc])] -> Property UnixLike
hostslines [(Desc, [Desc])]
ipsnames =
Desc -> ([Desc] -> [Desc]) -> Desc -> Property UnixLike
forall c.
(FileContent c, Eq c) =>
Desc -> (c -> c) -> Desc -> Property UnixLike
File.fileProperty Desc
desc ([(Desc, [Desc])] -> [Desc] -> [Desc]
addhostslines [(Desc, [Desc])]
ipsnames) Desc
"/etc/hosts"
addhostslines :: [(String, [String])] -> [String] -> [String]
addhostslines :: [(Desc, [Desc])] -> [Desc] -> [Desc]
addhostslines [(Desc, [Desc])]
ipsnames [Desc]
ls =
let ips :: [Desc]
ips = ((Desc, [Desc]) -> Desc) -> [(Desc, [Desc])] -> [Desc]
forall a b. (a -> b) -> [a] -> [b]
map (Desc, [Desc]) -> Desc
forall a b. (a, b) -> a
fst [(Desc, [Desc])]
ipsnames
hasip :: Desc -> Bool
hasip Desc
l = Bool -> (Desc -> Bool) -> Maybe Desc -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Desc -> [Desc] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Desc]
ips) ([Desc] -> Maybe Desc
forall a. [a] -> Maybe a
headMaybe (Desc -> [Desc]
words Desc
l))
mkline :: (Desc, [Desc]) -> Desc
mkline (Desc
ip, [Desc]
names) = Desc
ip Desc -> ExtractDomain
forall a. [a] -> [a] -> [a]
++ Desc
"\t" Desc -> ExtractDomain
forall a. [a] -> [a] -> [a]
++ ([Desc] -> Desc
unwords [Desc]
names)
in ((Desc, [Desc]) -> Desc) -> [(Desc, [Desc])] -> [Desc]
forall a b. (a -> b) -> [a] -> [b]
map (Desc, [Desc]) -> Desc
mkline [(Desc, [Desc])]
ipsnames [Desc] -> [Desc] -> [Desc]
forall a. [a] -> [a] -> [a]
++ (Desc -> Bool) -> [Desc] -> [Desc]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Desc -> Bool) -> Desc -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Desc -> Bool
hasip) [Desc]
ls
searchDomain :: Property UnixLike
searchDomain :: Property UnixLike
searchDomain = ExtractDomain -> Property UnixLike
searchDomain' ExtractDomain
extractDomain
searchDomain' :: ExtractDomain -> Property UnixLike
searchDomain' :: ExtractDomain -> Property UnixLike
searchDomain' ExtractDomain
extractdomain = Desc
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike
forall {k} (metatypes :: k).
SingI metatypes =>
Desc
-> (OuterMetaTypesWitness metatypes -> Propellor Result)
-> Property (MetaTypes metatypes)
property' Desc
desc ((OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike)
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike
forall a b. (a -> b) -> a -> b
$ \OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
w ->
(OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Property UnixLike -> Propellor Result
forall (inner :: [MetaType]) (outer :: [MetaType]).
EnsurePropertyAllowed inner outer =>
OuterMetaTypesWitness outer
-> Property (MetaTypes inner) -> Propellor Result
ensureProperty OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
w (Property UnixLike -> Propellor Result)
-> (Desc -> Property UnixLike) -> Desc -> Propellor Result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Desc -> Property UnixLike
go (Desc -> Propellor Result) -> Propellor Desc -> Propellor Result
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Host -> Desc) -> Propellor Desc
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Host -> Desc
hostName)
where
desc :: Desc
desc = Desc
"resolv.conf search and domain configured"
go :: Desc -> Property UnixLike
go Desc
hn =
let domain :: Desc
domain = ExtractDomain
extractdomain Desc
hn
in Desc -> ([Desc] -> [Desc]) -> Desc -> Property UnixLike
forall c.
(FileContent c, Eq c) =>
Desc -> (c -> c) -> Desc -> Property UnixLike
File.fileProperty Desc
desc (Desc -> [Desc] -> [Desc]
use Desc
domain) Desc
"/etc/resolv.conf"
use :: Desc -> [Desc] -> [Desc]
use Desc
domain [Desc]
ls = (Desc -> Bool) -> [Desc] -> [Desc]
forall a. (a -> Bool) -> [a] -> [a]
filter Desc -> Bool
wanted ([Desc] -> [Desc]) -> [Desc] -> [Desc]
forall a b. (a -> b) -> a -> b
$ [Desc] -> [Desc]
forall a. Eq a => [a] -> [a]
nub ([Desc]
ls [Desc] -> [Desc] -> [Desc]
forall a. [a] -> [a] -> [a]
++ [Desc]
cfgs)
where
cfgs :: [Desc]
cfgs = [Desc
"domain " Desc -> ExtractDomain
forall a. [a] -> [a] -> [a]
++ Desc
domain, Desc
"search " Desc -> ExtractDomain
forall a. [a] -> [a] -> [a]
++ Desc
domain]
wanted :: Desc -> Bool
wanted Desc
l
| Desc
l Desc -> [Desc] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Desc]
cfgs = Bool
True
| Desc
"domain " Desc -> Desc -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` Desc
l = Bool
False
| Desc
"search " Desc -> Desc -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` Desc
l = Bool
False
| Bool
otherwise = Bool
True
mailname :: Property UnixLike
mailname :: Property UnixLike
mailname = ExtractDomain -> Property UnixLike
mailname' ExtractDomain
extractDomain
mailname' :: ExtractDomain -> Property UnixLike
mailname' :: ExtractDomain -> Property UnixLike
mailname' ExtractDomain
extractdomain = Desc
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike
forall {k} (metatypes :: k).
SingI metatypes =>
Desc
-> (OuterMetaTypesWitness metatypes -> Propellor Result)
-> Property (MetaTypes metatypes)
property' (Desc
"mailname set from hostname") ((OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike)
-> (OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Propellor Result)
-> Property UnixLike
forall a b. (a -> b) -> a -> b
$ \OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
w ->
OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
-> Property UnixLike -> Propellor Result
forall (inner :: [MetaType]) (outer :: [MetaType]).
EnsurePropertyAllowed inner outer =>
OuterMetaTypesWitness outer
-> Property (MetaTypes inner) -> Propellor Result
ensureProperty OuterMetaTypesWitness
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
w (Property UnixLike -> Propellor Result)
-> (Desc -> Property UnixLike) -> Desc -> Propellor Result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Desc -> Property UnixLike
go (Desc -> Propellor Result) -> Propellor Desc -> Propellor Result
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Host -> Desc) -> Propellor Desc
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Host -> Desc
hostName
where
go :: Desc -> Property UnixLike
go Desc
mn = Desc
"/etc/mailname" Desc -> [Desc] -> Property UnixLike
`File.hasContent` [if Desc -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Desc
mn' then Desc
mn else Desc
mn']
where
mn' :: Desc
mn' = ExtractDomain
extractdomain Desc
mn
type ExtractDomain = HostName -> String
extractDomain :: ExtractDomain
extractDomain :: ExtractDomain
extractDomain Desc
hn =
let bits :: [Desc]
bits = Desc -> Desc -> [Desc]
forall a. Eq a => [a] -> [a] -> [[a]]
split Desc
"." Desc
hn
in Desc -> [Desc] -> Desc
forall a. [a] -> [[a]] -> [a]
intercalate Desc
"." ([Desc] -> Desc) -> [Desc] -> Desc
forall a b. (a -> b) -> a -> b
$
if [Desc] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Desc]
bits Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2
then Int -> [Desc] -> [Desc]
forall a. Int -> [a] -> [a]
drop Int
1 [Desc]
bits
else [Desc]
bits