From 73a5306136d80bf395b5f7fa32f5bc887db78cdd Mon Sep 17 00:00:00 2001 From: Markus Schirp Date: Thu, 4 Jan 2024 01:08:15 +0000 Subject: [PATCH] [stack-deploy] Fix maybe stack reads * Originally I thought AWS would return an empty result on a query for a stack that does not exist. * Instead it returns an error. * Unfortunately there is no exception free way (I know) to read a paginator from amazonka. --- stack-deploy/src/StackDeploy/Stack.hs | 33 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/stack-deploy/src/StackDeploy/Stack.hs b/stack-deploy/src/StackDeploy/Stack.hs index 19bfcba0..f084d898 100644 --- a/stack-deploy/src/StackDeploy/Stack.hs +++ b/stack-deploy/src/StackDeploy/Stack.hs @@ -14,7 +14,9 @@ import Control.Lens (Lens', set, view) import Data.Conduit ((.|)) import StackDeploy.Prelude import StackDeploy.Types +import UnliftIO.Exception (catchJust) +import qualified Amazonka import qualified Amazonka.CloudFormation.DescribeStacks as CF import qualified Amazonka.CloudFormation.Types as CF import qualified Data.Conduit as Conduit @@ -88,14 +90,35 @@ readCloudFormationStack :: forall env . AWS.Env env => StackDeploy.InstanceName -> MIO env (Maybe CF.Stack) -readCloudFormationStack name - = Conduit.runConduit - $ AWS.nestedResourceC describeSpecificStack (fromMaybe [] . (.stacks)) - .| Conduit.find ((convert name ==) . (.stackName)) +readCloudFormationStack instanceName = catchJust handleNotFoundError read pure where + read + = Conduit.runConduit + $ AWS.nestedResourceC describeSpecificStack (fromMaybe [] . (.stacks)) + .| Conduit.find ((instanceNameText ==) . (.stackName)) + + instanceNameText = convert instanceName + describeSpecificStack :: CF.DescribeStacks describeSpecificStack = - set CF.describeStacks_stackName (pure $ convert name) CF.newDescribeStacks + set CF.describeStacks_stackName (pure instanceNameText) CF.newDescribeStacks + + handleNotFoundError :: Amazonka.Error -> Maybe (Maybe CF.Stack) + handleNotFoundError + (Amazonka.ServiceError + Amazonka.ServiceError' + { code = Amazonka.ErrorCode "ValidationError" + , message = Just actualMessage + } + ) + = if actualMessage == expectedMessage + then pure empty + else empty + handleNotFoundError _error = empty + + expectedMessage :: Amazonka.ErrorMessage + expectedMessage = + Amazonka.ErrorMessage $ "Stack with id " <> toText instanceNameText <> " does not exist" readCloudFormationStackPresent :: forall env . AWS.Env env