Add a simple example to be run in integration tests
This commit is contained in:
4
examples/.gitignore
vendored
Normal file
4
examples/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
dist
|
||||||
|
dist-newstyle
|
||||||
|
*.cabal
|
||||||
|
.stack-work
|
||||||
1
examples/LICENSE
Symbolic link
1
examples/LICENSE
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../LICENSE
|
||||||
29
examples/package.yaml
Normal file
29
examples/package.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: kubernetes-examples
|
||||||
|
version: 0.1.0.1
|
||||||
|
description: |
|
||||||
|
Examples to interact with Kubernetes using kubernetes-client and kubernetes-client-core
|
||||||
|
synopsis: Kubernetes examples with Haskell
|
||||||
|
maintainer:
|
||||||
|
- Shimin Guo <smguo2001@gmail.com>
|
||||||
|
- Akshay Mankar <itsakshaymankar@gmail.com>
|
||||||
|
category: Examples, Kubernetes
|
||||||
|
license: Apache-2.0
|
||||||
|
license-file: LICENSE
|
||||||
|
|
||||||
|
executables:
|
||||||
|
simple:
|
||||||
|
main: Main.hs
|
||||||
|
source-dirs: simple
|
||||||
|
ghc-options:
|
||||||
|
- -Wall
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base
|
||||||
|
- containers
|
||||||
|
- http-client
|
||||||
|
- http-types
|
||||||
|
- kubernetes-client
|
||||||
|
- kubernetes-client-core
|
||||||
|
- safe-exceptions
|
||||||
|
- stm
|
||||||
|
- text
|
||||||
102
examples/simple/Main.hs
Normal file
102
examples/simple/Main.hs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
import Control.Exception.Safe
|
||||||
|
import Kubernetes.Client
|
||||||
|
import Kubernetes.OpenAPI
|
||||||
|
import Kubernetes.OpenAPI.API.AppsV1
|
||||||
|
import Kubernetes.OpenAPI.API.CoreV1
|
||||||
|
import Network.HTTP.Client
|
||||||
|
import Network.HTTP.Types.Status
|
||||||
|
import System.Environment
|
||||||
|
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.IO as T
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
kubeConfigFile <- getEnv "KUBECONFIG"
|
||||||
|
oidcCache <- newTVarIO $ Map.fromList []
|
||||||
|
(manager, cfg) <- mkKubeClientConfig oidcCache
|
||||||
|
$ KubeConfigFile kubeConfigFile
|
||||||
|
let createNamespaceRequest =
|
||||||
|
createNamespace (ContentType MimeJSON) (Accept MimeJSON) testNamespace
|
||||||
|
createdNS <- assertMimeSuccess =<< dispatchMime manager cfg createNamespaceRequest
|
||||||
|
nsName <- assertJust "Expected K8s to generate name for namespace, but it didn't"
|
||||||
|
$ (v1ObjectMetaName =<< v1NamespaceMetadata createdNS)
|
||||||
|
T.putStrLn $ "Created Namespace: " <> nsName
|
||||||
|
|
||||||
|
let createDeploymentRequest =
|
||||||
|
createNamespacedDeployment (ContentType MimeJSON) (Accept MimeJSON) testDeployment (Namespace nsName)
|
||||||
|
deployment <- assertMimeSuccess =<< dispatchMime manager cfg createDeploymentRequest
|
||||||
|
T.putStrLn $ "Created Deployment: " <> maybe "No name!?" id (v1DeploymentMetadata deployment >>= v1ObjectMetaName)
|
||||||
|
|
||||||
|
let listDeploymentsRequest =
|
||||||
|
listNamespacedDeployment (Accept MimeJSON) (Namespace nsName)
|
||||||
|
listedDeployments <- assertMimeSuccess =<< dispatchMime manager cfg listDeploymentsRequest
|
||||||
|
let numberOfDeployments = length $ v1DeploymentListItems listedDeployments
|
||||||
|
if numberOfDeployments /= 1
|
||||||
|
then throwM $ AssertionFailure $ "Expected 1 deployment, found: " <> show numberOfDeployments
|
||||||
|
else putStrLn "Test successful!"
|
||||||
|
|
||||||
|
-- NOTE: We cannot use dispatchMime due to this issue: https://github.com/kubernetes/kubernetes/issues/59501
|
||||||
|
let deleteNamespaceRequest =
|
||||||
|
deleteNamespace (ContentType MimeJSON) (Accept MimeJSON) (Name nsName)
|
||||||
|
deleteNamespaceResponse <- dispatchLbs manager cfg deleteNamespaceRequest
|
||||||
|
if responseStatus deleteNamespaceResponse /= status200
|
||||||
|
then throwM $ AssertionFailure
|
||||||
|
$ "Failed to cleanup namespace: " <> T.unpack nsName
|
||||||
|
<> "\nStatus Code: " <> show (responseStatus deleteNamespaceResponse)
|
||||||
|
<> "\nBody: " <> show (responseBody deleteNamespaceResponse)
|
||||||
|
else return ()
|
||||||
|
putStrLn "Clenaup complete!"
|
||||||
|
|
||||||
|
testDeployment :: V1Deployment
|
||||||
|
testDeployment =
|
||||||
|
let labelSelector =
|
||||||
|
mkV1LabelSelector
|
||||||
|
{ v1LabelSelectorMatchLabels =
|
||||||
|
Just $ Map.fromList [("app", "test")] }
|
||||||
|
container =
|
||||||
|
(mkV1Container "container-name")
|
||||||
|
{ v1ContainerImage = Just $ "nginx" }
|
||||||
|
podTemplate =
|
||||||
|
mkV1PodTemplateSpec
|
||||||
|
{ v1PodTemplateSpecMetadata =
|
||||||
|
Just $ mkV1ObjectMeta
|
||||||
|
{ v1ObjectMetaLabels = Just $ Map.fromList [("app", "test")] }
|
||||||
|
, v1PodTemplateSpecSpec =
|
||||||
|
Just $
|
||||||
|
mkV1PodSpec [container]
|
||||||
|
}
|
||||||
|
in mkV1Deployment
|
||||||
|
{ v1DeploymentMetadata =
|
||||||
|
Just $ mkV1ObjectMeta { v1ObjectMetaName = Just "test-deployment" }
|
||||||
|
, v1DeploymentSpec =
|
||||||
|
Just
|
||||||
|
$ (mkV1DeploymentSpec labelSelector podTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
testNamespace :: V1Namespace
|
||||||
|
testNamespace =
|
||||||
|
let nsMetadata =
|
||||||
|
mkV1ObjectMeta
|
||||||
|
{ v1ObjectMetaGenerateName = Just "haskell-client-test-" }
|
||||||
|
in mkV1Namespace
|
||||||
|
{ v1NamespaceMetadata = Just nsMetadata }
|
||||||
|
|
||||||
|
assertMimeSuccess :: MonadThrow m => MimeResult a -> m a
|
||||||
|
assertMimeSuccess (MimeResult (Right res) _) = pure res
|
||||||
|
assertMimeSuccess (MimeResult (Left err) _) =
|
||||||
|
throwM $ AssertionFailure $ "Unexpected MimeError: " ++ show err
|
||||||
|
|
||||||
|
assertJust :: MonadThrow m => String -> Maybe a -> m a
|
||||||
|
assertJust err Nothing = throwM $ AssertionFailure err
|
||||||
|
assertJust _ (Just x) = return x
|
||||||
|
|
||||||
|
data AssertionFailure = AssertionFailure String
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
instance Exception AssertionFailure
|
||||||
11
examples/stack.yaml
Normal file
11
examples/stack.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
resolver: lts-13.9
|
||||||
|
packages:
|
||||||
|
- .
|
||||||
|
- ../kubernetes-client
|
||||||
|
- ../kubernetes
|
||||||
|
extra-deps:
|
||||||
|
- jsonpath-0.1.0.1
|
||||||
|
- jwt-0.10.0
|
||||||
|
- katip-0.8.0.0
|
||||||
|
- oidc-client-0.4.0.0
|
||||||
|
- string-random-0.1.2.0
|
||||||
47
examples/stack.yaml.lock
Normal file
47
examples/stack.yaml.lock
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# This file was autogenerated by Stack.
|
||||||
|
# You should not edit this file by hand.
|
||||||
|
# For more information, please see the documentation at:
|
||||||
|
# https://docs.haskellstack.org/en/stable/lock_files
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- completed:
|
||||||
|
hackage: jsonpath-0.1.0.1@sha256:55718ac52b25cd8ce80fbdc9079a112344f032b056cfaf30737a29b6bd1a5c12,2377
|
||||||
|
pantry-tree:
|
||||||
|
size: 1097
|
||||||
|
sha256: 027749c943abaa6a78adc58e5abd4b3f42644c17c5fb7edf816557424a79448b
|
||||||
|
original:
|
||||||
|
hackage: jsonpath-0.1.0.1
|
||||||
|
- completed:
|
||||||
|
hackage: jwt-0.10.0@sha256:d14551b0c357424fb9441ec9a7a9d5b90b13f805fcc9327ba49db548cd64fc29,4180
|
||||||
|
pantry-tree:
|
||||||
|
size: 1027
|
||||||
|
sha256: e0cf95e834d99768ad8a3f7e99246948f0cdd2cfa18813517f540144aea6c3e5
|
||||||
|
original:
|
||||||
|
hackage: jwt-0.10.0
|
||||||
|
- completed:
|
||||||
|
hackage: katip-0.8.0.0@sha256:8a74858b692edfdbe83ac377b116111f81b4dcda774024615967d764f9f474b8,4097
|
||||||
|
pantry-tree:
|
||||||
|
size: 1140
|
||||||
|
sha256: f6baad9ee2edc7ed02d71bd8433872403500ebbdfaead9e4ef226dc47b3c4b97
|
||||||
|
original:
|
||||||
|
hackage: katip-0.8.0.0
|
||||||
|
- completed:
|
||||||
|
hackage: oidc-client-0.4.0.0@sha256:f72a496ab27d9a5071be44e750718c539118ac52c2f1535a5fb3dde7f9874a55,3306
|
||||||
|
pantry-tree:
|
||||||
|
size: 1153
|
||||||
|
sha256: 68c285c6365360975d50bbb18cb07755d5ef19af8bf0e998d3ea46d35ef4a4e1
|
||||||
|
original:
|
||||||
|
hackage: oidc-client-0.4.0.0
|
||||||
|
- completed:
|
||||||
|
hackage: string-random-0.1.2.0@sha256:db4f801dec1ec72cba7d662b9774da60ff54de6d05478e94478d6d730dc5034f,2439
|
||||||
|
pantry-tree:
|
||||||
|
size: 489
|
||||||
|
sha256: 21c7e61fceea98d14b453fc74c947b715ce33fe4c665c65b1f28c6f417d4ab7e
|
||||||
|
original:
|
||||||
|
hackage: string-random-0.1.2.0
|
||||||
|
snapshots:
|
||||||
|
- completed:
|
||||||
|
size: 496697
|
||||||
|
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/13/9.yaml
|
||||||
|
sha256: 3846ba7d13dd1b2679426dc3f450332a3b8a181063b0f3fc2d0c7d55db2e9c24
|
||||||
|
original: lts-13.9
|
||||||
Reference in New Issue
Block a user