packages feed

stratosphere 0.6.0 → 0.7.0

raw patch · 8 files changed

+119/−40 lines, 8 filesdep +hspecdep +hspec-discoverdep −tastydep −tasty-hspec

Dependencies added: hspec, hspec-discover

Dependencies removed: tasty, tasty-hspec

Files

CHANGELOG.md view
@@ -1,5 +1,16 @@ # Change Log +## 0.7.0++* Made `Val` and `ValList` more type-safe by moving some constructors to+  `ValList` and being more specific with types in functions that only accept+  `Text` parameters. Specific examples include:+  - `Join` and `Select` now require a `ValList` argument+  - `Base64` and `Join` now work only on `Val Text`, not `Val a`+  - `GetAZs` and `Split` are now in `ValList`, not `Val`+* Created `ImportValueList` as a `ValList` alternative to `ImportValue`.+* Added support for `Fn::Sub` intrinsic function.+ ## 0.6.0  * **BREAKING CHANGE**: Added `ValList` type. This new type allows you to
library/Stratosphere/ResourceAttributes/AutoScalingRollingUpdatePolicy.hs view
@@ -23,7 +23,7 @@   , _autoScalingRollingUpdatePolicyMinInstancesInService :: Maybe (Val Integer)   , _autoScalingRollingUpdatePolicyMinSuccessfulInstancesPercent :: Maybe (Val Integer)   , _autoScalingRollingUpdatePolicyPauseTime :: Maybe (Val Text)-  , _autoScalingRollingUpdatePolicySuspendProcess :: Maybe [Val Text]+  , _autoScalingRollingUpdatePolicySuspendProcess :: Maybe (ValList Text)   , _autoScalingRollingUpdatePolicyWaitOnResourceSignals :: Maybe (Val Bool)   } deriving (Show, Eq) @@ -110,7 +110,7 @@ -- execute scaling policies associated with an alarm. For valid values, see -- the ScalingProcesses.member.N parameter for the SuspendProcesses action in -- the Auto Scaling API Reference.-asrupSuspendProcess :: Lens' AutoScalingRollingUpdatePolicy (Maybe [Val Text])+asrupSuspendProcess :: Lens' AutoScalingRollingUpdatePolicy (Maybe (ValList Text)) asrupSuspendProcess = lens _autoScalingRollingUpdatePolicySuspendProcess (\s a -> s { _autoScalingRollingUpdatePolicySuspendProcess = a })  -- | Specifies whether the Auto Scaling group waits on signals from new
library/Stratosphere/Values.hs view
@@ -8,6 +8,7 @@  module Stratosphere.Values   ( Val (..)+  , sub   , ValList (..)   , Integer' (..)   , Bool' (..)@@ -16,6 +17,7 @@   ) where  import Data.Aeson+import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HM import Data.String (IsString (..)) import Data.Text (Text)@@ -42,13 +44,12 @@  | Equals (Val Bool) (Val Bool)  | Or (Val Bool) (Val Bool)  | GetAtt Text Text- | Base64 (Val a)- | Join Text [Val a]- | Split Text Text- | Select Integer (Val a)- | GetAZs (Val a)+ | Base64 (Val Text)+ | Join Text (ValList Text)+ | Select Integer (ValList a)  | FindInMap (Val a) (Val a) (Val a) -- ^ Map name, top level key, and second level key  | ImportValue Text -- ^ The account-and-region-unique exported name of the value to import+ | Sub Text (Maybe (HashMap Text (Val Text))) -- ^ Substitution string and optional map of values  deriving instance (Show a) => Show (Val a) deriving instance (Eq a) => Eq (Val a)@@ -67,16 +68,23 @@   toJSON (GetAtt x y) = mkFunc "Fn::GetAtt" [toJSON x, toJSON y]   toJSON (Base64 v) = object [("Fn::Base64", toJSON v)]   toJSON (Join d vs) = mkFunc "Fn::Join" [toJSON d, toJSON vs]-  toJSON (Split d s) = mkFunc "Fn::Split" [toJSON d, toJSON s]   toJSON (Select i vs) = mkFunc "Fn::Select" [toJSON (Integer' i), toJSON vs]-  toJSON (GetAZs r) = object [("Fn::GetAZs", toJSON r)]   toJSON (FindInMap mapName topKey secondKey) =     object [("Fn::FindInMap", toJSON [toJSON mapName, toJSON topKey, toJSON secondKey])]-  toJSON (ImportValue t) = object [("Fn::ImportValue", toJSON t)]+  toJSON (ImportValue t) = importValueToJSON t+  toJSON (Sub s Nothing) = object [("Fn::Sub", toJSON s)]+  toJSON (Sub s (Just vals)) = mkFunc "Fn::Sub" [toJSON s, Object (toJSON <$> vals)] +-- | Simple version of 'Sub' without a map of values.+sub :: Text -> Val Text+sub s = Sub s Nothing+ refToJSON :: Text -> Value refToJSON ref = object [("Ref", toJSON ref)] +importValueToJSON :: Text -> Value+importValueToJSON ref = object [("Fn::ImportValue", toJSON ref)]+ mkFunc :: Text -> [Value] -> Value mkFunc name args = object [(name, Array $ fromList args)] @@ -92,27 +100,33 @@       [("Fn::GetAtt", o')] -> uncurry GetAtt <$> parseJSON o'       [("Fn::Base64", o')] -> Base64 <$> parseJSON o'       [("Fn::Join", o')] -> uncurry Join <$> parseJSON o'-      [("Fn::Split", o')] -> uncurry Split <$> parseJSON o'       [("Fn::Select", o')] -> (\(x, y) -> Select (unInteger' x) y) <$> parseJSON o'-      [("Fn::GetAZs", o')] -> GetAZs <$> parseJSON o'       [("Fn::FindInMap", o')] -> do         (mapName, topKey, secondKey) <- parseJSON o'         return (FindInMap mapName topKey secondKey)       [("Fn::ImportValue", o')] -> ImportValue <$> parseJSON o'+      [("Fn::Sub", vals)] ->+        case vals of+          (String s) -> return $ Sub s Nothing+          otherwise' -> uncurry Sub <$> parseJSON otherwise'       [(n, o')] -> Literal <$> parseJSON (object [(n, o')])       os -> Literal <$> parseJSON (object os)   parseJSON v = Literal <$> parseJSON v --- | There are two ways to construct a list of 'Val's. One is to use a literal--- 'ValList' to construct the list. The other is to reference something that is--- already a list. For example, if you have a parameter called @SubnetIds@ of--- type @List<AWS::EC2::Subnet::Id>@ then, you can use @RefList "SubnetIds"@ to+-- | 'ValList' is like 'Val', except it is used in place of lists of Vals in+-- templates. For example, if you have a parameter called @SubnetIds@ of type+-- @List<AWS::EC2::Subnet::Id>@ then, you can use @RefList "SubnetIds"@ to -- reference it. data ValList a   = ValList [Val a]   | RefList Text+  | ImportValueList Text+  | Split Text Text+  | GetAZs (Val Text)   deriving (Show, Eq) +deriving instance Functor ValList+ instance IsList (ValList a) where   type Item (ValList a) = Val a   fromList = ValList@@ -121,16 +135,25 @@   -- This is obviously not meaningful, but the IsList instance is so useful   -- that I decided to allow it.   toList (RefList _) = []+  toList (ImportValueList _) = []+  toList (Split _ _) = []+  toList (GetAZs _) = []  instance (ToJSON a) => ToJSON (ValList a) where   toJSON (ValList vals) = toJSON vals   toJSON (RefList ref) = refToJSON ref+  toJSON (ImportValueList ref) = importValueToJSON ref+  toJSON (Split d s) = mkFunc "Fn::Split" [toJSON d, toJSON s]+  toJSON (GetAZs r) = object [("Fn::GetAZs", toJSON r)]  instance (FromJSON a) => FromJSON (ValList a) where   parseJSON a@(Array _) = ValList <$> parseJSON a   parseJSON (Object o) =     case HM.toList o of       [("Ref", o')] -> RefList <$> parseJSON o'+      [("Fn::ImportValue", o')] -> ImportValueList <$> parseJSON o'+      [("Fn::Split", o')] -> uncurry Split <$> parseJSON o'+      [("Fn::GetAZs", o')] -> GetAZs <$> parseJSON o'       _ -> fail "Could not parse object into RefList"   parseJSON _ = fail "Expected Array or Object for ValList in parseJSON" 
stratosphere.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack  name:           stratosphere-version:        0.6.0+version:        0.7.0 synopsis:       EDSL for AWS CloudFormation description:    EDSL for AWS CloudFormation category:       AWS, Cloud@@ -733,9 +733,9 @@     buildable: False   default-language: Haskell2010 -test-suite style+test-suite spec   type: exitcode-stdio-1.0-  main-is: HLint.hs+  main-is: Spec.hs   hs-source-dirs:       tests   build-depends:@@ -749,15 +749,17 @@     , text >= 1.1     , unordered-containers >= 0.2     , base-    , directory-    , hlint+    , stratosphere+    , hspec+    , hspec-discover   other-modules:-      Main+      HLint+      Stratosphere.ValuesSpec   default-language: Haskell2010 -test-suite tasty+test-suite style   type: exitcode-stdio-1.0-  main-is: Main.hs+  main-is: HLint.hs   hs-source-dirs:       tests   build-depends:@@ -771,9 +773,9 @@     , text >= 1.1     , unordered-containers >= 0.2     , base-    , stratosphere-    , tasty-    , tasty-hspec+    , directory+    , hlint   other-modules:-      HLint+      Spec+      Stratosphere.ValuesSpec   default-language: Haskell2010
tests/HLint.hs view
@@ -10,6 +10,7 @@   , "tests"   , "-i", "Use newtype instead of data"   , "-i", "Unused LANGUAGE pragma"+  , "-i", "Redundant do"   ]  main :: IO ()
− tests/Main.hs
@@ -1,12 +0,0 @@-import qualified Test.Tasty-import Test.Tasty.Hspec--main :: IO ()-main = do-    test <- testSpec "stratosphere" spec-    Test.Tasty.defaultMain test--spec :: Spec-spec = parallel $-    it "is trivially true" $-        True `shouldBe` True
+ tests/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ tests/Stratosphere/ValuesSpec.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}++module Stratosphere.ValuesSpec+  ( spec+  ) where++import Data.Aeson+import Data.Text (Text)+import Test.Hspec++import Stratosphere.Values++spec :: Spec+spec = do+  describe "Val/ValList JSON instances" $ do+    it "is idempotent for Sub" $ do+      idempotentJSON (sub "MyString")+      idempotentJSON (Sub "${Greeting} ${Name}" (Just []) :: Val Text)+      let+        values =+          [ ("Greeting", "Hello")+          , ("Name", "Bob")+          ]+      idempotentJSON (Sub "${Greeting} ${Name}" (Just values) :: Val Text)++    it "Ref and RefList produce the same JSON" $ do+      toJSON (Ref "MyVal" :: Val Text) `shouldBe` toJSON (RefList "MyVal" :: ValList Text)++    it "ImportValue and ImportValueList produce the same JSON" $ do+      toJSON (ImportValue "MyVal" :: Val Text) `shouldBe` toJSON (ImportValueList "MyVal" :: ValList Text)++    it "Functor conversions in nested Vals work" $ do+      let+        input :: Val Integer+        input =+          Select 1 $+            ValList+            [ Literal 1+            , Ref "Hello"+            , Literal 2+            ]+        expected =+          Select 1 $+            ValList+            [ Literal 2+            , Ref "Hello"+            , Literal 3+            ]+      fmap (+1) input `shouldBe` expected++idempotentJSON :: (ToJSON a, FromJSON a, Show a, Eq a) => a -> Expectation+idempotentJSON x = decode (encode x) `shouldBe` Just x