packages feed

stratosphere-1.0.0: src/Stratosphere/Parameter.hs

-- | See:
-- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
--
-- You can use the optional Parameters section to pass values into your
-- template when you create a stack. With parameters, you can create templates
-- that are customized each time you create a stack. Each parameter must
-- contain a value when you create a stack. You can specify a default value to
-- make the parameter optional. For more information about creating stacks, see
-- Working with Stacks.

module Stratosphere.Parameter where

import GHC.Exts (IsList(..))
import Stratosphere.NamedItem
import Stratosphere.Prelude
import Stratosphere.Property
import Stratosphere.Value

import qualified Data.Aeson as JSON

data Parameter =
  Parameter
  { name :: Text
  , type' :: Text
    -- ^ The data type for the parameter.
  , default' :: Maybe JSON.Value
    -- ^ A value of the appropriate type for the template to use if no value is
    -- specified when a stack is created. If you define constraints for the
    -- parameter, you must specify a value that adheres to those constraints.
  , noEcho :: Maybe Bool
    -- ^ Whether to mask the parameter value whenever anyone makes a call that
    -- describes the stack. If you set the value to true, the parameter value
    -- is masked with asterisks (*****).
  , allowedValues :: Maybe JSON.Array
    -- ^ An array containing the list of values allowed for the parameter.
  , allowedPattern :: Maybe Text
    -- ^ A regular expression that represents the patterns you want to allow
    -- for String types.
  , maxLength :: Maybe Integer
    -- ^ An integer value that determines the largest number of characters you
    -- want to allow for String types.
  , minLength :: Maybe Integer
    -- ^ An integer value that determines the smallest number of characters you
    -- want to allow for String types.
  , maxValue :: Maybe Integer
    -- ^ A numeric value that determines the largest numeric value you want to
    -- allow for Number types.
  , minValue :: Maybe Integer
    -- ^ A numeric value that determines the smallest numeric value you want to
    -- allow for Number types.
  , description :: Maybe Text
    -- ^ A string of up to 4000 characters that describes the parameter.
  , constraintDescription :: Maybe Text
    -- ^ A string that explains the constraint when the constraint is violated.
  } deriving (Show, Eq)

instance Property "Name" Parameter where
  type PropertyType "Name" Parameter = Text
  set newValue Parameter{..} = Parameter{name = newValue, ..}

instance Property "Type" Parameter where
  type PropertyType "Type" Parameter = Text
  set newValue Parameter{..} = Parameter{type' = newValue, ..}

instance Property "Default" Parameter where
  type PropertyType "Default" Parameter = JSON.Value
  set newValue Parameter{..} = Parameter{default' = pure newValue, ..}

instance Property "NoEcho" Parameter where
  type PropertyType "NoEcho" Parameter = Bool
  set newValue Parameter{..} = Parameter{noEcho = pure newValue, ..}

instance Property "AllowedValues" Parameter where
  type PropertyType "AllowedValues" Parameter = JSON.Array
  set newValue Parameter{..} = Parameter{allowedValues = pure newValue, ..}

instance Property "AllowedPattern" Parameter where
  type PropertyType "AllowedPattern" Parameter = Text
  set newValue Parameter{..} = Parameter{allowedPattern = pure newValue, ..}

instance Property "MaxLength" Parameter where
  type PropertyType "MaxLength" Parameter = Integer
  set newValue Parameter{..} = Parameter{maxLength = pure newValue, ..}

instance Property "MinLength" Parameter where
  type PropertyType "MinLength" Parameter = Integer
  set newValue Parameter{..} = Parameter{minLength = pure newValue, ..}

instance Property "MaxValue" Parameter where
  type PropertyType "MaxValue" Parameter = Integer
  set newValue Parameter{..} = Parameter{maxValue = pure newValue, ..}

instance Property "MinValue" Parameter where
  type PropertyType "MinValue" Parameter = Integer
  set newValue Parameter{..} = Parameter{minValue = pure newValue, ..}

instance Property "Description" Parameter where
  type PropertyType "Description" Parameter = Text
  set newValue Parameter{..} = Parameter{description = pure newValue, ..}

instance Property "ConstraintDescription" Parameter where
  type PropertyType "ConstraintDescription" Parameter = Text
  set newValue Parameter{..} = Parameter{constraintDescription = pure newValue, ..}

instance ToRef Parameter b where
  toRef Parameter{..} = Ref name

parameterToJSON :: Parameter -> JSON.Value
parameterToJSON Parameter{..}
  = JSON.object $ catMaybes
  [ Just ("Type" .= type')
  , maybeField "AllowedPattern"        allowedPattern
  , maybeField "AllowedValues"         allowedValues
  , maybeField "ConstraintDescription" constraintDescription
  , maybeField "Default"               default'
  , maybeField "Description"           description
  , maybeField "MaxLength"             maxLength
  , maybeField "MaxValue"              maxValue
  , maybeField "MinLength"             minLength
  , maybeField "MinValue"              minValue
  , maybeField "NoEcho"                noEcho
  ]

-- | Constructor for 'Parameter' with required arguments.
mkParameter
  :: Text -- ^ Name
  -> Text -- ^ Type
  -> Parameter
mkParameter name type' =
  Parameter
  { allowedPattern        = Nothing
  , allowedValues         = Nothing
  , constraintDescription = Nothing
  , default'              = Nothing
  , description           = Nothing
  , maxLength             = Nothing
  , maxValue              = Nothing
  , minValue              = Nothing
  , minLength             = Nothing
  , noEcho                = Nothing
  , ..
  }

-- | Wrapper around a list of 'Parameters's to we can modify the aeson
-- instances.
newtype Parameters = Parameters { parameterList :: [Parameter] }
  deriving stock (Show, Eq)
  deriving newtype (Monoid, MonoFunctor, Semigroup)

type instance Element Parameters = Parameter

instance IsList Parameters where
  type Item Parameters = Parameter
  fromList = Parameters
  toList = (.parameterList)

instance NamedItem Parameter where
  itemName = (.name)
  nameToJSON = parameterToJSON

instance JSON.ToJSON Parameters where
  toJSON = namedItemToJSON . (.parameterList)