hadolint-2.8.0: src/Hadolint/Config/Configuration.hs
module Hadolint.Config.Configuration
( Configuration (..),
PartialConfiguration (..),
applyPartialConfiguration,
)
where
import Data.Maybe (fromMaybe)
import Control.Applicative
import Data.Coerce (coerce)
import Data.Default
import Data.Text (Text)
import Data.YAML ((.:?), (.!=))
import GHC.Generics (Generic)
import Hadolint.Formatter.Format (OutputFormat (..))
import Hadolint.Rule (RuleCode (..), DLSeverity (..), LabelSchema)
import Language.Docker
import Prettyprinter
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.YAML as Yaml
data Configuration =
Configuration
{ noFail :: Bool,
noColor :: Bool,
verbose :: Bool,
format :: OutputFormat,
errorRules :: [RuleCode],
warningRules :: [RuleCode],
infoRules :: [RuleCode],
styleRules :: [RuleCode],
ignoreRules :: [RuleCode],
allowedRegistries :: Set.Set Registry,
labelSchema :: LabelSchema,
strictLabels :: Bool,
failureThreshold :: DLSeverity
}
deriving (Eq, Show)
instance Default Configuration where
def =
Configuration
False
False
False
def
mempty
mempty
mempty
mempty
mempty
mempty
mempty
False
def
applyPartialConfiguration ::
Configuration -> PartialConfiguration -> Configuration
applyPartialConfiguration config partial =
Configuration
(fromMaybe (noFail config) (partialNoFail partial))
(fromMaybe (noColor config) (partialNoColor partial))
(fromMaybe (verbose config) (partialVerbose partial))
(fromMaybe (format config) (partialFormat partial))
(errorRules config <> partialErrorRules partial)
(warningRules config <> partialWarningRules partial)
(infoRules config <> partialInfoRules partial)
(styleRules config <> partialStyleRules partial)
(ignoreRules config <> partialIgnoreRules partial)
(allowedRegistries config <> partialAllowedRegistries partial)
(labelSchema config <> partialLabelSchema partial)
(fromMaybe (strictLabels config) (partialStrictLabels partial))
(fromMaybe (failureThreshold config) (partialFailureThreshold partial))
instance Pretty Configuration where
pretty c =
nest 2
( vsep
[ "Configuration:",
"no fail:" <+> pretty (noFail c),
"no color:" <+> pretty (noColor c),
"output format:" <+> pretty (format c),
"failure threshold:" <+> pretty (failureThreshold c),
prettyPrintRulelist "error" (errorRules c),
prettyPrintRulelist "warning" (warningRules c),
prettyPrintRulelist "info" (infoRules c),
prettyPrintRulelist "style" (styleRules c),
prettyPrintRulelist "ignore" (ignoreRules c),
"strict labels:" <+> pretty (strictLabels c),
prettyPrintLabelSchema (labelSchema c),
prettyPrintRegistries (allowedRegistries c)
]
)
prettyPrintRulelist :: String -> [RuleCode] -> Doc ann
prettyPrintRulelist name lst =
nest 2 (("override" <+> pretty name <> ":\n") <> prettyPrintList pretty lst)
-- | This function needs to convert the set to a list because Doc ann is not
-- ordered.
prettyPrintRegistries :: Set.Set Registry -> Doc ann
prettyPrintRegistries regs =
nest 2 ( "allowed registries:\n"
<> prettyPrintList
(\r -> "-" <+> pretty (unRegistry r))
(Set.toList regs)
)
prettyPrintLabelSchema :: LabelSchema -> Doc ann
prettyPrintLabelSchema ls =
nest 2 ( "label schema:\n"
<> prettyPrintList
(\(n, t) -> pretty n <> ":" <+> pretty t)
(Map.toList ls)
)
-- | pretty print a list with a custom pretty printing function for each element
prettyPrintList :: (a -> Doc ann) -> [a] -> Doc ann
prettyPrintList _ [] = "none"
prettyPrintList prnt lst = vsep (fmap (\i -> "-" <+> prnt i) lst)
data PartialConfiguration =
PartialConfiguration
{ partialNoFail :: Maybe Bool,
partialNoColor :: Maybe Bool,
partialVerbose :: Maybe Bool,
partialFormat :: Maybe OutputFormat,
partialErrorRules :: [RuleCode],
partialWarningRules :: [RuleCode],
partialInfoRules :: [RuleCode],
partialStyleRules :: [RuleCode],
partialIgnoreRules :: [RuleCode],
partialAllowedRegistries :: Set.Set Registry,
partialLabelSchema :: LabelSchema,
partialStrictLabels :: Maybe Bool,
partialFailureThreshold :: Maybe DLSeverity
}
deriving (Eq, Show)
instance Semigroup PartialConfiguration where
PartialConfiguration a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13
<> PartialConfiguration b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 =
PartialConfiguration
(b1 <|> a1)
(b2 <|> a2)
(b3 <|> a3)
(a4 <> b4)
(a5 <> b5)
(a6 <> b6)
(a7 <> b7)
(a8 <> b8)
(a9 <> b9)
(a10 <> b10)
(a11 <> b11)
(b12 <|> a12)
(a13 <> b13)
instance Monoid PartialConfiguration where
mempty =
PartialConfiguration
Nothing
Nothing
Nothing
mempty
mempty
mempty
mempty
mempty
mempty
mempty
mempty
Nothing
mempty
instance Default PartialConfiguration where
def = mempty
instance Yaml.FromYAML PartialConfiguration where
parseYAML = Yaml.withMap "Configuration" $ \m -> do
partialNoFail <- m .:? "no-fail" .!= Nothing
partialNoColor <- m .:? "no-color" .!= Nothing
partialVerbose <- m .:? "verbose" .!= Nothing
partialFormat <- m .:? "output-format"
override <- m .:? "override" .!= mempty
ignored <- m .:? "ignored" .!= mempty
trusted <- m .:? "trusted-registries" .!= mempty
partialLabelSchema <- m .:? "label-schema" .!= mempty
partialStrictLabels <- m .:? "strict-labels" .!= Nothing
let partialIgnoreRules = coerce (ignored :: [Text])
partialErrorRules = overrideErrorRules override
partialWarningRules = overrideWarningRules override
partialInfoRules = overrideInfoRules override
partialStyleRules = overrideStyleRules override
partialAllowedRegistries = Set.fromList (coerce (trusted :: [Text]))
partialFailureThreshold <- m .:? "failure-threshold"
return PartialConfiguration {..}
data OverrideConfig = OverrideConfig
{ overrideErrorRules :: [RuleCode],
overrideWarningRules :: [RuleCode],
overrideInfoRules :: [RuleCode],
overrideStyleRules :: [RuleCode]
}
deriving (Show, Eq, Generic)
instance Semigroup OverrideConfig where
OverrideConfig a1 a2 a3 a4 <> OverrideConfig b1 b2 b3 b4 =
OverrideConfig (a1 <> b1) (a2 <> b2) (a3 <> b3) (a4 <> b4)
instance Monoid OverrideConfig where
mempty = OverrideConfig mempty mempty mempty mempty
instance Yaml.FromYAML OverrideConfig where
parseYAML = Yaml.withMap "OverrideConfig" $ \m -> do
err <- m .:? "error" .!= mempty
wrn <- m .:? "warning" .!= mempty
inf <- m .:? "info" .!= mempty
sty <- m .:? "style" .!= mempty
let overrideErrorRules = coerce (err :: [Text])
overrideWarningRules = coerce (wrn :: [Text])
overrideInfoRules = coerce (inf :: [Text])
overrideStyleRules = coerce (sty:: [Text])
return OverrideConfig {..}