cloud-seeder-0.0.0.0: test-suite/Network/CloudSeeder/MainSpec.hs
module Network.CloudSeeder.MainSpec (spec) where
import Control.Lens (review)
import Control.Monad.Except (ExceptT, runExceptT)
import Data.Function ((&))
import Data.Functor.Identity (runIdentity)
import Test.Hspec
import Network.CloudSeeder.DSL
import Network.CloudSeeder.Interfaces
import Network.CloudSeeder.Main
import Network.CloudSeeder.Test.Stubs
spec :: Spec
spec = parallel $ do
describe "cli" $ do
let stubExceptT :: ExceptT CliError m a -> m (Either CliError a)
stubExceptT = runExceptT
runSuccess x = runIdentity x `shouldBe` Right ()
runFailure p y x = runIdentity x `shouldBe` Left (review p y)
it "fails if the template doesn't exist" $ do
let config = runIdentity $ deployment "foo" $ do
stack_ "base"
stack_ "server"
env = [("Env", "test")]
runFailure _FileNotFound "server.yaml" $ cli (DeployStack "server") config
& stubFileSystemT []
& stubExceptT
& stubEnvironmentT env
& stubCloudT []
it "fails if user attempts to deploy a stack that doesn't exist in the config" $ do
let config = runIdentity $ deployment "foo" $ do
stack_ "base"
env = [("Env", "test")]
runFailure _CliStackNotConfigured "foo" $ cli (DeployStack "foo") config
& stubFileSystemT
[ ("base.yaml", "base.yaml contents")]
& stubExceptT
& stubEnvironmentT env
& stubCloudT []
context "the configuration does not have environment variables" $ do
let config = runIdentity $ deployment "foo" $ do
stack_ "base"
stack_ "server"
stack_ "frontend"
env = [("Env", "test")]
it "applies a changeset to a stack" $ example $ do
runSuccess $ cli (DeployStack "base") config
& stubFileSystemT
[ ("base.yaml", "base.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ ComputeChangeset "test-foo-base" "base.yaml contents" env :-> "csid"
, RunChangeSet "csid" :-> () ]
it "passes the outputs from prior stacks" $ do
runSuccess $ cli (DeployStack "server") config
& stubFileSystemT
[ ("server.yaml", "server.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ DescribeStack "test-foo-base" :-> Just [("foo", "bar")]
, ComputeChangeset "test-foo-server" "server.yaml contents" (env ++ [("foo", "bar")]) :-> "csid"
, RunChangeSet "csid" :-> () ]
runSuccess $ cli (DeployStack "frontend") config
& stubFileSystemT
[ ("frontend.yaml", "frontend.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ DescribeStack "test-foo-base" :-> Just [("foo", "bar")]
, DescribeStack "test-foo-server" :-> Just [("baz", "qux")]
, ComputeChangeset "test-foo-frontend" "frontend.yaml contents" (env ++ [("foo", "bar"), ("baz", "qux")]) :-> "csid"
, RunChangeSet "csid" :-> () ]
it "fails if a dependency stack does not exist" $ do
runFailure _CliMissingDependencyStacks ["base"] $ cli (DeployStack "frontend") config
& stubFileSystemT
[ ("frontend.yaml", "frontend.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ DescribeStack "test-foo-base" :-> Nothing
, DescribeStack "test-foo-server" :-> Just [] ]
runFailure _CliMissingDependencyStacks ["server"] $ cli (DeployStack "frontend") config
& stubFileSystemT
[ ("frontend.yaml", "frontend.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ DescribeStack "test-foo-base" :-> Just []
, DescribeStack "test-foo-server" :-> Nothing ]
runFailure _CliMissingDependencyStacks ["base", "server"] $ cli (DeployStack "frontend") config
& stubFileSystemT
[ ("frontend.yaml", "frontend.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ DescribeStack "test-foo-base" :-> Nothing
, DescribeStack "test-foo-server" :-> Nothing ]
it "fails when the Env environment variable is not specified" $ do
runFailure _CliMissingEnvVars ["Env"] $ cli (DeployStack "server") config
& stubFileSystemT
[ ("server.yaml", "server.yaml contents") ]
& stubExceptT
& stubEnvironmentT []
& stubCloudT []
context "the configuration has global environment variables" $ do
let config = runIdentity $ deployment "foo" $ do
environment ["Domain", "SecretsStore"]
stack_ "base"
stack_ "server"
stack_ "frontend"
it "passes the value in each global environment variable as a parameter" $ do
let env = [ ("Env", "test"), ("Domain", "example.com"), ("SecretsStore", "arn::aws:1234") ]
runSuccess $ cli (DeployStack "base") config
& stubFileSystemT
[ ("base.yaml", "base.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT
[ ComputeChangeset "test-foo-base" "base.yaml contents" env :-> "csid"
, RunChangeSet "csid" :-> () ]
it "fails when a global environment variable is missing" $ do
let env = [ ("Env", "test"), ("SecretsStore", "arn::aws:1234") ]
runFailure _CliMissingEnvVars ["Domain"] $ cli (DeployStack "base") config
& stubFileSystemT
[ ("base.yaml", "base.yaml contents") ]
& stubExceptT
& stubEnvironmentT env
& stubCloudT []
it "reports all missing environment variables at once in alphabetical order" $ do
runFailure _CliMissingEnvVars ["Domain", "Env", "SecretsStore"] $ cli (DeployStack "base") config
& stubFileSystemT
[ ("base.yaml", "base.yaml contents") ]
& stubExceptT
& stubEnvironmentT []
& stubCloudT []
context "the configuration has global and local environment variables" $ do
let config = runIdentity $ deployment "foo" $ do
environment ["Domain", "SecretsStore"]
stack "base" $ environment ["Base"]
stack "server" $ environment ["Server1", "Server2"]
stack "frontend" $ environment ["Frontend"]
it "passes the value in each local environment variable to the proper stack" $ do
let env = [ ("Env", "test"), ("Domain", "example.com"), ("SecretsStore", "arn::aws:1234") ]
baseEnv = env ++ [ ("Base", "a") ]
runSuccess $ cli (DeployStack "base") config
& stubFileSystemT
[ ("base.yaml", "base.yaml contents") ]
& stubExceptT
& stubEnvironmentT baseEnv
& stubCloudT
[ ComputeChangeset "test-foo-base" "base.yaml contents" baseEnv :-> "csid"
, RunChangeSet "csid" :-> () ]
let serverEnv = env ++ [ ("Server1", "b"), ("Server2", "c") ]
runSuccess $ cli (DeployStack "server") config
& stubFileSystemT
[ ("server.yaml", "server.yaml contents") ]
& stubExceptT
& stubEnvironmentT serverEnv
& stubCloudT
[ DescribeStack "test-foo-base" :-> Just []
, ComputeChangeset "test-foo-server" "server.yaml contents" serverEnv :-> "csid"
, RunChangeSet "csid" :-> () ]