{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-}
module Test.Sandwich.Contexts.Kubernetes.KataContainers (
introduceKataContainers
, withKataContainers
, withKataContainers'
, KataContainersOptions(..)
, SourceCheckout(..)
, defaultKataContainersOptions
, kataContainers
, KataContainersContext(..)
, HasKataContainersContext
) where
import Control.Lens
import Control.Monad
import Control.Monad.IO.Unlift
import Data.Aeson (FromJSON)
import Data.String.Interpolate
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.Yaml as Yaml
import Kubernetes.OpenAPI.Model as Kubernetes
import Kubernetes.OpenAPI.ModelLens as Kubernetes
import Relude hiding (withFile)
import Safe
import System.Exit
import System.FilePath
import Test.Sandwich
import Test.Sandwich.Contexts.Files
import Test.Sandwich.Contexts.Kubernetes.FindImages
import Test.Sandwich.Contexts.Kubernetes.Images
import Test.Sandwich.Contexts.Kubernetes.Kubectl
import Test.Sandwich.Contexts.Kubernetes.Types
import Test.Sandwich.Contexts.Nix
import Test.Sandwich.Waits
import UnliftIO.Process
data KataContainersContext = KataContainersContext {
KataContainersContext -> KataContainersOptions
kataContainersOptions :: KataContainersOptions
} deriving (Int -> KataContainersContext -> ShowS
[KataContainersContext] -> ShowS
KataContainersContext -> String
(Int -> KataContainersContext -> ShowS)
-> (KataContainersContext -> String)
-> ([KataContainersContext] -> ShowS)
-> Show KataContainersContext
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> KataContainersContext -> ShowS
showsPrec :: Int -> KataContainersContext -> ShowS
$cshow :: KataContainersContext -> String
show :: KataContainersContext -> String
$cshowList :: [KataContainersContext] -> ShowS
showList :: [KataContainersContext] -> ShowS
Show)
data SourceCheckout =
SourceCheckoutFilePath FilePath
| SourceCheckoutNixDerivation Text
deriving (Int -> SourceCheckout -> ShowS
[SourceCheckout] -> ShowS
SourceCheckout -> String
(Int -> SourceCheckout -> ShowS)
-> (SourceCheckout -> String)
-> ([SourceCheckout] -> ShowS)
-> Show SourceCheckout
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SourceCheckout -> ShowS
showsPrec :: Int -> SourceCheckout -> ShowS
$cshow :: SourceCheckout -> String
show :: SourceCheckout -> String
$cshowList :: [SourceCheckout] -> ShowS
showList :: [SourceCheckout] -> ShowS
Show, SourceCheckout -> SourceCheckout -> Bool
(SourceCheckout -> SourceCheckout -> Bool)
-> (SourceCheckout -> SourceCheckout -> Bool) -> Eq SourceCheckout
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SourceCheckout -> SourceCheckout -> Bool
== :: SourceCheckout -> SourceCheckout -> Bool
$c/= :: SourceCheckout -> SourceCheckout -> Bool
/= :: SourceCheckout -> SourceCheckout -> Bool
Eq)
data KataContainersOptions = KataContainersOptions {
:: SourceCheckout
, KataContainersOptions -> Maybe Text
kataContainersKataDeployImage :: Maybe Text
, KataContainersOptions -> Bool
kataContainersPreloadImages :: Bool
, KataContainersOptions -> Bool
kataContainersLabelNode :: Bool
} deriving (Int -> KataContainersOptions -> ShowS
[KataContainersOptions] -> ShowS
KataContainersOptions -> String
(Int -> KataContainersOptions -> ShowS)
-> (KataContainersOptions -> String)
-> ([KataContainersOptions] -> ShowS)
-> Show KataContainersOptions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> KataContainersOptions -> ShowS
showsPrec :: Int -> KataContainersOptions -> ShowS
$cshow :: KataContainersOptions -> String
show :: KataContainersOptions -> String
$cshowList :: [KataContainersOptions] -> ShowS
showList :: [KataContainersOptions] -> ShowS
Show)
defaultKataContainersOptions :: KataContainersOptions
defaultKataContainersOptions :: KataContainersOptions
defaultKataContainersOptions = KataContainersOptions {
kataContainersSourceCheckout :: SourceCheckout
kataContainersSourceCheckout = Text -> SourceCheckout
SourceCheckoutNixDerivation Text
kataContainersDerivation
, kataContainersKataDeployImage :: Maybe Text
kataContainersKataDeployImage = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
kataContainersDeployImage
, kataContainersPreloadImages :: Bool
kataContainersPreloadImages = Bool
True
, kataContainersLabelNode :: Bool
kataContainersLabelNode = Bool
True
}
kataContainers :: Label "kataContainers" KataContainersContext
kataContainers :: Label "kataContainers" KataContainersContext
kataContainers = Label "kataContainers" KataContainersContext
forall {k} (l :: Symbol) (a :: k). Label l a
Label
type HasKataContainersContext context = HasLabel context "kataContainers" KataContainersContext
type ContextWithKataContainers context =
LabelValue "kataContainers" KataContainersContext
:> LabelValue "file-kubectl" (EnvironmentFile "kubectl")
:> context
introduceKataContainers :: (
Typeable context, KubernetesClusterBasicWithoutReader context m, HasNixContext context
)
=> KataContainersOptions
-> SpecFree (ContextWithKataContainers context) m ()
-> SpecFree context m ()
introduceKataContainers :: forall context (m :: * -> *).
(Typeable context, KubernetesClusterBasicWithoutReader context m,
HasNixContext context) =>
KataContainersOptions
-> SpecFree (ContextWithKataContainers context) m ()
-> SpecFree context m ()
introduceKataContainers KataContainersOptions
options = forall (a :: Symbol) context (m :: * -> *).
(HasBaseContext context, HasNixContext context, MonadUnliftIO m,
KnownSymbol a) =>
Text
-> SpecFree
(LabelValue (AppendSymbol "file-" a) (EnvironmentFile a)
:> context)
m
()
-> SpecFree context m ()
introduceBinaryViaNixPackage @"kubectl" Text
"kubectl" (Free
(SpecCommand
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m)
()
-> Free (SpecCommand context m) ())
-> (SpecFree (ContextWithKataContainers context) m ()
-> Free
(SpecCommand
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m)
())
-> SpecFree (ContextWithKataContainers context) m ()
-> Free (SpecCommand context m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String
-> Label "kataContainers" KataContainersContext
-> ((HasCallStack =>
KataContainersContext
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result])
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
())
-> SpecFree (ContextWithKataContainers context) m ()
-> Free
(SpecCommand
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m)
()
forall (l :: Symbol) intro context (m :: * -> *).
HasCallStack =>
String
-> Label l intro
-> ((HasCallStack => intro -> ExampleT context m [Result])
-> ExampleT context m ())
-> SpecFree (LabelValue l intro :> context) m ()
-> SpecFree context m ()
introduceWith String
"introduce KataContainers" Label "kataContainers" KataContainersContext
kataContainers (ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result]
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result]
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
())
-> ((KataContainersContext
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result])
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result])
-> (KataContainersContext
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result])
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KataContainersOptions
-> (KataContainersContext
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result])
-> ExampleT
(LabelValue "file-kubectl" (EnvironmentFile "kubectl") :> context)
m
[Result]
forall context (m :: * -> *) a.
(HasCallStack, Typeable context, MonadFail m,
KubectlBasic context m) =>
KataContainersOptions -> (KataContainersContext -> m a) -> m a
withKataContainers KataContainersOptions
options)
withKataContainers :: forall context m a. (
HasCallStack, Typeable context, MonadFail m, KubectlBasic context m
)
=> KataContainersOptions
-> (KataContainersContext -> m a)
-> m a
withKataContainers :: forall context (m :: * -> *) a.
(HasCallStack, Typeable context, MonadFail m,
KubectlBasic context m) =>
KataContainersOptions -> (KataContainersContext -> m a) -> m a
withKataContainers KataContainersOptions
options KataContainersContext -> m a
action = do
kcc <- Label "kubernetesCluster" KubernetesClusterContext
-> m KubernetesClusterContext
forall context (l :: Symbol) a (m :: * -> *).
(HasLabel context l a, MonadReader context m) =>
Label l a -> m a
getContext Label "kubernetesCluster" KubernetesClusterContext
kubernetesCluster
kubectlBinary <- askFile @"kubectl"
withKataContainers' kcc kubectlBinary options action
withKataContainers' :: forall context m a. (
HasCallStack, Typeable context, MonadFail m, KubernetesBasic context m
)
=> KubernetesClusterContext
-> FilePath
-> KataContainersOptions
-> (KataContainersContext -> m a)
-> m a
withKataContainers' :: forall context (m :: * -> *) a.
(HasCallStack, Typeable context, MonadFail m,
KubernetesBasic context m) =>
KubernetesClusterContext
-> String
-> KataContainersOptions
-> (KataContainersContext -> m a)
-> m a
withKataContainers' kcc :: KubernetesClusterContext
kcc@(KubernetesClusterContext {Int
String
(Manager, KubernetesClientConfig)
Text
KubernetesClusterType
kubernetesClusterName :: Text
kubernetesClusterKubeConfigPath :: String
kubernetesClusterNumNodes :: Int
kubernetesClusterClientConfig :: (Manager, KubernetesClientConfig)
kubernetesClusterType :: KubernetesClusterType
kubernetesClusterType :: KubernetesClusterContext -> KubernetesClusterType
kubernetesClusterClientConfig :: KubernetesClusterContext -> (Manager, KubernetesClientConfig)
kubernetesClusterNumNodes :: KubernetesClusterContext -> Int
kubernetesClusterKubeConfigPath :: KubernetesClusterContext -> String
kubernetesClusterName :: KubernetesClusterContext -> Text
..}) String
kubectlBinary options :: KataContainersOptions
options@(KataContainersOptions {Bool
Maybe Text
SourceCheckout
kataContainersSourceCheckout :: KataContainersOptions -> SourceCheckout
kataContainersKataDeployImage :: KataContainersOptions -> Maybe Text
kataContainersPreloadImages :: KataContainersOptions -> Bool
kataContainersLabelNode :: KataContainersOptions -> Bool
kataContainersSourceCheckout :: SourceCheckout
kataContainersKataDeployImage :: Maybe Text
kataContainersPreloadImages :: Bool
kataContainersLabelNode :: Bool
..}) KataContainersContext -> m a
action = do
case KubernetesClusterType
kubernetesClusterType of
KubernetesClusterKind {} -> String -> m ()
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Can't install Kata Containers on Kind at present.|]
KubernetesClusterMinikube {String
[Text]
Text
kubernetesClusterTypeMinikubeBinary :: String
kubernetesClusterTypeMinikubeProfileName :: Text
kubernetesClusterTypeMinikubeFlags :: [Text]
kubernetesClusterTypeMinikubeFlags :: KubernetesClusterType -> [Text]
kubernetesClusterTypeMinikubeProfileName :: KubernetesClusterType -> Text
kubernetesClusterTypeMinikubeBinary :: KubernetesClusterType -> String
..} -> do
output <- CreateProcess -> String -> m String
forall (m :: * -> *).
(HasCallStack, MonadUnliftIO m, MonadLogger m) =>
CreateProcess -> String -> m String
readCreateProcessWithLogging (String -> [String] -> CreateProcess
proc String
kubernetesClusterTypeMinikubeBinary [
String
"--profile", Text -> String
forall a. ToString a => a -> String
toString Text
kubernetesClusterTypeMinikubeProfileName
, String
"ssh", [i|egrep -c 'vmx|svm' /proc/cpuinfo|]
]) String
""
case readMay output of
Just (Int
0 :: Int) -> String -> m ()
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Preflight check: didn't find "vmx" or "svm" in /proc/cpuinfo. Please make sure virtualization support is enabled.|]
Just Int
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe Int
Nothing -> String -> m ()
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Preflight check: couldn't parse output of minikube ssh "egrep -c 'vmx|svm' /proc/cpuinfo"|]
kataRoot <- case SourceCheckout
kataContainersSourceCheckout of
SourceCheckoutFilePath String
x -> String -> m String
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
x
SourceCheckoutNixDerivation Text
d -> Label "nixContext" NixContext -> m (Maybe NixContext)
forall context (m :: * -> *) (l :: Symbol) a.
(MonadReader context m, KnownSymbol l, Typeable context,
Typeable a) =>
Label l a -> m (Maybe a)
getContextMaybe Label "nixContext" NixContext
nixContext m (Maybe NixContext) -> (Maybe NixContext -> m String) -> m String
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe NixContext
Nothing -> String -> m String
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Wanted to build Kata Containers source checkout via derivation, but no Nix context was provided.|]
Just NixContext
nc -> NixContext -> Text -> m String
forall context (m :: * -> *).
(HasBaseContextMonad context m, MonadUnliftIO m, MonadLogger m) =>
NixContext -> Text -> m String
buildNixCallPackageDerivation' NixContext
nc Text
d
info [i|kataRoot: #{kataRoot}|]
env <- getKubectlEnvironment kcc
rbacContents <- liftIO $ T.readFile $ kataRoot </> "tools/packaging/kata-deploy/kata-rbac/base/kata-rbac.yaml"
deploymentContents' <- liftIO $ T.readFile $ kataRoot </> "tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml"
let deploymentContents = case Maybe Text
kataContainersKataDeployImage of
Maybe Text
Nothing -> Text
deploymentContents'
Just Text
deployImage -> Text
deploymentContents'
Text -> (Text -> Text) -> Text
forall a b. a -> (a -> b) -> b
& Text -> Text -> Text
setDaemonSetImage Text
deployImage
when kataContainersPreloadImages $ do
let images = Text -> [Text]
findAllImages (Text
rbacContents Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n---\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
deploymentContents)
forM_ images $ \Text
image -> do
Text -> m ()
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
info [i|Preloading image: #{image}|]
KubernetesClusterContext -> ImageLoadSpec -> m ()
forall (m :: * -> *) context.
(HasCallStack, MonadFail m, KubernetesBasic context m) =>
KubernetesClusterContext -> ImageLoadSpec -> m ()
loadImageIfNecessary' KubernetesClusterContext
kcc (Text -> ImagePullPolicy -> ImageLoadSpec
ImageLoadSpecDocker Text
image ImagePullPolicy
IfNotPresent)
debug [i|Applying kata-rbac.yaml|]
createProcessWithLoggingAndStdin ((proc kubectlBinary ["apply", "-f", "-"]) { env = Just env }) (toString rbacContents)
>>= waitForProcess >>= (`shouldBe` ExitSuccess)
debug [i|Applying kata-deploy.yaml|]
createProcessWithLoggingAndStdin ((proc kubectlBinary ["apply", "-f", "-"]) { env = Just env }) (toString deploymentContents)
>>= waitForProcess >>= (`shouldBe` ExitSuccess)
debug [i|Waiting for kata-deploy pod to exist|]
podName <- waitUntil 600 $ do
pods <- (T.words . toText) <$> readCreateProcessWithLogging ((
(proc kubectlBinary ["-n", "kube-system"
, "get", "pods", "-o=name"]) { env = Just env }
) { env = Just env }) ""
case headMay [t | t <- pods, "pod/kata-deploy" `T.isPrefixOf` t] of
Just Text
x -> Text -> m Text
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
x
Maybe Text
Nothing -> String -> m Text
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Couldn't find kata-deploy pod in: #{pods}|]
info [i|Got podName: #{podName}|]
waitUntil 600 $ do
(exitCode, sout, serr) <- readCreateProcessWithExitCode (
(proc kubectlBinary ["-n", "kube-system"
, "exec", toString podName
, "--"
, "ps", "-ef"
])
{ env = Just env }
) ""
case exitCode of
ExitCode
ExitSuccess -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ExitFailure Int
n -> String -> m ()
forall (m :: * -> *) a. (HasCallStack, MonadIO m) => String -> m a
expectationFailure [i|Command failed with code #{n}. Stderr: #{serr}|]
toText sout `textShouldContain` "sleep infinity"
debug [i|Applying kata-runtimeClasses.yaml|]
runtimeClassesContents <- liftIO $ T.readFile $ kataRoot </> "tools/packaging/kata-deploy/runtimeclasses/kata-runtimeClasses.yaml"
createProcessWithLoggingAndStdin ((proc kubectlBinary ["apply", "-f", "-"]) { env = Just env }) (toString runtimeClassesContents)
>>= waitForProcess >>= (`shouldBe` ExitSuccess)
debug [i|Labeling nodes with katacontainers.io/kata-runtime=true|]
when kataContainersLabelNode $ do
createProcessWithLoggingAndStdin ((proc kubectlBinary ["label", "nodes", "--all", "--overwrite", "katacontainers.io/kata-runtime=true"]) { env = Just env }) (toString deploymentContents)
>>= waitForProcess >>= (`shouldBe` ExitSuccess)
action $ KataContainersContext options
kataContainersDeployImage :: Text
kataContainersDeployImage :: Text
kataContainersDeployImage = Text
"quay.io/kata-containers/kata-deploy:3.19.1"
kataContainersDerivation :: Text
kataContainersDerivation :: Text
kataContainersDerivation = [__i|{fetchFromGitHub}:
fetchFromGitHub {
owner = "kata-containers";
repo = "kata-containers";
rev = "acae4480ac84701d7354e679714cc9d084b37f44";
sha256 = "sha256-h9Jsto2l1NhQEwIQoecT/D+yt/QbGoqqH/l6NNzJOwk=";
}
|]
setDaemonSetImage :: Text -> Text -> Text
setDaemonSetImage :: Text -> Text -> Text
setDaemonSetImage Text
image = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Text
setDaemonSetImage' ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
"---\n"
where
setDaemonSetImage' :: Text -> Text
setDaemonSetImage' :: Text -> Text
setDaemonSetImage' (Text -> Either ParseException V1DaemonSet
forall a. FromJSON a => Text -> Either ParseException a
decode -> Right x :: V1DaemonSet
x@(V1DaemonSet {v1DaemonSetKind :: V1DaemonSet -> Maybe Text
v1DaemonSetKind=(Just Text
"DaemonSet")})) = V1DaemonSet
x
V1DaemonSet -> (V1DaemonSet -> V1DaemonSet) -> V1DaemonSet
forall a b. a -> (a -> b) -> b
& ASetter V1DaemonSet V1DaemonSet (Maybe Text) (Maybe Text)
-> Maybe Text -> V1DaemonSet -> V1DaemonSet
forall s t a b. ASetter s t a b -> b -> s -> t
set ((Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> V1DaemonSet -> Identity V1DaemonSet
Lens_' V1DaemonSet (Maybe V1DaemonSetSpec)
v1DaemonSetSpecL ((Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> V1DaemonSet -> Identity V1DaemonSet)
-> ((Maybe Text -> Identity (Maybe Text))
-> Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> ASetter V1DaemonSet V1DaemonSet (Maybe Text) (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec)
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just ((V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> ((Maybe Text -> Identity (Maybe Text))
-> V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> (Maybe Text -> Identity (Maybe Text))
-> Maybe V1DaemonSetSpec
-> Identity (Maybe V1DaemonSetSpec)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> V1DaemonSetSpec -> Identity V1DaemonSetSpec
Lens_' V1DaemonSetSpec V1PodTemplateSpec
v1DaemonSetSpecTemplateL ((V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> ((Maybe Text -> Identity (Maybe Text))
-> V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> (Maybe Text -> Identity (Maybe Text))
-> V1DaemonSetSpec
-> Identity V1DaemonSetSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> V1PodTemplateSpec -> Identity V1PodTemplateSpec
Lens_' V1PodTemplateSpec (Maybe V1PodSpec)
v1PodTemplateSpecSpecL ((Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> ((Maybe Text -> Identity (Maybe Text))
-> Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> (Maybe Text -> Identity (Maybe Text))
-> V1PodTemplateSpec
-> Identity V1PodTemplateSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (V1PodSpec -> Identity V1PodSpec)
-> Maybe V1PodSpec -> Identity (Maybe V1PodSpec)
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just ((V1PodSpec -> Identity V1PodSpec)
-> Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> ((Maybe Text -> Identity (Maybe Text))
-> V1PodSpec -> Identity V1PodSpec)
-> (Maybe Text -> Identity (Maybe Text))
-> Maybe V1PodSpec
-> Identity (Maybe V1PodSpec)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([V1Container] -> Identity [V1Container])
-> V1PodSpec -> Identity V1PodSpec
Lens_' V1PodSpec [V1Container]
v1PodSpecContainersL (([V1Container] -> Identity [V1Container])
-> V1PodSpec -> Identity V1PodSpec)
-> ((Maybe Text -> Identity (Maybe Text))
-> [V1Container] -> Identity [V1Container])
-> (Maybe Text -> Identity (Maybe Text))
-> V1PodSpec
-> Identity V1PodSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index [V1Container]
-> Traversal' [V1Container] (IxValue [V1Container])
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Int
Index [V1Container]
0 ((V1Container -> Identity V1Container)
-> [V1Container] -> Identity [V1Container])
-> ((Maybe Text -> Identity (Maybe Text))
-> V1Container -> Identity V1Container)
-> (Maybe Text -> Identity (Maybe Text))
-> [V1Container]
-> Identity [V1Container]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text -> Identity (Maybe Text))
-> V1Container -> Identity V1Container
Lens_' V1Container (Maybe Text)
v1ContainerImageL) (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
image)
V1DaemonSet -> (V1DaemonSet -> V1DaemonSet) -> V1DaemonSet
forall a b. a -> (a -> b) -> b
& ASetter V1DaemonSet V1DaemonSet (Maybe Text) (Maybe Text)
-> Maybe Text -> V1DaemonSet -> V1DaemonSet
forall s t a b. ASetter s t a b -> b -> s -> t
set ((Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> V1DaemonSet -> Identity V1DaemonSet
Lens_' V1DaemonSet (Maybe V1DaemonSetSpec)
v1DaemonSetSpecL ((Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> V1DaemonSet -> Identity V1DaemonSet)
-> ((Maybe Text -> Identity (Maybe Text))
-> Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> ASetter V1DaemonSet V1DaemonSet (Maybe Text) (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec)
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just ((V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> Maybe V1DaemonSetSpec -> Identity (Maybe V1DaemonSetSpec))
-> ((Maybe Text -> Identity (Maybe Text))
-> V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> (Maybe Text -> Identity (Maybe Text))
-> Maybe V1DaemonSetSpec
-> Identity (Maybe V1DaemonSetSpec)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> V1DaemonSetSpec -> Identity V1DaemonSetSpec
Lens_' V1DaemonSetSpec V1PodTemplateSpec
v1DaemonSetSpecTemplateL ((V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> V1DaemonSetSpec -> Identity V1DaemonSetSpec)
-> ((Maybe Text -> Identity (Maybe Text))
-> V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> (Maybe Text -> Identity (Maybe Text))
-> V1DaemonSetSpec
-> Identity V1DaemonSetSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> V1PodTemplateSpec -> Identity V1PodTemplateSpec
Lens_' V1PodTemplateSpec (Maybe V1PodSpec)
v1PodTemplateSpecSpecL ((Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> V1PodTemplateSpec -> Identity V1PodTemplateSpec)
-> ((Maybe Text -> Identity (Maybe Text))
-> Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> (Maybe Text -> Identity (Maybe Text))
-> V1PodTemplateSpec
-> Identity V1PodTemplateSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (V1PodSpec -> Identity V1PodSpec)
-> Maybe V1PodSpec -> Identity (Maybe V1PodSpec)
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just ((V1PodSpec -> Identity V1PodSpec)
-> Maybe V1PodSpec -> Identity (Maybe V1PodSpec))
-> ((Maybe Text -> Identity (Maybe Text))
-> V1PodSpec -> Identity V1PodSpec)
-> (Maybe Text -> Identity (Maybe Text))
-> Maybe V1PodSpec
-> Identity (Maybe V1PodSpec)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([V1Container] -> Identity [V1Container])
-> V1PodSpec -> Identity V1PodSpec
Lens_' V1PodSpec [V1Container]
v1PodSpecContainersL (([V1Container] -> Identity [V1Container])
-> V1PodSpec -> Identity V1PodSpec)
-> ((Maybe Text -> Identity (Maybe Text))
-> [V1Container] -> Identity [V1Container])
-> (Maybe Text -> Identity (Maybe Text))
-> V1PodSpec
-> Identity V1PodSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index [V1Container]
-> Traversal' [V1Container] (IxValue [V1Container])
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Int
Index [V1Container]
0 ((V1Container -> Identity V1Container)
-> [V1Container] -> Identity [V1Container])
-> ((Maybe Text -> Identity (Maybe Text))
-> V1Container -> Identity V1Container)
-> (Maybe Text -> Identity (Maybe Text))
-> [V1Container]
-> Identity [V1Container]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text -> Identity (Maybe Text))
-> V1Container -> Identity V1Container
Lens_' V1Container (Maybe Text)
v1ContainerImagePullPolicyL) (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"IfNotPresent")
V1DaemonSet -> (V1DaemonSet -> ByteString) -> ByteString
forall a b. a -> (a -> b) -> b
& V1DaemonSet -> ByteString
forall a. ToJSON a => a -> ByteString
Yaml.encode
ByteString -> (ByteString -> Text) -> Text
forall a b. a -> (a -> b) -> b
& ByteString -> Text
forall a b. ConvertUtf8 a b => b -> a
decodeUtf8
setDaemonSetImage' Text
t = Text
t
decode :: FromJSON a => Text -> Either Yaml.ParseException a
decode :: forall a. FromJSON a => Text -> Either ParseException a
decode = ByteString -> Either ParseException a
forall a. FromJSON a => ByteString -> Either ParseException a
Yaml.decodeEither' (ByteString -> Either ParseException a)
-> (Text -> ByteString) -> Text -> Either ParseException a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8