module Propellor.Property.Apt.PPA where
import Data.List
import Control.Applicative
import Prelude
import Data.String (IsString(..))
import Propellor.Base
import qualified Propellor.Property.Apt as Apt
import Utility.Split
installed :: Property DebianLike
installed = Apt.installed ["software-properties-common"]
data PPA = PPA
{ ppaAccount :: String
, ppaArchive :: String
} deriving (Eq, Ord)
instance ConfigurableValue PPA where
val p = concat ["ppa:", ppaAccount p, "/", ppaArchive p]
instance IsString PPA where
fromString s =
let
[_, ppa] = split "ppa:" s
[acct, arch] = split "/" ppa
in
PPA acct arch
addPpa :: PPA -> Property DebianLike
addPpa p =
cmdPropertyEnv "apt-add-repository" ["--yes", val p] Apt.noninteractiveEnv
`assume` MadeChange
`describe` ("Added PPA " ++ (val p))
`requires` installed
data AptKeyId = AptKeyId
{ akiName :: String
, akiId :: String
, akiServer :: String
} deriving (Eq, Ord)
addKeyId :: AptKeyId -> Property DebianLike
addKeyId keyId =
check keyTrusted akcmd
`describe` (unwords ["Add third-party Apt key", desc keyId])
where
akcmd =
tightenTargets $ cmdProperty "apt-key" ["adv", "--keyserver", akiServer keyId, "--recv-keys", akiId keyId]
keyTrusted =
let
pks ls = concatMap (drop 1 . split "/")
$ concatMap (take 1 . drop 1 . words)
$ filter (\l -> "pub" `isPrefixOf` l)
$ lines ls
nkid = take 8 (akiId keyId)
in
(isInfixOf [nkid] . pks) <$> readProcess "apt-key" ["list"]
desc k = unwords ["Apt Key", akiName k, akiId k, "from", akiServer k]
data AptSource = AptSource
{ asURL :: Apt.Url
, asSuite :: String
, asComponents :: [String]
} deriving (Eq, Ord)
instance ConfigurableValue AptSource where
val asrc = unwords ["deb", asURL asrc, asSuite asrc, unwords . asComponents $ asrc]
instance IsString AptSource where
fromString s =
let
url:suite:comps = drop 1 . words $ s
in
AptSource url suite comps
data AptRepository = AptRepositoryPPA PPA | AptRepositorySource AptSource
addRepository :: AptRepository -> Property DebianLike
addRepository (AptRepositoryPPA p) = addPpa p
addRepository (AptRepositorySource src) =
check repoExists addSrc
`describe` unwords ["Adding APT repository", val src]
`requires` installed
where
allSourceLines =
readProcess "/bin/sh" ["-c", "cat /etc/apt/sources.list /etc/apt/sources.list.d/*"]
activeSources = map (\s -> fromString s :: AptSource )
. filter (not . isPrefixOf "#")
. filter (/= "") . lines <$> allSourceLines
repoExists = isInfixOf [src] <$> activeSources
addSrc = cmdProperty "apt-add-source" [val src]