@@ -66,6 +66,7 @@ import Control.Monad
66
66
import Data.Aeson (ToJSON (.. ), FromJSON (.. ), withText )
67
67
import qualified Data.Attoparsec.Text as AP
68
68
import Data.Hashable (Hashable , hashWithSalt , hashUsing )
69
+ import qualified Data.List as L
69
70
import Data.Monoid
70
71
import Data.String
71
72
import qualified Data.Text as T
@@ -182,9 +183,13 @@ data Region
182
183
| UsEast1
183
184
| UsWest1
184
185
| UsWest2
185
- deriving (Show , Read , Eq , Ord , Enum , Bounded , Typeable )
186
+ | CustomEndpoint ! T. Text ! Int
187
+ -- ^ To override the region settings with a custom service endpoint, e.g.
188
+ -- for testing purpose
189
+
190
+ deriving (Show , Read , Eq , Ord , Typeable )
186
191
187
- regionToText :: IsString a => Region -> a
192
+ regionToText :: ( Monoid a , IsString a ) => Region -> a
188
193
regionToText ApNortheast1 = " ap-northeast-1"
189
194
regionToText ApSoutheast1 = " ap-southeast-1"
190
195
regionToText ApSoutheast2 = " ap-southeast-2"
@@ -193,7 +198,22 @@ regionToText SaEast1 = "sa-east-1"
193
198
regionToText UsEast1 = " us-east-1"
194
199
regionToText UsWest1 = " us-west-1"
195
200
regionToText UsWest2 = " us-west-2"
201
+ regionToText (CustomEndpoint e p) = " custom:" <> fromString (T. unpack e) <> " :" <> fromString (show p)
196
202
203
+ -- | Regions are parsed as follows:
204
+ --
205
+ -- @
206
+ -- 'ApNortheast1' ::= "ap-northeast-1"
207
+ -- 'ApSoutheast1' ::= "ap-southeast-1"
208
+ -- 'ApSoutheast2' ::= "ap-southeast-2"
209
+ -- 'EuWest1' ::= "eu-west-1"
210
+ -- 'SaEast1' ::= "sa-east-1"
211
+ -- 'UsEast1' ::= "us-east-1"
212
+ -- 'UsWest1' ::= "us-west-1"
213
+ -- 'UsWest2' ::= "us-west-2"
214
+ -- 'CustomEndpoint' ::= "custom:" 'T.Text' ":" 'Int'
215
+ -- @
216
+ --
197
217
parseRegion :: P. CharParsing m => m Region
198
218
parseRegion =
199
219
ApNortheast1 <$ P. text " ap-northeast-1"
@@ -204,12 +224,30 @@ parseRegion =
204
224
<|> UsEast1 <$ P. text " us-east-1"
205
225
<|> UsWest1 <$ P. text " us-west-1"
206
226
<|> UsWest2 <$ P. text " us-west-2"
227
+ <|> parseCustomEndpoint
207
228
<?> " Region"
229
+ where
230
+ parseCustomEndpoint = CustomEndpoint
231
+ <$> (fmap T. pack $ P. text " custom:" *> many (P. notChar ' :' ))
232
+ <*> (fmap read $ P. text " :" *> some P. digit)
208
233
209
234
instance AwsType Region where
210
235
toText = regionToText
211
236
parse = parseRegion
212
237
238
+ standardRegions :: [Region ]
239
+ standardRegions =
240
+ [ ApNortheast1
241
+ , ApSoutheast1
242
+ , ApSoutheast2
243
+ , EuWest1
244
+ , SaEast1
245
+ , UsEast1
246
+ , UsWest1
247
+ , UsWest2
248
+ ]
249
+
250
+
213
251
{-
214
252
instance FromJSON Ec2Region where
215
253
parseJSON = withText "Ec2Region" $ either fail return ∘ readEither ∘ T.unpack
@@ -219,10 +257,20 @@ instance ToJSON Ec2Region where
219
257
-}
220
258
221
259
instance Hashable Region where
222
- hashWithSalt = hashUsing fromEnum
260
+ hashWithSalt s (CustomEndpoint e p) = s `hashWithSalt` (0 :: Int ) `hashWithSalt` (e, p)
261
+ hashWithSalt s r =
262
+ case L. elemIndex r standardRegions of
263
+ Just i -> hashWithSalt s (succ i)
264
+ Nothing -> hashWithSalt s (length standardRegions + 1 )
223
265
224
266
instance Q. Arbitrary Region where
225
- arbitrary = Q. elements [minBound .. maxBound ]
267
+ arbitrary = Q. oneof
268
+ [ Q. elements standardRegions
269
+ , CustomEndpoint <$> arbitraryEndpoint <*> arbitraryPort
270
+ ]
271
+ where
272
+ arbitraryEndpoint = fmap T. pack . Q. listOf . Q. elements $ ' .' : [' a' .. ' z' ]
273
+ arbitraryPort = Q. choose (0 , 10000 )
226
274
227
275
-- -------------------------------------------------------------------------- --
228
276
-- AWS Account Id
0 commit comments