sandwich-contexts-kubernetes-0.1.0.0: lib/Test/Sandwich/Contexts/Kubernetes/MinioS3Server/Parsing.hs
module Test.Sandwich.Contexts.Kubernetes.MinioS3Server.Parsing (
parseMinioUserAndPassword
, transformKustomizeChunks
) where
import Control.Lens
import Data.Aeson (FromJSON)
import qualified Data.Aeson as A
import Data.Aeson.Lens
import qualified Data.Map as M
import Data.String.Interpolate
import Data.Text as T
import qualified Data.Yaml as Yaml
import Kubernetes.OpenAPI.Model as Kubernetes
import Relude
import Safe (headMay)
import Test.Sandwich.Contexts.Kubernetes.Util.Aeson
import Text.Regex.TDFA
parseMinioUserAndPassword :: Text -> Maybe (Text, Text)
parseMinioUserAndPassword txt = case (userValues, passwordValues) of
(Just (_before, _fullMatch, _after, [user]), Just (_, _, _, [password])) -> Just (user, toText password)
_ -> Nothing
where
userValues :: Maybe (Text, Text, Text, [Text]) = txt =~~ ([i|MINIO_ROOT_USER="([^"]*)"|] :: Text)
passwordValues :: Maybe (Text, Text, Text, [Text]) = txt =~~ ([i|MINIO_ROOT_PASSWORD="([^"]*)"|] :: Text)
-- testInput :: Text
-- testInput = [__i|export MINIO_ROOT_USER="WXSTFUWIRS04LMGIMJGV"
-- export MINIO_ROOT_PASSWORD="NCDCfTaiXcGHq8QRfSaXMAWOXgdrhpGwPSkoYMWf"|]
transformKustomizeChunks :: String -> String -> [Text] -> Either String ((Text, Text), Text)
transformKustomizeChunks namespace deploymentName initialChunks = do
userAndPassword <- getUserAndPassword initialChunks
return (userAndPassword, finalYaml)
where
finalYaml = initialChunks
-- Don't include a kind: Namespace
& Relude.filter (not . isNamespace)
-- Set metadata.namespace on all values
& fmap (setMetaNamespace namespace)
-- Disable TLS
& fmap disableTLS
-- Set deployment name
& fmap (setDeploymentNameAndPoolSize deploymentName)
-- Combine everything into multi-document Yaml
& T.intercalate "---\n"
getUserAndPassword :: [Text] -> Either String (Text, Text)
getUserAndPassword chunks = case headMay (mapMaybe getUserAndPassword' chunks) of
Nothing -> Left "Couldn't find user/password YAML."
Just x -> Right x
where
getUserAndPassword' :: Text -> Maybe (Text, Text)
getUserAndPassword' (decode -> Right (V1Secret {v1SecretMetadata=(Just (V1ObjectMeta {v1ObjectMetaName=(Just "storage-configuration")}))
, v1SecretStringData=(Just (M.lookup "config.env" -> Just t))
}))
= parseMinioUserAndPassword t
getUserAndPassword' _ = Nothing
isNamespace :: Text -> Bool
isNamespace (decode -> Right (A.Object (aesonLookup "kind" -> Just (A.String "Namespace")))) = True
isNamespace _ = False
setMetaNamespace :: String -> Text -> Text
setMetaNamespace namespace (decode -> Right (A.Object obj1@(aesonLookup "metadata" -> Just (A.Object obj2@(aesonLookup "namespace" -> Just (A.String _)))))) =
decodeUtf8 (Yaml.encode obj1')
where
obj1' :: A.Value
obj1' = A.Object (aesonInsert "metadata" obj2' obj1)
obj2' :: A.Value
obj2' = A.Object (aesonInsert "namespace" (A.String (toText namespace)) obj2)
setMetaNamespace _ t = t
-- Do the steps to disable TLS in the tenant CRD.
-- See https://min.io/docs/minio/kubernetes/upstream/reference/operator-crd.html#tenantspec
disableTLS :: Text -> Text
disableTLS (decode -> Right x@(A.Object (aesonLookup "kind" -> Just (A.String "Tenant")))) = decodeUtf8 (Yaml.encode x')
where
x' = x
& set (_Object . ix "spec" . _Object . ix "requestAutoCert") (A.Bool False)
& set (_Object . ix "spec" . _Object . at "externalCertSecret") Nothing
disableTLS t = t
setDeploymentNameAndPoolSize :: String -> Text -> Text
setDeploymentNameAndPoolSize deploymentName (decode -> Right x@(A.Object (aesonLookup "kind" -> Just (A.String "Tenant")))) = decodeUtf8 (Yaml.encode x')
where
x' = x
& set (_Object . ix "metadata" . _Object . ix "name") (A.String (toText deploymentName))
& set (_Object . ix "spec" . _Object . ix "pools" . _Array . ix 0 . _Object . ix "servers") (A.Number 1)
setDeploymentNameAndPoolSize _ t = t
decode :: FromJSON a => Text -> Either Yaml.ParseException a
decode = Yaml.decodeEither' . encodeUtf8