1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
-- | FreeBSD Poudriere properties
--
-- Copyright 2016 Evan Cofsky <evan@theunixman.com>
-- License: BSD 2-clause
{-# Language GeneralizedNewtypeDeriving #-}
-- | Maintainer: Evan Cofsky <evan@theunixman.com>
module Propellor.Property.FreeBSD.Poudriere where
import Propellor.Base
import Propellor.Types.Info
import Data.List
import Data.String (IsString(..))
import qualified Propellor.Property.FreeBSD.Pkg as Pkg
import qualified Propellor.Property.ZFS as ZFS
import qualified Propellor.Property.File as File
poudriereConfigPath :: FilePath
poudriereConfigPath = "/usr/local/etc/poudriere.conf"
newtype PoudriereConfigured = PoudriereConfigured String
deriving (Typeable, Monoid, Show)
instance IsInfo PoudriereConfigured where
propagateInfo _ = False
poudriereConfigured :: PoudriereConfigured -> Bool
poudriereConfigured (PoudriereConfigured _) = True
setConfigured :: Property HasInfo
setConfigured = pureInfoProperty "Poudriere Configured" (PoudriereConfigured "")
poudriere :: Poudriere -> Property HasInfo
poudriere conf@(Poudriere _ _ _ _ _ _ zfs) =
let
confProp =
File.containsLines poudriereConfigPath (toLines conf)
setZfs (PoudriereZFS z p) = ZFS.zfsSetProperties z p `describe` "Configuring Poudriere with ZFS"
prop :: CombinedType (Property NoInfo) (Property NoInfo)
prop =
if isJust zfs
then ((setZfs $ fromJust zfs) `before` confProp)
else propertyList "Configuring Poudriere without ZFS" [confProp]
in
prop
`requires` Pkg.installed "poudriere"
`before` setConfigured
poudriereCommand :: String -> [String] -> (String, [String])
poudriereCommand cmd args = ("poudriere", cmd:args)
runPoudriere :: String -> [String] -> IO [String]
runPoudriere cmd args =
let
(p, a) = poudriereCommand cmd args
in
lines <$> readProcess p a
listJails :: IO [String]
listJails = runPoudriere "jail" ["-l", "-q"]
jailExists :: Jail -> IO Bool
jailExists (Jail name _ _) = isInfixOf [name] <$> listJails
jail :: Jail -> Property NoInfo
jail j@(Jail name version arch) =
let
cfgd = poudriereConfigured <$> askInfo
notExists :: IO Bool
notExists = not <$> jailExists j
chk = do
c <- cfgd
x <- liftIO notExists
return $ c && x
(cmd, args) = poudriereCommand "jail" ["-c", "-j", name, "-a", show arch, "-v", show version]
createJail = cmdProperty cmd args
in
checkResult chk (\_ -> return MadeChange) createJail
`describe` unwords ["Create poudriere jail", name]
data Poudriere = Poudriere
{ _resolvConf :: String
, _freebsdHost :: String
, _baseFs :: String
, _usePortLint :: Bool
, _distFilesCache :: FilePath
, _svnHost :: String
, _zfs :: Maybe PoudriereZFS}
defaultConfig :: Poudriere
defaultConfig = Poudriere
"/etc/resolv.conf"
"ftp://ftp5.us.FreeBSD.org"
"/usr/local/poudriere"
True
"/usr/ports/distfiles"
"svn.freebsd.org"
Nothing
data PoudriereZFS = PoudriereZFS ZFS.ZFS ZFS.ZFSProperties
data Jail = Jail String FBSDVersion PoudriereArch
data PoudriereArch = I386 | AMD64 deriving (Eq)
instance Show PoudriereArch where
show I386 = "i386"
show AMD64 = "amd64"
instance IsString PoudriereArch where
fromString "i386" = I386
fromString "amd64" = AMD64
fromString _ = error "Not a valid Poudriere architecture."
yesNoProp :: Bool -> String
yesNoProp b = if b then "yes" else "no"
instance ToShellConfigLines Poudriere where
toAssoc c = map (\(k, f) -> (k, f c))
[("RESOLV_CONF", _resolvConf)
,("FREEBSD_HOST", _freebsdHost)
,("BASEFS", _baseFs)
,("USE_PORTLINT", yesNoProp . _usePortLint)
,("DISTFILES_CACHE", _distFilesCache)
,("SVN_HOST", _svnHost)] ++ maybe [("NO_ZFS", "yes")] toAssoc (_zfs c)
instance ToShellConfigLines PoudriereZFS where
toAssoc (PoudriereZFS (ZFS.ZFS (ZFS.ZPool pool) dataset) _) =
[("NO_ZFS", "no")
, ("ZPOOL", pool)
, ("ZROOTFS", show dataset)]
type ConfigLine = String
type ConfigFile = [ConfigLine]
class ToShellConfigLines a where
toAssoc :: a -> [(String, String)]
toLines :: a -> [ConfigLine]
toLines c = map (\(k, v) -> intercalate "=" [k, v]) $ toAssoc c
confFile :: FilePath
confFile = "/usr/local/etc/poudriere.conf"
|