git.iko.soy/typeable/pagerduty
on develop help sign in
36 files changed+1315−1031
since splitsnapshots
unifiedsplit
.gitignore+1 .travis.yml+30 Makefile−20 README.md+14 pagerduty.cabal+41−29 script/travis-lifecycle-before_install+11 script/travis-lifecycle-install+13 script/travis-lifecycle-script+9 script/travis-timeout+15 src/Control/Monad/Trans/PagerDuty.hs+55−72 src/Network/PagerDuty/IO.hs−66 src/Network/PagerDuty/Integration.hs+190−150 src/Network/PagerDuty/Internal/IO.hs+76 src/Network/PagerDuty/Options.hs → src/Network/PagerDuty/Internal/Options.hs+6−6 src/Network/PagerDuty/Query.hs → src/Network/PagerDuty/Internal/Query.hs+21−19 src/Network/PagerDuty/TH.hs → src/Network/PagerDuty/Internal/TH.hs+9−9 src/Network/PagerDuty/Internal/Types.hs+497 src/Network/PagerDuty/REST.hs+42−30 src/Network/PagerDuty/REST/Alerts.hs+7−7 src/Network/PagerDuty/REST/EscalationPolicies.hs+14−14 src/Network/PagerDuty/REST/EscalationPolicies/EscalationRules.hs+11−11 src/Network/PagerDuty/REST/Incidents.hs+23−27 src/Network/PagerDuty/REST/Incidents/Notes.hs+12−12 src/Network/PagerDuty/REST/LogEntries.hs+8−9 src/Network/PagerDuty/REST/MaintenanceWindows.hs+10−10 src/Network/PagerDuty/REST/Reports.hs+11−11 src/Network/PagerDuty/REST/Schedules.hs+14−14 src/Network/PagerDuty/REST/Schedules/Overrides.hs+12−12 src/Network/PagerDuty/REST/Services.hs+16−16 src/Network/PagerDuty/REST/Services/EmailFilters.hs+14−14 src/Network/PagerDuty/REST/Users.hs+17−17 src/Network/PagerDuty/REST/Users/ContactMethods.hs+10−10 src/Network/PagerDuty/REST/Users/NotificationRules.hs+10−10 src/Network/PagerDuty/REST/Webhooks.hs+5−4 src/Network/PagerDuty/Types.hs+84−432 stack.yaml+7
.gitignore+1
@@ -9,6 +9,7 @@
99cabal.sandbox.config
1010
1111# Dirs
12+.stack-work
1213cabal-dev
1314bin
1415dist
.travis.ymlnew file+30
@@ -0,0 +1,30 @@
1+sudo: false
2+
3+cache:
4+ apt: true
5+ directories:
6+ - ~/.stack
7+
8+branches:
9+ only:
10+ - master
11+ - develop
12+
13+before_install:
14+ - export PATH=/opt/ghc/$GHCVER/bin:$PATH
15+ - export PATH=~/.local/bin:$PATH
16+ - ./script/travis-lifecycle-before_install
17+
18+install:
19+ - ./script/travis-lifecycle-install
20+
21+script:
22+ - ./script/travis-lifecycle-script
23+
24+matrix:
25+ fast_finish: true
26+ include:
27+ - env: GHCVER=8.0.1
28+ addons: { apt: { packages: [ghc-8.0.1], sources: [hvr-ghc] } }
29+ - env: GHCVER=7.10.3
30+ addons: { apt: { packages: [ghc-7.10.3], sources: [hvr-ghc] } }
Makefiledeleted−20
@@ -1,20 +0,0 @@
1−FLAGS := -j --disable-documentation --disable-library-coverage
2−
3−build:
4− cabal build $(addprefix -,$(findstring j,$(MAKEFLAGS)))
5−
6−all:
7− make clean; make install && make build
8−
9−install: cabal.sandbox.config
10− cabal install $(FLAGS) --only-dependencies
11−
12−clean:
13− cabal clean
14− rm -rf cabal.sandbox.config .cabal-sandbox
15−
16−doc:
17− cabal haddock
18−
19−cabal.sandbox.config:
20− cabal sandbox init
README.md+14
@@ -0,0 +1,14 @@
1+# PagerDuty
2+
3+[![Build Status](https://travis-ci.org/brendanhay/amazonka.svg?branch=develop)](https://travis-ci.org/brendanhay/pagerduty)
4+
5+* [Contribute](#contribute)
6+* [Licence](#licence)
7+
8+## Contribute
9+
10+For any problems, comments, or feedback please create an issue [here on GitHub](https://github.com/brendanhay/pagerduty/issues).
11+
12+## Licence
13+
14+PagerDuty is released under the [Mozilla Public License Version 2.0](http://www.mozilla.org/MPL/).
pagerduty.cabal+41−29
@@ -1,21 +1,32 @@
11name: pagerduty
2−version: 0.1.0
3−synopsis: Pager Duty API Client
2+version: 0.0.8
3+synopsis: Client library for PagerDuty Integration and REST APIs.
44homepage: http://github.com/brendanhay/pagerduty
55license: OtherLicense
66license-file: LICENSE
7−author: Brendan Hay, Kim Altintop
8−maintainer: Brendan Hay <brendan.g.hay@gmail.com>, Kim Altintop <kim.altintop@gmail.com>
9−copyright: Copyright (c) 2013-2014 Brendan Hay, 2014 Kim Altintop
10−category: Network, Monitoring
7+author: Brendan Hay
8+maintainer: Brendan Hay <brendan.g.hay@gmail.com>
9+copyright: Copyright (c) 2013-2015 Brendan Hay, 2014 Kim Altintop
10+category: Network, PagerDuty, Monitoring
1111build-type: Simple
1212cabal-version: >= 1.10
1313
1414description:
15− Client library for the the PagerDuty REST APIs documented here:
15+ PagerDuty is an alerting system for IT professionals. PagerDuty connects
16+ with a variety of systems (including monitoring tools and ticketing
17+ systems) and dispatches alerts via automated phone call, SMS and email.
18+
19+ This library implements the full PagerDuty Integration and REST APIs which
20+ are documented here:
1621 .
1722 * Integration API - <http://developer.pagerduty.com/documentation/integration>
23+ .
1824 * REST API - <http://developer.pagerduty.com/documentation/rest>
25+ .
26+ /Warning:/ This is an experimental preview release which is still under
27+ heavy development and not intended for public consumption, caveat emptor!
28+ .
29+ /Note:/ An alternative source for Haddock documentation can be found <http://brendanhay.nz/pagerduty here>.
1930
2031extra-source-files:
2132 README.md
@@ -52,34 +63,35 @@ library
5263 , Network.PagerDuty.REST.Webhooks
5364
5465 other-modules:
55− Network.PagerDuty.IO
56− , Network.PagerDuty.Options
57− , Network.PagerDuty.Query
58− , Network.PagerDuty.TH
66+ Network.PagerDuty.Internal.IO
67+ , Network.PagerDuty.Internal.Options
68+ , Network.PagerDuty.Internal.Query
69+ , Network.PagerDuty.Internal.TH
70+ , Network.PagerDuty.Internal.Types
5971 , Network.PagerDuty.Types
6072
6173 build-depends:
62− aeson > 0.7 && <= 0.8
63− , base >= 4.5 && < 5.0
64− , bifunctors
74+ aeson >= 2.0
75+ , base >= 4.7 && < 5
76+ , bifunctors >= 4.1
6577 , bytestring >= 0.9
6678 , bytestring-conversion >= 0.2.1
67− , conduit >= 0.5.5
68− , data-default-class
79+ , conduit > 1.1
80+ , data-default-class >= 0.0.1
6981 , exceptions >= 0.6
70− , http-client >= 0.3.6
82+ , generics-sop >= 0.5.0.0
83+ , http-client >= 0.5 && < 1
7184 , http-types >= 0.8
72− , lens >= 4.0
73− , lens-aeson >= 1.0
74− , mmorph >= 1.0
75− , mtl >= 2.2.1
76− , old-locale
85+ , lens >= 4.4
86+ , lens-aeson >= 1
87+ , mmorph >= 1
88+ , monad-control >= 1
89+ , mtl >= 2.1.3.1
90+ , template-haskell >= 2.2
7791 , text >= 1.1
78− , time == 1.4.*
79− , transformers >= 0.4.1
92+ , time >= 1.2
93+ , time-locale-compat >= 0.1.0.1
94+ , transformers >= 0.2
95+ , transformers-compat >= 0.3
96+ , transformers-base >= 0.4.2
8097 , unordered-containers >= 0.2.3
81−
82− , generics-sop
83− , monad-control
84− , template-haskell
85− , transformers-base
script/travis-lifecycle-before_installnew file+11
@@ -0,0 +1,11 @@
1+#!/usr/bin/env bash
2+
3+set -e
4+
5+mkdir -p ~/.local/bin
6+
7+curl -L https://www.stackage.org/stack/linux-x86_64 | \
8+ tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
9+
10+ghc --version
11+stack --version
script/travis-lifecycle-installnew file+13
@@ -0,0 +1,13 @@
1+#!/usr/bin/env bash
2+
3+set -e
4+
5+GHCVER=${GHCVER?"GHCVER needs to be set."}
6+
7+path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
8+
9+$path/travis-timeout \
10+ stack --no-terminal --skip-ghc-check --stack-yaml stack-$GHCVER.yaml setup
11+
12+$path/travis-timeout \
13+ stack --no-terminal --skip-ghc-check --stack-yaml stack-$GHCVER.yaml test pagerduty --only-snapshot
script/travis-lifecycle-scriptnew file+9
@@ -0,0 +1,9 @@
1+#!/usr/bin/env bash
2+
3+set -e
4+
5+GHCVER=${GHCVER?"GHCVER needs to be set."}
6+
7+path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
8+
9+stack --no-terminal --skip-ghc-check --stack-yaml stack-$GHCVER.yaml test pagerduty
script/travis-timeoutnew file+15
@@ -0,0 +1,15 @@
1+#!/usr/bin/env bash
2+
3+$* &
4+pidA=$!
5+minutes=0
6+
7+while true; do sleep 60; ((minutes++)); echo -e "\033[0;32m$minutes minute(s) elapsed running '$*'\033[0m."; done &
8+pidB=$!
9+wait $pidA
10+resA=$?
11+
12+echo -e "\033[0;32m'$*' exited with status ${resA}.\033[0m"
13+kill -9 $pidB
14+
15+exit $resA
src/Control/Monad/Trans/PagerDuty.hs+55−72
@@ -2,15 +2,12 @@
22{-# LANGUAGE FlexibleContexts #-}
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5−{-# LANGUAGE KindSignatures #-}
65{-# LANGUAGE MultiParamTypeClasses #-}
7−{-# LANGUAGE RecordWildCards #-}
8−{-# LANGUAGE TemplateHaskell #-}
96{-# LANGUAGE TypeFamilies #-}
107{-# LANGUAGE UndecidableInstances #-}
118
129-- Module : Control.Monad.Trans.PagerDuty
13−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1411-- License : This Source Code Form is subject to the terms of
1512-- the Mozilla Public License, v. 2.0.
1613-- A copy of the MPL can be found in the LICENSE file or
@@ -22,57 +19,50 @@
2219module Control.Monad.Trans.PagerDuty
2320 (
2421 -- * Transformer
25− PD
26− , PDT
22+ PagerDuty
23+ , PagerDutyT
2724
28− -- * Run
29− , runPDT
25+ -- * Running
26+ , runPagerDutyT
3027
31− -- * Environment
32− , Env
33− , envDomain
34− , envAuth
35− , envManager
36−-- , envLogging
37−
38− -- * Integration API
28+ -- * Integration events
3929 , submit
30+ , submitCatch
4031
41− -- * REST API
32+ -- * REST requests
4233 , send
34+ , sendCatch
4335 , paginate
36+ , paginateCatch
37+
38+ -- ** Lifting errors
39+ , hoistError
40+
41+ , module Network.PagerDuty.Types
4442 ) where
4543
4644import Control.Applicative
47−import Control.Lens
45+import Control.Monad
4846import Control.Monad.Base
4947import Control.Monad.Catch
50−import Control.Monad.Except
48+import Control.Monad.Except (MonadError (..))
5149import Control.Monad.Morph
5250import Control.Monad.Reader
5351import Control.Monad.Trans.Control
52+import Control.Monad.Trans.Except
5453import Data.Aeson
5554import Data.Conduit
56−import Network.HTTP.Client (Manager)
57−import Network.PagerDuty.Integration (Event, Response)
58−import qualified Network.PagerDuty.Integration as Int
59−import qualified Network.PagerDuty.REST as REST
55+import Network.PagerDuty.Integration (Event, Response)
56+import qualified Network.PagerDuty.Integration as Int
57+import Network.PagerDuty.Internal.Types
58+import qualified Network.PagerDuty.REST as REST
6059import Network.PagerDuty.Types
6160
62−data Env (s :: Security) = Env
63− { _envDomain :: SubDomain
64− , _envAuth :: Auth s
65− , _envManager :: Manager
66−-- , _envLogging ::
67− }
68−
69−makeLenses ''Env
70−
71−-- | A convenient alias for 'PDT' 'IO'.
72−type PD s = PDT s IO
61+-- | A convenient alias for 'PagerDutyT' 'IO'.
62+type PagerDuty s = PagerDutyT s IO
7363
74−newtype PDT s m a = PDT
75− { unPDT :: ReaderT (Env s) (ExceptT Error m) a
64+newtype PagerDutyT s m a = PagerDutyT
65+ { unPagerDutyT :: ReaderT (Env s) (ExceptT Error m) a
7666 } deriving
7767 ( Functor
7868 , Applicative
@@ -84,50 +74,48 @@ newtype PDT s m a = PDT
8474 , MonadError Error
8575 )
8676
87−instance MonadTrans (PDT s) where
88− lift = PDT . lift . lift
77+instance MonadTrans (PagerDutyT s) where
78+ lift = PagerDutyT . lift . lift
8979 {-# INLINE lift #-}
9080
91−instance MonadBase b m => MonadBase b (PDT s m) where
81+instance MonadBase b m => MonadBase b (PagerDutyT s m) where
9282 liftBase = liftBaseDefault
9383 {-# INLINE liftBase #-}
9484
95−instance MonadTransControl (PDT s) where
96− newtype StT (PDT s) a = StTAWS
97− { unStTAWS :: StT (ExceptT Error) (StT (ReaderT (Env s)) a)
98− }
85+instance MonadTransControl (PagerDutyT s) where
86+ type StT (PagerDutyT s) a = StT (ExceptT Error) (StT (ReaderT (Env s)) a)
9987
100− liftWith f = PDT $
88+ liftWith f = PagerDutyT $
10189 liftWith $ \g ->
102− liftWith $ \h ->
103− f (liftM StTAWS . h . g . unPDT)
90+ liftWith $ \h ->
91+ f (h . g . unPagerDutyT)
10492 {-# INLINE liftWith #-}
10593
106− restoreT = PDT . restoreT . restoreT . liftM unStTAWS
94+ restoreT = PagerDutyT . restoreT . restoreT
10795 {-# INLINE restoreT #-}
10896
109−instance MonadBaseControl b m => MonadBaseControl b (PDT s m) where
110− newtype StM (PDT s m) a = StMPDT { unStMPDT :: ComposeSt (PDT s) m a }
97+instance MonadBaseControl b m => MonadBaseControl b (PagerDutyT s m) where
98+ type StM (PagerDutyT s m) a = ComposeSt (PagerDutyT s) m a
11199
112− liftBaseWith = defaultLiftBaseWith StMPDT
100+ liftBaseWith = defaultLiftBaseWith
113101 {-# INLINE liftBaseWith #-}
114102
115− restoreM = defaultRestoreM unStMPDT
103+ restoreM = defaultRestoreM
116104 {-# INLINE restoreM #-}
117105
118−instance MFunctor (PDT s) where
119− hoist nat m = PDT (ReaderT (ExceptT . nat . runPDT m))
106+instance MFunctor (PagerDutyT s) where
107+ hoist nat m = PagerDutyT (ReaderT (ExceptT . nat . runPagerDutyT m))
120108 {-# INLINE hoist #-}
121109
122−instance MMonad (PDT s) where
123− embed f m = ask >>= f . runPDT m >>= either throwError return
110+instance MMonad (PagerDutyT s) where
111+ embed f m = ask >>= f . runPagerDutyT m >>= either throwError return
124112 {-# INLINE embed #-}
125113
126−runPDT :: PDT s m a -> Env s -> m (Either Error a)
127−runPDT (PDT k) = runExceptT . runReaderT k
114+runPagerDutyT :: PagerDutyT s m a -> Env s -> m (Either Error a)
115+runPagerDutyT (PagerDutyT k) = runExceptT . runReaderT k
128116
129−hoistEither :: (MonadError Error m) => Either Error a -> m a
130−hoistEither = either throwError return
117+hoistError :: (MonadError Error m) => Either Error a -> m a
118+hoistError = either throwError return
131119
132120scoped :: MonadReader (Env s) m => (Env s -> m a) -> m a
133121scoped f = ask >>= f
@@ -135,20 +123,17 @@ scoped f = ask >>= f
135123submit :: ( MonadIO m
136124 , MonadReader (Env s) m
137125 , MonadError Error m
138− , Event a
139126 )
140− => a
127+ => Event
141128 -> m Response
142−submit = submitCatch >=> hoistEither
129+submit = submitCatch >=> hoistError
143130
144131submitCatch :: ( MonadIO m
145132 , MonadReader (Env s) m
146− , Event a
147133 )
148− => a
134+ => Event
149135 -> m (Either Error Response)
150−submitCatch x = scoped $ \e ->
151− Int.submit (_envManager e) x
136+submitCatch x = scoped $ \e -> Int.submitWith (_envManager e) (_envLogger e) x
152137
153138send :: ( MonadIO m
154139 , MonadReader (Env s) m
@@ -157,7 +142,7 @@ send :: ( MonadIO m
157142 )
158143 => Request a s b
159144 -> m b
160−send = sendCatch >=> hoistEither
145+send = sendCatch >=> hoistError
161146
162147sendCatch :: ( MonadIO m
163148 , MonadReader (Env s) m
@@ -165,8 +150,7 @@ sendCatch :: ( MonadIO m
165150 )
166151 => Request a s b
167152 -> m (Either Error b)
168−sendCatch x = scoped $ \Env{..} ->
169− REST.send _envAuth _envDomain _envManager x
153+sendCatch x = scoped (`REST.sendWith` x)
170154
171155paginate :: ( MonadIO m
172156 , MonadReader (Env s) m
@@ -176,7 +160,7 @@ paginate :: ( MonadIO m
176160 )
177161 => Request a s b
178162 -> Source m b
179−paginate x = paginateCatch x $= awaitForever (hoistEither >=> yield)
163+paginate x = paginateCatch x $= awaitForever (hoistError >=> yield)
180164
181165paginateCatch :: ( MonadIO m
182166 , MonadReader (Env s) m
@@ -185,5 +169,4 @@ paginateCatch :: ( MonadIO m
185169 )
186170 => Request a s b
187171 -> Source m (Either Error b)
188−paginateCatch x = scoped $ \Env{..} ->
189− REST.paginate _envAuth _envDomain _envManager x
172+paginateCatch x = scoped (`REST.paginateWith` x)
src/Network/PagerDuty/IO.hsdeleted−66
@@ -1,66 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−-- Module : Network.PagerDuty.IO
4−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
5−-- License : This Source Code Form is subject to the terms of
6−-- the Mozilla Public License, v. 2.0.
7−-- A copy of the MPL can be found in the LICENSE file or
8−-- you can obtain it at http://mozilla.org/MPL/2.0/.
9−-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
10−-- Stability : experimental
11−-- Portability : non-portable (GHC extensions)
12−
13−module Network.PagerDuty.IO where
14−
15−import Control.Monad
16−import Control.Monad.IO.Class
17−import Data.Aeson hiding (Error)
18−import qualified Data.ByteString.Lazy as LBS
19−import Network.HTTP.Client (Manager, httpLbs)
20−import qualified Network.HTTP.Client as Client
21−import Network.HTTP.Types
22−import Network.PagerDuty.Types
23−
24−request :: (MonadIO m, ToJSON a, FromJSON b)
25− => Manager
26− -> a
27− -> Client.Request
28− -> m (Either Error b)
29−request m x rq = liftIO (httpLbs raw m) >>= response
30− where
31− raw = rq
32− { Client.secure = True
33− , Client.port = 443
34− , Client.requestHeaders = headers
35− , Client.requestBody = Client.RequestBodyLBS (encode x)
36− }
37−
38− headers =
39− [ ("Content-Type", "application/json")
40− , ("Accept", "application/json")
41− ]
42−
43−response :: (Monad m, FromJSON b)
44− => Client.Response LBS.ByteString
45− -> m (Either Error b)
46−response rs = case statusCode (Client.responseStatus rs) of
47− 200 -> success
48− 201 -> success
49− 400 -> failure
50− 500 -> failure
51− n -> return . Left $ unhandled n
52− where
53− success = maybe (Left unknown) Right `liftM` parse
54− failure = maybe (Left unknown) Left `liftM` parse
55−
56− unhandled n = Internal
57− $ "PagerDuty returned unhandled status code: " ++ show n
58−
59− unknown = Internal
60− $ "Unable to parse response into a PagerDuty API compatible type: "
61− ++ show body
62−
63− parse :: (Monad m, FromJSON a) => m (Maybe a)
64− parse = return (decode body)
65−
66− body = Client.responseBody rs
src/Network/PagerDuty/Integration.hs+190−150
@@ -1,10 +1,12 @@
1−{-# LANGUAGE GADTs #-}
2−{-# LANGUAGE DefaultSignatures #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE FunctionalDependencies #-}
3+{-# LANGUAGE LambdaCase #-}
4+{-# LANGUAGE MultiParamTypeClasses #-}
5+{-# LANGUAGE OverloadedStrings #-}
6+{-# LANGUAGE TemplateHaskell #-}
57
68-- Module : Network.PagerDuty.Integration
7−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
9+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
810-- License : This Source Code Form is subject to the terms of
911-- the Mozilla Public License, v. 2.0.
1012-- A copy of the MPL can be found in the LICENSE file or
@@ -36,52 +38,57 @@
3638-- /See:/ <http://developer.pagerduty.com/documentation/integration/events>
3739module Network.PagerDuty.Integration
3840 (
39− -- * Events
41+ -- * Sending events
4042 submit
43+ , submitWith
4144
4245 -- ** Trigger
4346 , Trigger
4447 , trigger
45− , tDescription
46− , tIncidentKey
47− , tClient
48− , tClientUrl
49− , tDetails
48+ , client
49+ , clientUrl
5050
5151 -- ** Acknowledge
5252 , Acknowledge
5353 , acknowledge
54− , aDescription
55− , aDetails
5654
5755 -- ** Resolve
5856 , Resolve
5957 , resolve
60− , rDescription
61− , rDetails
58+
59+ -- * Fields
60+ , HasServiceKey (..)
61+ , HasIncidentKey (..)
62+ , HasDescription (..)
63+ , HasDetails (..)
6264
6365 -- * Types
64− , Event
65− , AnyEvent (..)
66+ , Event (..)
67+ , _Trigger
68+ , _Acknowledge
69+ , _Resolve
6670
6771 , Response
6872 , rsStatus
6973 , rsMessage
7074 , rsIncidentKey
75+
76+ , Generic
77+
78+ , module Network.PagerDuty.Types
7179 ) where
7280
7381import Control.Lens
7482import Control.Monad.IO.Class
7583import Data.Aeson
76−import Data.Default.Class
77−import qualified Data.HashMap.Strict as Map
78−import Data.Monoid
79−import Data.Text (Text)
80−import Network.HTTP.Client (Manager)
81−import qualified Network.HTTP.Client as Client
82−import Network.PagerDuty.IO
83−import Network.PagerDuty.TH
84−import Network.PagerDuty.Types
84+import qualified Data.Aeson.KeyMap as Map
85+import Data.Text (Text)
86+import Network.HTTP.Client (Manager)
87+import qualified Network.HTTP.Client as Client
88+import Network.PagerDuty.Internal.IO
89+import Network.PagerDuty.Internal.TH
90+import Network.PagerDuty.Internal.Types
91+import Network.PagerDuty.Types hiding (description, message)
8592
8693data Response = Response
8794 { _rsStatus :: Text
@@ -100,128 +107,161 @@ makeLens "_rsMessage" ''Response
100107-- | The key of the incident that will be affected by the request.
101108makeLens "_rsIncidentKey" ''Response
102109
103−class Event a where
104− eventType :: a -> Text
105− eventPayload :: a -> Object
106−
107− default eventPayload :: ToJSON a => a -> Object
108− eventPayload x = let Object o = toJSON x in o
109−
110−data AnyEvent where
111− Event :: Event a => a -> AnyEvent
112−
113−instance Event AnyEvent where
114− eventType (Event x) = eventType x
115− eventPayload (Event x) = eventPayload x
116−
117−data Generic = Generic
118− { _gServiceKey :: ServiceKey
119− , _gDescription :: Maybe Text
120− , _gIncidentKey :: IncidentKey
121− , _gDetails :: Object
110+class HasServiceKey s a | s -> a where
111+ -- | The GUID of one of your "Generic API" services. This is the "service key"
112+ -- listed on a Generic API's service detail page.
113+ serviceKey :: Lens' s a
114+
115+class HasIncidentKey s a | s -> a where
116+ -- | Identifies the incident to which this trigger event should be applied.
117+ -- If there's no open (i.e. unresolved) incident with this key, a new one
118+ -- will be created. If there's already an open incident with a matching key,
119+ -- this event will be appended to that incident's log. The event key provides
120+ -- an easy way to "de-dup" problem reports. If this field isn't provided,
121+ -- PagerDuty will automatically open a new incident with a unique key.
122+ incidentKey :: Lens' s a
123+
124+class HasDescription s a | s -> a where
125+ -- | A short description of the problem that led to this trigger.
126+ -- This field (or a truncated version) will be used when generating phone
127+ -- calls, SMS messages and alert emails. It will also appear on the incidents
128+ -- tables in the PagerDuty UI. The maximum length is 1024 characters.
129+ description :: Lens' s a
130+
131+class HasDetails s a | s -> a where
132+ -- | An arbitrary JSON object containing any data you'd like included
133+ -- in the incident log.
134+ details :: Lens' s a
135+
136+data Trigger = Trigger'
137+ { _tServiceKey' :: ServiceKey
138+ , _tIncidentKey' :: IncidentKey
139+ , _tDescription' :: Text
140+ , _tDetails' :: Maybe Object
141+ , _tClient' :: Maybe Text
142+ , _tClientUrl' :: Maybe Text
122143 } deriving (Eq, Show)
123144
124−deriveJSON ''Generic
145+deriveRecord ''Trigger
125146
126−makeLens "_gDescription" ''Generic
127−makeLens "_gDetails" ''Generic
147+instance HasServiceKey Trigger ServiceKey where serviceKey = tServiceKey'
148+instance HasIncidentKey Trigger IncidentKey where incidentKey = tIncidentKey'
149+instance HasDescription Trigger Text where description = tDescription'
150+instance HasDetails Trigger (Maybe Object) where details = tDetails'
128151
129−data Trigger = Trigger
130− { _tServiceKey :: ServiceKey
131− , _tDescription :: Text
132− , _tIncidentKey :: Maybe IncidentKey
133− , _tClient :: Maybe Text
134− , _tClientUrl :: Maybe Text
135− , _tDetails :: Object
136− } deriving (Eq, Show)
152+-- | The name of the monitoring client that is triggering this event.
153+client :: Lens' Trigger (Maybe Text)
154+client = tClient'
137155
138−deriveJSON ''Trigger
156+-- | The URL of the monitoring client that is triggering this event.
157+clientUrl :: Lens' Trigger (Maybe Text)
158+clientUrl = tClientUrl'
159+
160+data Generic = Generic'
161+ { _gServiceKey' :: ServiceKey
162+ , _gIncidentKey' :: IncidentKey
163+ , _gDescription' :: Maybe Text
164+ , _gDetails' :: Maybe Object
165+ } deriving (Eq, Show)
139166
140−instance Event Trigger where
141− eventType = const "trigger"
167+deriveRecord ''Generic
168+
169+instance HasServiceKey Generic ServiceKey where serviceKey = gServiceKey'
170+instance HasIncidentKey Generic IncidentKey where incidentKey = gIncidentKey'
171+instance HasDescription Generic (Maybe Text) where description = gDescription'
172+instance HasDetails Generic (Maybe Object) where details = gDetails'
173+
174+type Resolve = Generic
175+type Acknowledge = Generic
176+
177+data Event
178+ = Trigger Trigger -- ^ /See:/ 'trigger'
179+ | Acknowledge Generic -- ^ /See:/ 'acknowledge'
180+ | Resolve Generic -- ^ /See:/ 'resolve'
181+ deriving (Eq, Show)
182+
183+makePrisms ''Event
184+
185+instance HasServiceKey Event ServiceKey where
186+ serviceKey = lens f g
187+ where
188+ f (Trigger s) = _tServiceKey' s
189+ f (Acknowledge s) = _gServiceKey' s
190+ f (Resolve s) = _gServiceKey' s
191+
192+ g (Trigger s) x = Trigger $ s { _tServiceKey' = x }
193+ g (Acknowledge s) x = Acknowledge $ s { _gServiceKey' = x }
194+ g (Resolve s) x = Resolve $ s { _gServiceKey' = x }
195+
196+instance HasIncidentKey Event IncidentKey where
197+ incidentKey = lens f g
198+ where
199+ f (Trigger s) = _tIncidentKey' s
200+ f (Acknowledge s) = _gIncidentKey' s
201+ f (Resolve s) = _gIncidentKey' s
202+
203+ g (Trigger s) x = Trigger $ s { _tIncidentKey' = x }
204+ g (Acknowledge s) x = Acknowledge $ s { _gIncidentKey' = x }
205+ g (Resolve s) x = Resolve $ s { _gIncidentKey' = x }
206+
207+instance HasDetails Event (Maybe Object) where
208+ details = lens f g
209+ where
210+ f (Trigger s) = _tDetails' s
211+ f (Acknowledge s) = _gDetails' s
212+ f (Resolve s) = _gDetails' s
213+
214+ g (Trigger s) x = Trigger $ s { _tDetails' = x }
215+ g (Acknowledge s) x = Acknowledge $ s { _gDetails' = x }
216+ g (Resolve s) x = Resolve $ s { _gDetails' = x }
217+
218+instance ToJSON Event where
219+ toJSON = \case
220+ Trigger x -> event "trigger" x
221+ Acknowledge x -> event "acknowledge" x
222+ Resolve x -> event "resolve" x
223+ where
224+ event k x =
225+ case toJSON x of
226+ Object o -> Object (Map.insert "event_type" (String k) o)
227+ v -> v
142228
143229-- | Your monitoring tools should send PagerDuty a trigger event to report a new
144230-- or ongoing problem. When PagerDuty receives a trigger event, it will either open
145231-- a new incident, or add a new trigger log entry to an existing incident,
146232-- depending on the provided incident_key.
147−trigger :: ServiceKey
148− -> Text -- ^ 'tDescription'
149− -> Trigger
150−trigger k d =
151− Trigger
152− { _tServiceKey = k
153− , _tDescription = d
154− , _tIncidentKey = Nothing
155− , _tClient = Nothing
156− , _tClientUrl = Nothing
157− , _tDetails = mempty
233+trigger :: ServiceKey -- ^ 'serviceKey'
234+ -> IncidentKey -- ^ 'incidentKey'
235+ -> Text -- ^ 'description'
236+ -> Event
237+trigger k i d =
238+ Trigger Trigger'
239+ { _tServiceKey' = k
240+ , _tDescription' = d
241+ , _tIncidentKey' = i
242+ , _tClient' = Nothing
243+ , _tClientUrl' = Nothing
244+ , _tDetails' = Nothing
158245 }
159246
160−-- | A short description of the problem that led to this trigger.
161−-- This field (or a truncated version) will be used when generating phone
162−-- calls, SMS messages and alert emails. It will also appear on the incidents
163−-- tables in the PagerDuty UI. The maximum length is 1024 characters.
164−makeLens "_tDescription" ''Trigger
165−
166−-- | Identifies the incident to which this trigger event should be applied.
167−-- If there's no open (i.e. unresolved) incident with this key, a new one
168−-- will be created. If there's already an open incident with a matching key,
169−-- this event will be appended to that incident's log. The event key provides
170−-- an easy way to "de-dup" problem reports. If this field isn't provided,
171−-- PagerDuty will automatically open a new incident with a unique key.
172−makeLens "_tIncidentKey" ''Trigger
173−
174−-- | The name of the monitoring client that is triggering this event.
175−makeLens "_tClient" ''Trigger
176−
177−-- | The URL of the monitoring client that is triggering this event.
178−makeLens "_tClientUrl" ''Trigger
179−
180−-- | An arbitrary JSON object containing any data you'd like included
181−-- in the incident log.
182−makeLens "_tDetails" ''Trigger
183−
184−newtype Acknowledge = Acknowledge Generic
185−
186−deriveJSON ''Acknowledge
187−makePrisms ''Acknowledge
188−
189−instance Event Acknowledge where
190− eventType = const "acknowledge"
191−
192247-- | Acknowledge events cause the referenced incident to enter the acknowledged
193248-- state.
194249--
195250-- While an incident is acknowledged, it won't generate any additional
196251-- notifications, even if it receives new trigger events. Your monitoring tools
197−-- should send PagerDuty an acknowledge event when they know someone is presently
198−-- working on the problem.
199−acknowledge :: ServiceKey -> IncidentKey -> Acknowledge
252+-- should send PagerDuty an acknowledge event when they know someone is
253+-- presently working on the problem.
254+acknowledge :: ServiceKey -- ^ 'serviceKey'
255+ -> IncidentKey -- ^ 'incidentKey'
256+ -> Event
200257acknowledge k i =
201− Acknowledge Generic
202− { _gServiceKey = k
203− , _gDescription = Nothing
204− , _gIncidentKey = i
205− , _gDetails = mempty
258+ Acknowledge Generic'
259+ { _gServiceKey' = k
260+ , _gIncidentKey' = i
261+ , _gDescription' = Nothing
262+ , _gDetails' = Nothing
206263 }
207264
208−-- | Text that will appear in the incident's log associated with this event.
209−aDescription :: Lens' Acknowledge (Maybe Text)
210−aDescription = _Acknowledge.gDescription
211−
212−-- | An arbitrary JSON object containing any data you'd like included
213−-- in the incident log.
214−aDetails :: Lens' Acknowledge Object
215−aDetails = _Acknowledge.gDetails
216−
217−newtype Resolve = Resolve Generic
218−
219−deriveJSON ''Resolve
220−makePrisms ''Resolve
221−
222−instance Event Resolve where
223− eventType = const "acknowledge"
224−
225265-- | Resolve events cause the referenced incident to enter the resolved state.
226266--
227267-- Once an incident is resolved, it won't generate any additional
@@ -229,30 +269,30 @@ instance Event Resolve where
229269-- incident won't re-open the incident. Instead, a new incident will be
230270-- created. Your monitoring tools should send PagerDuty a resolve event when the
231271-- problem that caused the initial trigger event has been fixed.
232−resolve :: ServiceKey -> IncidentKey -> Resolve
272+resolve :: ServiceKey -- ^ 'serviceKey'
273+ -> IncidentKey -- ^ 'incidentKey'
274+ -> Event
233275resolve k i =
234− Resolve Generic
235− { _gServiceKey = k
236− , _gDescription = Nothing
237− , _gIncidentKey = i
238− , _gDetails = mempty
276+ Resolve Generic'
277+ { _gServiceKey' = k
278+ , _gIncidentKey' = i
279+ , _gDescription' = Nothing
280+ , _gDetails' = Nothing
239281 }
240282
241−-- | Text that will appear in the incident's log associated with this event.
242−rDescription :: Lens' Resolve (Maybe Text)
243−rDescription = _Resolve.gDescription
244−
245−-- | An arbitrary JSON object containing any data youd like included
246−-- in the incident log.
247−rDetails :: Lens' Resolve Object
248−rDetails = _Resolve.gDetails
249−
250283-- | Send an event to the integration API.
251−submit :: (MonadIO m, Event a) => Manager -> a -> m (Either Error Response)
252−submit m x = request m payload $ def
253− { Client.host = "events.pagerduty.com"
254− , Client.path = "/generic/2010-04-15/create_event.json"
255− }
256− where
257− payload = Object $
258− Map.insert "event_type" (String (eventType x)) (eventPayload x)
284+submit :: MonadIO m => Manager -> Event -> m (Either Error Response)
285+submit m = submitWith m None
286+
287+-- | /See:/ 'submit'
288+submitWith :: MonadIO m
289+ => Manager
290+ -> Logger
291+ -> Event
292+ -> m (Either Error Response)
293+submitWith m l e = request m l e $
294+ Client.defaultRequest
295+ { Client.host = "events.pagerduty.com"
296+ , Client.path = "/generic/2010-04-15/create_event.json"
297+ , Client.method = "POST"
298+ }
src/Network/PagerDuty/Internal/IO.hsnew file+76
@@ -0,0 +1,76 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+
4+-- Module : Network.PagerDuty.Internal.IO
5+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
6+-- License : This Source Code Form is subject to the terms of
7+-- the Mozilla Public License, v. 2.0.
8+-- A copy of the MPL can be found in the LICENSE file or
9+-- you can obtain it at http://mozilla.org/MPL/2.0/.
10+-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
11+-- Stability : experimental
12+-- Portability : non-portable (GHC extensions)
13+
14+module Network.PagerDuty.Internal.IO where
15+
16+import Control.Monad
17+import Control.Monad.IO.Class
18+import Data.Aeson hiding (Error)
19+import qualified Data.ByteString.Lazy as LBS
20+import Data.Monoid
21+import qualified Data.Text as Text
22+import Network.HTTP.Client (Manager, httpLbs)
23+import qualified Network.HTTP.Client as Client
24+import Network.HTTP.Types
25+import Network.PagerDuty.Internal.Types
26+
27+request :: (MonadIO m, ToJSON a, FromJSON b)
28+ => Manager
29+ -> Logger
30+ -> a
31+ -> Client.Request
32+ -> m (Either Error b)
33+request m l x rq = msg >> liftIO (httpLbs raw m) >>= response l
34+ where
35+ msg = debug l ("[Raw Request]\n" <> Text.pack (show raw))
36+
37+ raw = rq
38+ { Client.secure = True
39+ , Client.port = 443
40+ , Client.requestHeaders = headers
41+ , Client.requestBody = Client.RequestBodyLBS (encode x)
42+ }
43+
44+ headers =
45+ [ ("Content-Type", "application/json")
46+ , ("Accept", "application/json")
47+ ]
48+
49+response :: forall m b. (MonadIO m, FromJSON b)
50+ => Logger
51+ -> Client.Response LBS.ByteString
52+ -> m (Either Error b)
53+response l rs = case statusCode (Client.responseStatus rs) of
54+ 200 -> success
55+ 201 -> success
56+ 400 -> failure
57+ 500 -> failure
58+ n -> return . Left $ unhandled n
59+ where
60+ success = maybe (Left unknown) Right `liftM` parse
61+ failure = maybe (Left unknown) Left `liftM` parse
62+
63+ unhandled n = Internal $
64+ "PagerDuty returned unhandled status code: "
65+ <> Text.pack (show n)
66+
67+ unknown = Internal $
68+ "Unable to parse response into a PagerDuty API compatible type: "
69+ <> Text.pack (show body)
70+
71+ parse :: FromJSON a => m (Maybe a)
72+ parse = msg >> return (decode body)
73+
74+ msg = debug l ("[Raw Response]\n" <> Text.pack (show rs))
75+
76+ body = Client.responseBody rs
src/Network/PagerDuty/Options.hs → src/Network/PagerDuty/Internal/Options.hsrenamed+6−6
@@ -1,5 +1,5 @@
1−-- Module : Network.PagerDuty.Options
2−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1+-- Module : Network.PagerDuty.Internal.Options
2+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
33-- License : This Source Code Form is subject to the terms of
44-- the Mozilla Public License, v. 2.0.
55-- A copy of the MPL can be found in the LICENSE file or
@@ -8,15 +8,15 @@
88-- Stability : experimental
99-- Portability : non-portable (GHC extensions)
1010
11−module Network.PagerDuty.Options
11+module Network.PagerDuty.Internal.Options
1212 ( dropped
1313 , hyphenated
1414 , underscored
1515 ) where
1616
17−import Data.Aeson.Types
18−import Data.Char
19−import Data.List
17+import Data.Aeson.Types
18+import Data.Char
19+import Data.List
2020
2121dropped :: Int -> Options -> Options
2222dropped n o = o
src/Network/PagerDuty/Query.hs → src/Network/PagerDuty/Internal/Query.hsrenamed+21−19
@@ -1,12 +1,13 @@
11{-# LANGUAGE ConstraintKinds #-}
22{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE FlexibleContexts #-}
34{-# LANGUAGE GADTs #-}
45{-# LANGUAGE OverloadedStrings #-}
56{-# LANGUAGE ScopedTypeVariables #-}
67{-# LANGUAGE TupleSections #-}
78
8−-- Module : Network.PagerDuty.Query
9−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
9+-- Module : Network.PagerDuty.Internal.Query
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1011-- License : This Source Code Form is subject to the terms of
1112-- the Mozilla Public License, v. 2.0.
1213-- A copy of the MPL can be found in the LICENSE file or
@@ -15,7 +16,7 @@
1516-- Stability : experimental
1617-- Portability : non-portable (GHC extensions)
1718
18−module Network.PagerDuty.Query
19+module Network.PagerDuty.Internal.Query
1920 ( QueryValues (..)
2021 , gquery
2122 , gqueryWith
@@ -23,17 +24,17 @@ module Network.PagerDuty.Query
2324
2425import Data.Aeson.Types
2526import Data.Bifunctor
26−import Data.ByteString (ByteString)
27−import qualified Data.ByteString.Char8 as BS
27+import Data.ByteString (ByteString)
28+import qualified Data.ByteString.Char8 as BS
2829import Data.ByteString.Conversion
29−import Data.Function (on)
30−import Data.List (groupBy)
31−import Data.Monoid ((<>))
32−import Data.Text (Text)
33−import qualified Data.Text.Encoding as Text
30+import Data.Function (on)
31+import Data.List (groupBy)
32+import Data.Monoid ((<>))
33+import Data.Text (Text)
34+import qualified Data.Text.Encoding as Text
3435import Generics.SOP
3536import Network.HTTP.Types
36−import Network.PagerDuty.Options
37+import Network.PagerDuty.Internal.Options
3738
3839class QueryValues a where
3940 queryValues :: a -> [ByteString]
@@ -58,14 +59,15 @@ gqueryWith :: forall a. (Generic a, HasDatatypeInfo a, All2 QueryValues (Code a)
5859 -> a
5960 -> Query
6061gqueryWith o a = case datatypeInfo (Proxy :: Proxy a) of
61− ADT _ _ cs -> go cs (from a)
62− Newtype _ _ c -> go (c :* Nil) (from a)
62+ ADT _ _ cs _ -> go cs (from a)
63+ Newtype _ _ c -> go (c :* Nil) (from a)
6364 where
64− go :: (All2 QueryValues xss, SingI xss)
65+ go :: (All2 QueryValues xss, SListI xss)
6566 => NP ConstructorInfo xss
6667 -> SOP I xss
6768 -> Query
68− go cs (SOP sop) = group . unI . hcollapse $ hcliftA2' p (gctor o) cs sop
69+ go cs (SOP sop) =
70+ group . hcollapse $ hcliftA2' p (gctor o) cs sop
6971
7072 group :: [(ByteString, ByteString)] -> Query
7173 group = concatMap f . groupBy ((==) `on` fst)
@@ -82,7 +84,7 @@ gctor :: All QueryValues xs
8284gctor o (Constructor n) args =
8385 K . concat . hcollapse $ hcliftA p (K . map (k,) . queryValues . unI) args
8486 where
85− k = BS.pack $ (constructorTagModifier o) n
87+ k = BS.pack (constructorTagModifier o n)
8688
8789gctor o (Record _ ns) args =
8890 K . concat . hcollapse $ hcliftA2 p (gfield o) ns args
@@ -90,9 +92,9 @@ gctor o (Record _ ns) args =
9092gctor o (Infix n _ _) (x :* y :* Nil) =
9193 K $ map (k,) (queryValues (unI x) ++ queryValues (unI y))
9294 where
93− k = BS.pack $ (constructorTagModifier o) n
95+ k = BS.pack (constructorTagModifier o n)
9496
95−gctor _ (Infix _ _ _) _ =
97+gctor _ Infix{} _ =
9698 error "Network.PagerDuty.Generics.inaccessible"
9799
98100gfield :: QueryValues a
@@ -103,7 +105,7 @@ gfield :: QueryValues a
103105gfield o (FieldInfo f) (I a) =
104106 K $ map (k,) (queryValues a)
105107 where
106− k = BS.pack $ (fieldLabelModifier o) f
108+ k = BS.pack (fieldLabelModifier o f)
107109
108110p :: Proxy QueryValues
109111p = Proxy
src/Network/PagerDuty/TH.hs → src/Network/PagerDuty/Internal/TH.hsrenamed+9−9
@@ -1,7 +1,7 @@
11{-# LANGUAGE TemplateHaskell #-}
22
3−-- Module : Network.PagerDuty.TH
4−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
3+-- Module : Network.PagerDuty.Internal.TH
4+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
55-- License : This Source Code Form is subject to the terms of
66-- the Mozilla Public License, v. 2.0.
77-- A copy of the MPL can be found in the LICENSE file or
@@ -10,7 +10,7 @@
1010-- Stability : experimental
1111-- Portability : non-portable (GHC extensions)
1212
13−module Network.PagerDuty.TH
13+module Network.PagerDuty.Internal.TH
1414 (
1515 -- * Requests
1616 jsonRequest
@@ -40,15 +40,15 @@ module Network.PagerDuty.TH
4040
4141import Control.Applicative
4242import Control.Lens
43−import qualified Data.Aeson.TH as Aeson
43+import qualified Data.Aeson.TH as Aeson
4444import Data.Aeson.Types
45−import Data.ByteString (ByteString)
46−import qualified Data.Text.Encoding as Text
45+import Data.ByteString (ByteString)
46+import qualified Data.Text.Encoding as Text
4747import Generics.SOP.TH
4848import Language.Haskell.TH
4949import Network.HTTP.Types.QueryLike
50−import Network.PagerDuty.Query
51−import Network.PagerDuty.Options
50+import Network.PagerDuty.Internal.Options
51+import Network.PagerDuty.Internal.Query
5252
5353jsonRequest :: Name -> Q [Dec]
5454jsonRequest n = concat <$> sequence
@@ -61,7 +61,7 @@ queryRequest :: Name -> Q [Dec]
6161queryRequest n = concat <$> sequence
6262 [ deriveGeneric n
6363 , makeLenses n
64− , [d|instance ToJSON $(conT n) where toJSON = const (toJSON (object []))|]
64+ , [d|instance ToJSON $(conT n) where toJSON = const emptyObject|]
6565 , [d|instance QueryLike $(conT n) where toQuery = gquery|]
6666 ]
6767
src/Network/PagerDuty/Internal/Types.hsnew file+497
@@ -0,0 +1,497 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FunctionalDependencies #-}
5+{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7+{-# LANGUAGE KindSignatures #-}
8+{-# LANGUAGE MultiParamTypeClasses #-}
9+{-# LANGUAGE OverloadedStrings #-}
10+{-# LANGUAGE PatternSynonyms #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE StandaloneDeriving #-}
13+{-# LANGUAGE TemplateHaskell #-}
14+{-# LANGUAGE TupleSections #-}
15+{-# LANGUAGE ViewPatterns #-}
16+
17+-- Module : Network.PagerDuty.Internal.Types
18+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
19+-- License : This Source Code Form is subject to the terms of
20+-- the Mozilla Public License, v. 2.0.
21+-- A copy of the MPL can be found in the LICENSE file or
22+-- you can obtain it at http://mozilla.org/MPL/2.0/.
23+-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
24+-- Stability : experimental
25+-- Portability : non-portable (GHC extensions)
26+
27+module Network.PagerDuty.Internal.Types where
28+
29+import Control.Applicative
30+import Control.Lens hiding ((.=), Empty)
31+import Control.Monad.IO.Class
32+import Data.Aeson hiding (Error, Key)
33+import qualified Data.Aeson.KeyMap as Map
34+import Data.Aeson.Types (Parser)
35+import Data.ByteString (ByteString)
36+import qualified Data.ByteString.Char8 as BS
37+import Data.ByteString.Conversion hiding (List)
38+import Data.Default.Class
39+import Data.Function (on)
40+import Data.List (deleteBy, intersperse)
41+import Data.Monoid
42+import Data.String
43+import Data.Text (Text)
44+import qualified Data.Text as Text
45+import qualified Data.Text.Encoding as Text
46+import Data.Time (UTCTime, TimeZone, formatTime, utc, timeZoneName)
47+import GHC.TypeLits
48+import Network.HTTP.Client (Manager)
49+import Network.HTTP.Types
50+import Network.HTTP.Types.QueryLike
51+import Network.PagerDuty.Internal.Query
52+import Network.PagerDuty.Internal.TH
53+import Data.Time.Locale.Compat
54+
55+newtype CSV a = CSV [a]
56+ deriving (Eq, Show, Semigroup, Monoid)
57+
58+makePrisms ''CSV
59+
60+instance ToByteString a => QueryValues (CSV a)
61+
62+instance ToByteString a => ToByteString (CSV a) where
63+ builder (CSV xs) = mconcat . intersperse "," $ map builder xs
64+
65+instance FromJSON a => FromJSON (CSV a) where
66+ parseJSON = withText "comma_separated_value" $
67+ fmap CSV . traverse (parseJSON . String) . Text.split (== ',')
68+
69+instance ToByteString a => ToJSON (CSV a) where
70+ toJSON = String . Text.decodeUtf8 . toByteString'
71+
72+newtype List a = L [a]
73+ deriving (Eq, Show, Semigroup, Monoid)
74+
75+deriveJSON ''List
76+makePrisms ''List
77+
78+instance QueryValues a => QueryValues (List a) where
79+ queryValues (L xs) = concatMap queryValues xs
80+
81+newtype Bool' = B Bool
82+ deriving (Eq, Show)
83+
84+deriveJSON ''Bool'
85+makePrisms ''Bool'
86+
87+instance ToByteString Bool' where
88+ builder (B True) = "true"
89+ builder (B False) = "false"
90+
91+instance QueryValues Bool'
92+
93+pattern T = B True
94+pattern F = B False
95+
96+newtype Date = D UTCTime
97+ deriving (Eq, Ord, Show)
98+
99+makePrisms ''Date
100+
101+instance FromJSON Date where
102+ parseJSON = fmap D . parseJSON
103+
104+instance ToJSON Date where
105+ toJSON (D d) = toJSON d
106+
107+instance ToByteString Date where
108+ builder (D d) = builder
109+ (formatTime defaultTimeLocale ("%Y-%m-%dT%XZ") d)
110+
111+instance QueryValues Date
112+
113+newtype TZ = TZ TimeZone
114+ deriving (Eq, Show)
115+
116+makePrisms ''TZ
117+
118+instance FromJSON TZ where
119+ parseJSON = undefined
120+
121+instance ToJSON TZ where
122+ toJSON = toJSON . Text.decodeUtf8 . toByteString'
123+
124+instance ToByteString TZ where
125+ builder (TZ tz) = builder (timeZoneName tz)
126+
127+instance QueryValues TZ
128+
129+instance Default TZ where
130+ def = TZ utc
131+
132+data Security = Basic | Token
133+ deriving (Eq, Show)
134+
135+data Auth (a :: Security) where
136+ AuthBasic :: ByteString -> ByteString -> Auth 'Basic
137+ AuthToken :: ByteString -> Auth 'Token
138+
139+deriving instance Eq (Auth a)
140+deriving instance Show (Auth a)
141+
142+newtype SubDomain = SubDomain { subDomain :: ByteString }
143+ deriving (Eq, Show, IsString, ToByteString)
144+
145+mkSubDomain :: ByteString -> SubDomain
146+mkSubDomain = SubDomain
147+
148+domain :: SubDomain -> ByteString
149+domain (SubDomain s)
150+ | base `BS.isSuffixOf` s = s
151+ | otherwise = s <> base
152+ where
153+ base = ".pagerduty.com"
154+
155+-- | The log level and associated logger function.
156+data Logger
157+ = None
158+ | Debug (Text -> IO ())
159+
160+-- | Log a message using the debug logger, or if none is specified noop.
161+debug :: MonadIO m => Logger -> Text -> m ()
162+debug None = const (return ())
163+debug (Debug f) = liftIO . f
164+
165+-- | The environment containing the parameters required to
166+-- make PagerDuty requests.
167+data Env (s :: Security) = Env
168+ { _envDomain :: SubDomain
169+ , _envAuth' :: Auth s
170+ , _envManager :: Manager
171+ , _envLogger :: Logger
172+ }
173+
174+makeLenses ''Env
175+
176+envAuth :: forall s s'. Lens (Env s) (Env s') (Auth s) (Auth s')
177+envAuth = lens _envAuth' (\s x -> s { _envAuth' = x })
178+
179+prod :: SubDomain -> Auth s -> Manager -> Env s
180+prod d a m = Env d a m None
181+
182+newtype Code = Code Integer
183+ deriving (Eq, Show, Num)
184+
185+deriveJSON ''Code
186+
187+description :: Code -> Text
188+description (Code c) =
189+ case c of
190+ 2000 -> "Internal Error"
191+ 2001 -> "Invalid Input Provided"
192+ 2002 -> "Arguments Caused Error"
193+ 2003 -> "Missing Arguments"
194+ 2004 -> "Invalid 'since' or 'until' Parameter Values"
195+ 2005 -> "Invalid Query Date Range"
196+ 2006 -> "Authentication Failed"
197+ 2007 -> "Account Not Found"
198+ 2008 -> "Account Locked"
199+ 2009 -> "Only HTTPS Allowed For This Call"
200+ 2010 -> "Access Denied"
201+ 2011 -> "The action requires a 'requester_id' to be specified"
202+ 2012 -> "Your account is expired and cannot use the API"
203+ _ -> "Unrecognised error code"
204+
205+class HasMessage s a | s -> a where
206+ -- | A short human-readable message describing the error.
207+ message :: Lens' s a
208+
209+class HasErrors s a | s -> a where
210+ -- | A list of human-readable reasons for the error. These values,
211+ -- and even their format, are subject to change.
212+ errors :: Lens' s a
213+
214+data IntegrationError = IntegrationError
215+ { _ieStatus :: Text
216+ , _ieMessage :: Text
217+ , _ieErrors :: [Text]
218+ } deriving (Eq, Show)
219+
220+deriveRecord ''IntegrationError
221+
222+instance HasMessage IntegrationError Text where message = ieMessage
223+instance HasErrors IntegrationError [Text] where errors = ieErrors
224+
225+status :: Lens' IntegrationError Text
226+status = ieStatus
227+
228+data RESTError = RESTError
229+ { _reCode :: Code
230+ , _reMessage :: Text
231+ , _reErrors :: [Text]
232+ } deriving (Eq, Show)
233+
234+deriveRecord ''RESTError
235+
236+instance HasMessage RESTError Text where message = reMessage
237+instance HasErrors RESTError [Text] where errors = reErrors
238+
239+-- | In the case of an error, the PagerDuty error code can give further details
240+-- on the nature of the error.
241+--
242+-- /See:/ 'description'
243+code :: Lens' RESTError Code
244+code = reCode
245+
246+data Error
247+ = Internal Text
248+ | Integration IntegrationError
249+ | REST RESTError
250+ deriving (Eq, Show)
251+
252+instance FromJSON Error where
253+ parseJSON o = (REST <$> parseJSON o)
254+ <|> (Integration <$> parseJSON o)
255+
256+makePrisms ''Error
257+
258+instance HasMessage Error Text where
259+ message = lens f g
260+ where
261+ f (Internal x) = x
262+ f (Integration s) = _ieMessage s
263+ f (REST s) = _reMessage s
264+
265+ g (Internal _) x = Internal x
266+ g (Integration s) x = Integration $ s { _ieMessage = x }
267+ g (REST s) x = REST $ s { _reMessage = x }
268+
269+data Pager = Pager
270+ { _pgOffset :: !Int
271+ -- ^ The offset used in the execution of the query.
272+ , _pgLimit :: !Int
273+ -- ^ The limit used in the execution of the query.
274+ , _pgTotal :: !Int
275+ -- ^ The total number of records available.
276+ , _pgQuery :: Maybe Text
277+ -- ^ An optional query= value to be added to the query string.
278+ } deriving (Eq, Show)
279+
280+makeLenses ''Pager
281+
282+data Page a = Page
283+ { _pgItem :: a
284+ , _pgPager :: Maybe Pager
285+ }
286+
287+instance FromJSON a => FromJSON (Page a) where
288+ parseJSON = withObject "paginated" $ \o -> Page
289+ <$> parseJSON (Object o)
290+ <*> optional (parse o)
291+ where
292+ parse o = Pager
293+ -- The offset of the first record returned.
294+ -- Default is 0.
295+ <$> o .: "offset" .!= 0
296+ -- The number of records returned.
297+ -- Default (and max limit) is 100 for most APIs.
298+ <*> o .: "limit" .!= 100
299+ <*> o .: "total"
300+ <*> o .:? "query"
301+
302+instance ToJSON Pager where
303+ toJSON p = object
304+ [ "offset" .= _pgOffset p
305+ , "limit" .= _pgLimit p
306+ ]
307+
308+-- | A path segment.
309+data Path where
310+ Path :: Path
311+ Seg :: ToByteString a => a -> Path
312+
313+instance Semigroup Path where
314+ x <> Path = x
315+ Path <> y = y
316+ Seg x <> Seg y = Seg (builder x <> "/" <> builder y)
317+
318+instance Monoid Path where
319+ mempty = Path
320+
321+instance IsString Path where
322+ fromString = Seg
323+
324+instance ToByteString Path where
325+ builder Path = mempty
326+ builder (Seg x) = builder x
327+
328+(%) :: ToByteString a => Path -> a -> Path
329+a % b = a <> Seg b
330+
331+renderPath :: Path -> ByteString
332+renderPath = toByteString' . mappend v1
333+ where
334+ v1 :: Path
335+ v1 = "/api/v1"
336+
337+data Request a (s :: Security) b where
338+ Request :: (QueryLike a, ToJSON a)
339+ => { _rqMeth :: !StdMethod
340+ , _rqPath :: Path
341+ , _rqQuery :: Query
342+ , _rqBody :: a
343+ , _rqPager :: Maybe Pager
344+ , _rqUnwrap :: Value -> Parser Value
345+ }
346+ -> Request a s b
347+
348+instance ToJSON (Request a s b) where
349+ -- Manually unwrapped to ensure GADT constraint holds.
350+ toJSON (Request _ _ _ b p _) = Object $
351+ let Object x = toJSON b
352+ in case toJSON p of
353+ (Object y) -> x <> y
354+ _ -> x
355+
356+type Unwrap = Getting (First Value) Value Value
357+
358+-- | Create a defaulted request from the payload type.
359+mk :: (QueryLike a, ToJSON a) => a -> Request a s b
360+mk x = Request GET mempty mempty x Nothing pure
361+
362+empty :: Request Empty s r
363+empty = mk Empty
364+
365+-- | Lens into the body of a request.
366+upd :: (QueryLike a, ToJSON a) => Lens' (Request a s b) a
367+upd = lens _rqBody (\(Request m p q _ g u) x -> Request m p q x g u)
368+
369+-- | Drop the security constraint.
370+auth :: Request a s b -> Request a t b
371+auth (Request x m p q g u) = Request x m p q g u
372+
373+meth :: Lens' (Request a s b) StdMethod
374+meth = lens _rqMeth (\r x -> r { _rqMeth = x })
375+
376+path :: Lens' (Request a s b) Path
377+path = lens _rqPath (\r x -> r { _rqPath = x })
378+
379+query :: QueryValueLike v
380+ => Lens (Request a s b) (Request a s b) Query [(ByteString, v)]
381+query = lens _rqQuery (\r x -> r { _rqQuery = toQuery x })
382+
383+pager :: Lens' (Request a s b) (Maybe Pager)
384+pager = lens _rqPager (\r x -> r { _rqPager = x })
385+
386+unwrap :: Setter (Request a s b) (Request a s b) (Value -> Parser Value) Unwrap
387+unwrap f r = f (_rqUnwrap r) <&> \k -> r { _rqUnwrap = g k }
388+ where
389+ g k x = maybe (fail "Failed to extract nested keys.") return (x ^? k)
390+
391+-- | Exists primarily to obtain a constraint for the 'paginate' function.
392+class Paginate a where
393+ next :: Request a s b -> Maybe Pager -> Maybe (Request a s b)
394+ next rq = maybe Nothing go
395+ where
396+ go x | x ^. pgTotal == 0 = Nothing
397+ | otherwise = Just $
398+ rq & pager ?~ (x & pgOffset +~ x ^. pgTotal)
399+ & query %~ (add . clear)
400+ where
401+ add :: Query -> Query
402+ add = maybe id ((:) . (k,) . Just . Text.encodeUtf8) (x ^. pgQuery)
403+
404+ clear :: Query -> Query
405+ clear = deleteBy ((==) `on` fst) (k, Nothing)
406+
407+ k :: ByteString
408+ k = "query"
409+
410+newtype Key (a :: Symbol) = Key Text
411+ deriving (Eq, Show, IsString)
412+
413+mkKey :: Text -> Key a
414+mkKey = Key
415+
416+instance FromJSON (Key a) where
417+ parseJSON = withText "key" (return . Key)
418+
419+instance ToJSON (Key a) where
420+ toJSON (Key k) = toJSON k
421+
422+instance ToByteString (Key a) where
423+ builder (Key k) = builder k
424+
425+instance QueryValues (Key a)
426+
427+instance QueryValueLike (Key a) where
428+ toQueryValue = Just . toByteString'
429+
430+type ServiceKey = Key "service"
431+type IncidentKey = Key "incident"
432+
433+newtype Id (a :: Symbol) = Id Text
434+ deriving (Eq, Show, IsString)
435+
436+mkId :: Text -> Id a
437+mkId = Id
438+
439+instance FromJSON (Id a) where
440+ parseJSON = withText "id" (return . Id)
441+
442+instance ToJSON (Id a) where
443+ toJSON (Id i) = toJSON i
444+
445+instance ToByteString (Id a) where
446+ builder (Id i) = builder i
447+
448+instance QueryValues (Id a)
449+
450+instance QueryValueLike (Id a) where
451+ toQueryValue = Just . toByteString'
452+
453+type AlertId = Id "alert"
454+type ContactId = Id "contact"
455+type EmailFilterId = Id "email-filter"
456+type EscalationPolicyId = Id "escalation-policy"
457+type EscalationRuleId = Id "escalation-rule"
458+type IncidentId = Id "incident"
459+type LogEntryId = Id "log-entry"
460+type NoteId = Id "note"
461+type NotificationRuleId = Id "notification-rule"
462+type OverrideId = Id "schedule-override"
463+type RequesterId = Id "requester"
464+type ScheduleId = Id "schedule"
465+type ServiceId = Id "service"
466+type UserId = Id "user"
467+type VendorId = Id "vendor"
468+type WebhookId = Id "webhook"
469+type WindowId = Id "maintenance-window"
470+
471+data Empty = Empty
472+
473+instance ToJSON Empty where
474+ toJSON = const (object [])
475+
476+instance FromJSON Empty where
477+ parseJSON = withObject "empty" f
478+ where
479+ f !o | Map.null o = pure Empty
480+ | otherwise = fail "Unexpected non-empty JSON object."
481+
482+instance QueryLike Empty where
483+ toQuery = const []
484+
485+newtype Address = Address Text
486+ deriving (Eq, Show, IsString)
487+
488+mkAddress :: Text -> Address
489+mkAddress = Address
490+
491+deriveJSON ''Address
492+makePrisms ''Address
493+
494+instance ToByteString Address where
495+ builder (Address a) = builder a
496+
497+instance QueryValues Address
src/Network/PagerDuty/REST.hs+42−30
@@ -2,7 +2,7 @@
22{-# LANGUAGE OverloadedStrings #-}
33
44-- Module : Network.PagerDuty.REST
5−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
5+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
66-- License : This Source Code Form is subject to the terms of
77-- the Mozilla Public License, v. 2.0.
88-- A copy of the MPL can be found in the LICENSE file or
@@ -15,7 +15,11 @@ module Network.PagerDuty.REST
1515 (
1616 -- * Sending requests
1717 send
18+ , sendWith
1819 , paginate
20+ , paginateWith
21+
22+ , module Network.PagerDuty.Types
1923 ) where
2024
2125import Control.Applicative
@@ -23,61 +27,69 @@ import Control.Lens
2327import Control.Monad
2428import Control.Monad.IO.Class
2529import Control.Monad.Trans
26−import Data.Aeson (FromJSON)
30+import Data.Aeson (FromJSON)
2731import Data.Conduit
28−import Data.Default.Class
2932import Data.Monoid
30−import Network.HTTP.Client (Manager)
31−import qualified Network.HTTP.Client as Client
33+import Network.HTTP.Client (Manager)
34+import qualified Network.HTTP.Client as Client
3235import Network.HTTP.Types
33−import Network.PagerDuty.IO
36+import Network.PagerDuty.Internal.IO
37+import Network.PagerDuty.Internal.Types
3438import Network.PagerDuty.Types
3539
36−-- Make the type names consistent, for example:
37−-- Suffix with *Details or *Info for results
38−-- No suffix for requests if necessary
39−
4040-- FIXME: verify correct actions are all paginated
41+-- FIXME: Ensure RequesterId parameter is always most significant param
42+-- FIXME: add smart constructors for all types, for testing purposes
4143
42−-- FIXME: Ensure requesterid parameter is always first
43−
44+-- | /See:/ 'sendWith'
4445send :: (MonadIO m, FromJSON b)
45− => Auth s
46− -> SubDomain
46+ => SubDomain
47+ -> Auth s
4748 -> Manager
4849 -> Request a s b
4950 -> m (Either Error b)
50−send a s m = liftM (fmap fst) . http a s m
51+send d a m = sendWith (prod d a m)
5152
53+sendWith :: (MonadIO m, FromJSON b)
54+ => Env s
55+ -> Request a s b
56+ -> m (Either Error b)
57+sendWith e = liftM (fmap _pgItem) . http e
58+
59+-- | /See:/ 'paginateWith'
5260paginate :: (MonadIO m, Paginate a, FromJSON b)
53− => Auth s
54− -> SubDomain
61+ => SubDomain
62+ -> Auth s
5563 -> Manager
5664 -> Request a s b
5765 -> Source m (Either Error b)
58−paginate a d m = go
66+paginate d a m = paginateWith (prod d a m)
67+
68+paginateWith :: (MonadIO m, Paginate a, FromJSON b)
69+ => Env s
70+ -> Request a s b
71+ -> Source m (Either Error b)
72+paginateWith e = go
5973 where
6074 go rq = do
61− rs <- lift (http a d m rq)
62− yield (fst <$> rs)
75+ rs <- lift (http e rq)
76+ yield (_pgItem <$> rs)
6377 either (const (return ()))
64− (maybe (return ()) go . next rq . snd)
78+ (maybe (return ()) go . next rq . _pgPager)
6579 rs
6680
6781http :: (MonadIO m, FromJSON b)
68− => Auth s
69− -> SubDomain
70− -> Manager
82+ => Env s
7183 -> Request a s b
72− -> m (Either Error (b, Maybe Pager))
73−http a (SubDomain h) m rq = request m rq $ raw
74− { Client.host = h
84+ -> m (Either Error (Page b))
85+http e rq = request (e ^. envManager) (e ^. envLogger) rq $ raw
86+ { Client.host = domain (e ^. envDomain)
7587 , Client.path = renderPath (rq ^. path)
7688 , Client.queryString = renderQuery False (rq ^. query)
7789 }
7890 where
79− raw = case a of
80− AuthBasic u p -> Client.applyBasicAuth u p def
81− AuthToken t -> def
91+ raw = case e ^. envAuth of
92+ AuthBasic u p -> Client.applyBasicAuth u p Client.defaultRequest
93+ AuthToken t -> Client.defaultRequest
8294 { Client.requestHeaders = [("Authorization", "Token token=" <> t)]
8395 }
src/Network/PagerDuty/REST/Alerts.hs+7−7
@@ -4,7 +4,7 @@
44{-# LANGUAGE TypeFamilies #-}
55
66-- Module : Network.PagerDuty.REST.Alerts
7−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
7+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
88-- License : This Source Code Form is subject to the terms of
99-- the Mozilla Public License, v. 2.0.
1010-- A copy of the MPL can be found in the LICENSE file or
@@ -43,12 +43,12 @@ module Network.PagerDuty.REST.Alerts
4343 , alertAddress
4444 ) where
4545
46−import Control.Lens
47−import Data.Aeson.Lens
48−import Data.Time
49−import Network.PagerDuty.REST.Users (User)
50−import Network.PagerDuty.TH
51−import Network.PagerDuty.Types
46+import Control.Lens hiding (Empty)
47+import Data.Aeson.Lens
48+import Data.Time
49+import Network.PagerDuty.Internal.TH
50+import Network.PagerDuty.Internal.Types
51+import Network.PagerDuty.REST.Users (User)
5252
5353alerts :: Path
5454alerts = "alerts"
src/Network/PagerDuty/REST/EscalationPolicies.hs+14−14
@@ -1,13 +1,13 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.EscalationPolicies
10−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -60,15 +60,15 @@ module Network.PagerDuty.REST.EscalationPolicies
6060 , pServices
6161 ) where
6262
63−import Control.Lens
64−import Data.Aeson.Lens
65−import Data.Text (Text)
66−import Network.HTTP.Types
67−import Network.PagerDuty.REST.Services (Service)
68−import Network.PagerDuty.TH
69−import Network.PagerDuty.Types
63+import Control.Lens hiding (Empty)
64+import Data.Aeson.Lens
65+import Data.Text (Text)
66+import Network.HTTP.Types
67+import Network.PagerDuty.Internal.TH
68+import Network.PagerDuty.Internal.Types
69+import Network.PagerDuty.REST.Services (Service)
7070
71−import Network.PagerDuty.REST.EscalationPolicies.EscalationRules
71+import Network.PagerDuty.REST.EscalationPolicies.EscalationRules
7272
7373default (Path)
7474
src/Network/PagerDuty/REST/EscalationPolicies/EscalationRules.hs+11−11
@@ -1,12 +1,12 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
55
66{-# OPTIONS_GHC -fno-warn-type-defaults #-}
77
88-- Module : Network.PagerDuty.REST.EscalationPolicies.EscalationRules
9−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
9+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1010-- License : This Source Code Form is subject to the terms of
1111-- the Mozilla Public License, v. 2.0.
1212-- A copy of the MPL can be found in the LICENSE file or
@@ -64,15 +64,15 @@ module Network.PagerDuty.REST.EscalationPolicies.EscalationRules
6464 , rTargets
6565 ) where
6666
67−import Control.Applicative ((<$>))
68−import Control.Lens hiding ((.=))
67+import Control.Applicative ((<$>))
68+import Control.Lens hiding ((.=))
6969import Data.Aeson
70−import qualified Data.HashMap.Strict as Map
71−import Data.Text (Text)
70+import qualified Data.Aeson.KeyMap as Map
71+import Data.Text (Text)
7272import Network.HTTP.Types
73+import Network.PagerDuty.Internal.TH
74+import Network.PagerDuty.Internal.Types
7375import Network.PagerDuty.REST.Users
74−import Network.PagerDuty.TH
75−import Network.PagerDuty.Types
7676
7777default (Path)
7878
src/Network/PagerDuty/REST/Incidents.hs+23−27
@@ -10,7 +10,7 @@
1010{-# OPTIONS_GHC -fno-warn-type-defaults #-}
1111
1212-- Module : Network.PagerDuty.REST.Incidents
13−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
13+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1414-- License : This Source Code Form is subject to the terms of
1515-- the Mozilla Public License, v. 2.0.
1616-- A copy of the MPL can be found in the LICENSE file or
@@ -129,19 +129,21 @@ module Network.PagerDuty.REST.Incidents
129129 , Incident
130130 ) where
131131
132−import Control.Applicative hiding (empty)
133−import Control.Lens
132+import Control.Applicative hiding (empty)
133+import Control.Lens hiding (Empty)
134134import Data.Aeson
135−import Data.ByteString.Conversion (ToByteString(..), toByteString')
135+import Data.ByteString.Conversion (ToByteString (..),
136+ toByteString')
136137import Data.Default.Class
137−import Data.Monoid hiding (All)
138−import Data.Text (Text)
139−import qualified Data.Text.Encoding as Text
138+import Data.Maybe
139+import Data.Monoid hiding (All)
140+import Data.Text (Text)
141+import qualified Data.Text.Encoding as Text
140142import Data.Time
141143import Network.HTTP.Types
142−import Network.PagerDuty.Query
143−import Network.PagerDuty.TH
144−import Network.PagerDuty.Types
144+import Network.PagerDuty.Internal.Query
145+import Network.PagerDuty.Internal.TH
146+import Network.PagerDuty.Internal.Types
145147
146148default (Path)
147149
@@ -345,13 +347,10 @@ lsUntil = upd.lsUntil'.mapping _D
345347-- | When set, the since and until parameters and defaults are
346348-- ignored. Use this to get all incidents since the account was created.
347349lsDateRange :: Lens' (Request ListIncidents s b) Bool
348−lsDateRange = upd . lens get_ set_
350+lsDateRange = upd.lens get_ (flip set_)
349351 where
350− get_ x
351− | Just All <- _lsDateRange' x = True
352− | otherwise = False
353−
354− set_ l x = l { _lsDateRange' = if x then Just All else Nothing }
352+ get_ = (Just All ==) . view lsDateRange'
353+ set_ x = lsDateRange' .~ listToMaybe [All | x]
355354
356355-- | Returns only the incidents currently in the passed status(es).
357356lsStatus :: Lens' (Request ListIncidents s b) (Maybe [IncidentStatus])
@@ -438,12 +437,12 @@ cSince = upd.cSince'.mapping _D
438437
439438-- | The end of the date range over which you want to search.
440439--
441−-- /Note: If you leave off either since or until, a 30 day default range is
440+-- /Note:/ If you leave off either since or until, a 30 day default range is
442441-- applied to your open ended range. Not including the since parameter will set
443−-- the date range to until - 30 days. Likewise, if you leave off until,
444−-- it is set to since + 30 days.
442+-- the date range to until @-30@ days. Likewise, if you leave off until,
443+-- it is set to since @+30@ days.
445444--
446−-- Defaults to the last 30 days if you leave off both. The size of the date
445+-- /Default:/ The last 30 days if you leave off both. The size of the date
447446-- range must be less than 180 days.
448447cUntil :: Lens' (Request CountIncidents s b) (Maybe UTCTime)
449448cUntil = upd.cUntil'.mapping _D
@@ -451,13 +450,10 @@ cUntil = upd.cUntil'.mapping _D
451450-- | When set, the since and until parameters and defaults are
452451-- ignored. Use this to get all counts since the account was created.
453452cDateRange :: Lens' (Request CountIncidents s b) Bool
454−cDateRange = upd . lens get_ set_
453+cDateRange = upd.lens get_ (flip set_)
455454 where
456− get_ x
457− | Just All <- _cDateRange' x = True
458− | otherwise = False
459−
460− set_ l x = l { _cDateRange' = if x then Just All else Nothing }
455+ get_ = (Just All ==) . view cDateRange'
456+ set_ x = cDateRange' .~ listToMaybe [All | x]
461457
462458-- | Only counts the incidents currently in the passed status(es).
463459cStatus :: Lens' (Request CountIncidents s b) (Maybe [IncidentStatus])
@@ -571,7 +567,7 @@ updateIncidents r = auth updateIncidentsBasic & query .~ [("requester_id", r)]
571567
572568-- | A version of 'updateIncidents' which uses HTTP Basic authentication and
573569-- doesn't require a 'RequesterId'.
574−updateIncidentsBasic :: Request UpdateIncidents Basic [UpdatedIncidents]
570+updateIncidentsBasic :: Request UpdateIncidents 'Basic [UpdatedIncidents]
575571updateIncidentsBasic =
576572 mk UpdateIncidents
577573 { _uiIncidents' = []
src/Network/PagerDuty/REST/Incidents/Notes.hs+12−12
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Incidents.Notes
8−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -36,14 +36,14 @@ module Network.PagerDuty.REST.Incidents.Notes
3636 , nContent
3737 ) where
3838
39−import Control.Lens hiding ((.=))
40−import Data.Aeson
41−import Data.Text (Text)
42−import Data.Time
43−import Network.HTTP.Types
44−import Network.PagerDuty.REST.Users
45−import Network.PagerDuty.TH
46−import Network.PagerDuty.Types
39+import Control.Lens hiding ((.=))
40+import Data.Aeson
41+import Data.Text (Text)
42+import Data.Time
43+import Network.HTTP.Types
44+import Network.PagerDuty.Internal.TH
45+import Network.PagerDuty.Internal.Types
46+import Network.PagerDuty.REST.Users
4747
4848default (Path)
4949
src/Network/PagerDuty/REST/LogEntries.hs+8−9
@@ -5,7 +5,7 @@
55{-# LANGUAGE TypeFamilies #-}
66
77-- Module : Network.PagerDuty.REST.LogEntries
8−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -111,19 +111,18 @@ module Network.PagerDuty.REST.LogEntries
111111 , nAddress
112112 ) where
113113
114−import Control.Applicative
115−import Control.Lens
114+import Control.Lens hiding (Empty)
116115import Data.Aeson
117116import Data.Aeson.Lens
117+import qualified Data.Aeson.KeyMap as Map
118118import Data.Default.Class
119−import qualified Data.HashMap.Strict as Map
120−import Data.Text (Text)
121−import qualified Data.Text as Text
119+import Data.Text (Text)
120+import qualified Data.Text as Text
122121import Data.Time
123122import Network.HTTP.Types
124−import Network.PagerDuty.REST.Users (User)
125−import Network.PagerDuty.TH
126−import Network.PagerDuty.Types
123+import Network.PagerDuty.Internal.TH
124+import Network.PagerDuty.Internal.Types
125+import Network.PagerDuty.REST.Users (User)
127126
128127logs :: Path
129128logs = "log_entries"
src/Network/PagerDuty/REST/MaintenanceWindows.hs+10−10
@@ -4,7 +4,7 @@
44{-# LANGUAGE TypeFamilies #-}
55
66-- Module : Network.PagerDuty.REST.MaintenanceWindows
7−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
7+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
88-- License : This Source Code Form is subject to the terms of
99-- the Mozilla Public License, v. 2.0.
1010-- A copy of the MPL can be found in the LICENSE file or
@@ -74,14 +74,14 @@ module Network.PagerDuty.REST.MaintenanceWindows
7474 , mwServices
7575 ) where
7676
77−import Control.Lens
78−import Data.Monoid
79−import Data.Text (Text)
80−import Data.Time
81−import Network.HTTP.Types
82−import Network.PagerDuty.REST.Users (User)
83−import Network.PagerDuty.TH
84−import Network.PagerDuty.Types
77+import Control.Lens hiding (Empty)
78+import Data.Monoid
79+import Data.Text (Text)
80+import Data.Time
81+import Network.HTTP.Types
82+import Network.PagerDuty.Internal.TH
83+import Network.PagerDuty.Internal.Types
84+import Network.PagerDuty.REST.Users (User)
8585
8686windows :: Path
8787windows = "maintenance_windows"
@@ -214,7 +214,7 @@ createWindow r s e xs =
214214createWindowBasic :: UTCTime -- ^ 'cwStartTime'
215215 -> UTCTime -- ^ 'cwEndTime'
216216 -> [ServiceId] -- ^ 'cwServiceIds'
217− -> Request CreateWindow Basic MaintenanceWindow
217+ -> Request CreateWindow 'Basic MaintenanceWindow
218218createWindowBasic s e xs =
219219 mk CreateWindow
220220 { _cwRequesterId' = Nothing
src/Network/PagerDuty/REST/Reports.hs+11−11
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Reports
10−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -58,11 +58,11 @@ module Network.PagerDuty.REST.Reports
5858 , irNumberOfIncidents
5959 ) where
6060
61−import Control.Lens
62−import Data.Aeson.Lens
63−import Data.Time
64−import Network.PagerDuty.TH
65−import Network.PagerDuty.Types
61+import Control.Lens hiding (Empty)
62+import Data.Aeson.Lens
63+import Data.Time
64+import Network.PagerDuty.Internal.TH
65+import Network.PagerDuty.Internal.Types
6666
6767default (Path)
6868
src/Network/PagerDuty/REST/Schedules.hs+14−14
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Schedules
10−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -110,14 +110,14 @@ module Network.PagerDuty.REST.Schedules
110110 , sFinalSchedule
111111 ) where
112112
113−import Control.Lens hiding ((.=))
114−import Data.Aeson
115−import Data.Text (Text)
116−import Data.Time
117−import Network.HTTP.Types
118−import Network.PagerDuty.REST.Users (User)
119−import Network.PagerDuty.TH
120−import Network.PagerDuty.Types
113+import Control.Lens hiding (Empty, (.=))
114+import Data.Aeson
115+import Data.Text (Text)
116+import Data.Time
117+import Network.HTTP.Types
118+import Network.PagerDuty.Internal.TH
119+import Network.PagerDuty.Internal.Types
120+import Network.PagerDuty.REST.Users (User)
121121
122122default (Path)
123123
src/Network/PagerDuty/REST/Schedules/Overrides.hs+12−12
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Schedules
10−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -50,12 +50,12 @@ module Network.PagerDuty.REST.Schedules.Overrides
5050 , oUser
5151 ) where
5252
53−import Control.Lens
54−import Data.Time
55−import Network.HTTP.Types
56−import Network.PagerDuty.REST.Users
57−import Network.PagerDuty.TH
58−import Network.PagerDuty.Types
53+import Control.Lens
54+import Data.Time
55+import Network.HTTP.Types
56+import Network.PagerDuty.Internal.TH
57+import Network.PagerDuty.Internal.Types
58+import Network.PagerDuty.REST.Users
5959
6060overrides :: ScheduleId -> Path
6161overrides i = "schedules" % i % "overrides"
src/Network/PagerDuty/REST/Services.hs+16−16
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Services
10−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -106,14 +106,14 @@ module Network.PagerDuty.REST.Services
106106 , svcSeverityFilter
107107 ) where
108108
109−import Control.Lens
110−import Data.Aeson.Lens
111−import Data.Text (Text)
112−import Data.Time
113−import Network.HTTP.Types
114−import Network.PagerDuty.REST.Services.EmailFilters
115−import Network.PagerDuty.TH
116−import Network.PagerDuty.Types
109+import Control.Lens hiding (Empty)
110+import Data.Aeson.Lens
111+import Data.Text (Text)
112+import Data.Time
113+import Network.HTTP.Types
114+import Network.PagerDuty.Internal.TH
115+import Network.PagerDuty.Internal.Types
116+import Network.PagerDuty.REST.Services.EmailFilters
117117
118118default (Path)
119119
@@ -483,7 +483,7 @@ enableService r i =
483483
484484-- | A version of 'enableService' which uses HTTP Basic authentication and
485485-- doesn't require a 'RequesterId'.
486−enableServiceBasic :: ServiceId -> Request Empty Basic Empty
486+enableServiceBasic :: ServiceId -> Request Empty 'Basic Empty
487487enableServiceBasic i = empty & meth .~ PUT & path .~ services % i % "enable"
488488
489489-- | Disable a service. Once a service is disabled, it will not be able to
@@ -498,7 +498,7 @@ disableService r i =
498498
499499-- | A version of 'disableService' which uses HTTP Basic authentication and
500500-- doesn't require a 'RequesterId'.
501−disableServiceBasic :: ServiceId -> Request Empty Basic Empty
501+disableServiceBasic :: ServiceId -> Request Empty 'Basic Empty
502502disableServiceBasic i = empty & meth .~ PUT & path .~ services % i % "disable"
503503
504504-- | Regenerate a new service key for an existing service.
src/Network/PagerDuty/REST/Services/EmailFilters.hs+14−14
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Services.EmailFilters
8−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -39,15 +39,15 @@ module Network.PagerDuty.REST.Services.EmailFilters
3939 , efId
4040 ) where
4141
42−import Control.Applicative hiding (empty)
43−import Control.Lens hiding ((.=))
44−import Data.Aeson
45−import Data.Default.Class
46−import Data.Monoid
47−import Data.Text (Text)
48−import Network.HTTP.Types
49−import Network.PagerDuty.TH
50−import Network.PagerDuty.Types
42+import Control.Applicative hiding (empty)
43+import Control.Lens hiding ((.=))
44+import Data.Aeson
45+import Data.Default.Class
46+import Data.Monoid
47+import Data.Text (Text)
48+import Network.HTTP.Types
49+import Network.PagerDuty.Internal.TH
50+import Network.PagerDuty.Internal.Types
5151
5252default (Path)
5353
@@ -65,7 +65,7 @@ deriveNullaryWith hyphenated ''MatchMode
6565-- FIXME: Tighten up this type! Make the regex required for match/no-match and
6666-- encode the conditional invariants.
6767data EmailFilterInfo = EmailFilterInfo
68− { _efSubjectMode' :: Maybe MatchMode
68+ { _efSubjectMode' :: Maybe MatchMode
6969 , _efSubjectRegex' :: Maybe Text
7070 , _efBodyMode' :: Maybe MatchMode
7171 , _efBodyRegex' :: Maybe Text
src/Network/PagerDuty/REST/Users.hs+17−17
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Users
10−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -81,16 +81,16 @@ module Network.PagerDuty.REST.Users
8181 , uJobTitle
8282 ) where
8383
84−import Control.Applicative hiding (empty)
85−import Control.Lens hiding ((.=))
86−import Data.Aeson
87−import Data.Default.Class
88−import Data.Monoid
89−import Data.Text (Text)
90−import Data.Time
91−import Network.HTTP.Types
92−import Network.PagerDuty.TH
93−import Network.PagerDuty.Types
84+import Control.Applicative hiding (empty)
85+import Control.Lens hiding (Empty, (.=))
86+import Data.Aeson
87+import Data.Default.Class
88+import Data.Monoid
89+import Data.Text (Text)
90+import Data.Time
91+import Network.HTTP.Types
92+import Network.PagerDuty.Internal.TH
93+import Network.PagerDuty.Internal.Types
9494
9595default (Path)
9696
@@ -315,7 +315,7 @@ createUser r n e = auth (createUserBasic n e) & query .~ [("requester_id", r)]
315315-- doesn't require a 'RequesterId'.
316316createUserBasic :: Text -- ^ 'cuName'
317317 -> Address -- ^ 'cuEmail'
318− -> Request CreateUser Basic User
318+ -> Request CreateUser 'Basic User
319319createUserBasic n e =
320320 mk CreateUser
321321 { _cuName' = n
src/Network/PagerDuty/REST/Users/ContactMethods.hs+10−10
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Users.ContactMethods
8−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -56,12 +56,12 @@ module Network.PagerDuty.REST.Users.ContactMethods
5656 , Contact
5757 ) where
5858
59−import Control.Lens
60−import Data.Aeson.Lens
61−import Data.Text (Text)
62−import Network.HTTP.Types
63−import Network.PagerDuty.TH
64−import Network.PagerDuty.Types
59+import Control.Lens
60+import Data.Aeson.Lens
61+import Data.Text (Text)
62+import Network.HTTP.Types
63+import Network.PagerDuty.Internal.TH
64+import Network.PagerDuty.Internal.Types
6565
6666default (Path)
6767
src/Network/PagerDuty/REST/Users/NotificationRules.hs+10−10
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Users.NotificationRules
8−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -51,12 +51,12 @@ module Network.PagerDuty.REST.Users.NotificationRules
5151 , rContactMethod
5252 ) where
5353
54−import Control.Lens
55−import Data.Aeson.Lens
56−import Network.HTTP.Types
57−import Network.PagerDuty.REST.Users.ContactMethods
58−import Network.PagerDuty.TH
59−import Network.PagerDuty.Types
54+import Control.Lens
55+import Data.Aeson.Lens
56+import Network.HTTP.Types
57+import Network.PagerDuty.Internal.TH
58+import Network.PagerDuty.Internal.Types
59+import Network.PagerDuty.REST.Users.ContactMethods
6060
6161default (Path)
6262
src/Network/PagerDuty/REST/Webhooks.hs+5−4
@@ -3,7 +3,7 @@
33{-# LANGUAGE TemplateHaskell #-}
44
55-- Module : Network.PagerDuty.REST.Webhooks
6−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
6+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
77-- License : This Source Code Form is subject to the terms of
88-- the Mozilla Public License, v. 2.0.
99-- A copy of the MPL can be found in the LICENSE file or
@@ -35,13 +35,14 @@ module Network.PagerDuty.REST.Webhooks
3535import Control.Applicative hiding (empty)
3636import Control.Lens
3737import Data.Aeson
38−import Data.ByteString.Conversion (ToByteString(..), toByteString')
38+import Data.ByteString.Conversion (ToByteString (..),
39+ toByteString')
3940import Data.Text (Text)
4041import qualified Data.Text.Encoding as Text
4142import Data.Time
43+import Network.PagerDuty.Internal.TH
44+import Network.PagerDuty.Internal.Types
4245import Network.PagerDuty.REST.Incidents
43−import Network.PagerDuty.TH
44−import Network.PagerDuty.Types
4546
4647data WebhookType
4748 = WTrigger
src/Network/PagerDuty/Types.hs+84−432
@@ -1,19 +1,5 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE FlexibleInstances #-}
4−{-# LANGUAGE GADTs #-}
5−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6−{-# LANGUAGE KindSignatures #-}
7−{-# LANGUAGE OverloadedStrings #-}
8−{-# LANGUAGE PatternSynonyms #-}
9−{-# LANGUAGE RankNTypes #-}
10−{-# LANGUAGE StandaloneDeriving #-}
11−{-# LANGUAGE TemplateHaskell #-}
12−{-# LANGUAGE TupleSections #-}
13−{-# LANGUAGE ViewPatterns #-}
14−
151-- Module : Network.PagerDuty.Types
16−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
2+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
173-- License : This Source Code Form is subject to the terms of
184-- the Mozilla Public License, v. 2.0.
195-- A copy of the MPL can be found in the LICENSE file or
@@ -22,420 +8,86 @@
228-- Stability : experimental
239-- Portability : non-portable (GHC extensions)
2410
25−module Network.PagerDuty.Types where
26− -- (
27− -- -- * Requests
28− -- Auth (..)
29− -- , Cred (..)
30− -- , Domain (..)
31−
32− -- , Request (..)
33− -- , Request'
34−
35− -- , Paginate (..)
36−
37− -- -- * Errors
38− -- , Code (..)
39− -- , message
40− -- , RestError (..)
41− -- , Error (..)
42−
43− -- -- * Primitives
44− -- , Key (..)
45− -- , ServiceKey
46− -- , IncidentKey
47−
48− -- , Id (..)
49− -- , ServiceId
50− -- , RequesterId
51−
52− -- , Empty (..)
53− -- ) where
54−
55−import Control.Applicative
56−import Control.Lens hiding ((.=))
57−import Data.Aeson hiding (Error)
58−import Data.Aeson.Types (Parser)
59−import Data.ByteString (ByteString)
60−import qualified Data.ByteString.Char8 as BS
61−import Data.ByteString.Conversion hiding (List)
62−import Data.Default.Class
63−import Data.Function (on)
64−import qualified Data.HashMap.Strict as Map
65−import Data.List (deleteBy, intersperse)
66−import Data.Monoid
67−import Data.String
68−import Data.Text (Text)
69−import qualified Data.Text as Text
70−import qualified Data.Text.Encoding as Text
71−import Data.Time
72−import GHC.TypeLits
73−import Network.HTTP.Types
74−import Network.HTTP.Types.QueryLike
75−import Network.PagerDuty.Query
76−import Network.PagerDuty.TH
77−import System.Locale
78−
79−-- FIXME: Verify IncidentId/IncidentKey .. *Id/*Key are actually different or needed
80−
81−newtype CSV a = CSV [a]
82− deriving (Eq, Show, Monoid)
83−
84−makePrisms ''CSV
85−
86−instance ToByteString a => QueryValues (CSV a)
87−
88−instance ToByteString a => ToByteString (CSV a) where
89− builder (CSV xs) = mconcat . intersperse "," $ map builder xs
90−
91−instance FromJSON a => FromJSON (CSV a) where
92− parseJSON = withText "comma_separated_value" $
93− fmap CSV . traverse (parseJSON . String) . Text.split (== ',')
94−
95−instance ToByteString a => ToJSON (CSV a) where
96− toJSON = String . Text.decodeUtf8 . toByteString'
97−
98−newtype List a = L [a]
99− deriving (Eq, Show, Monoid)
100−
101−deriveJSON ''List
102−makePrisms ''List
103−
104−instance QueryValues a => QueryValues (List a) where
105− queryValues (L xs) = concatMap queryValues xs
106−
107−newtype Bool' = B Bool
108− deriving (Eq, Show)
109−
110−deriveJSON ''Bool'
111−makePrisms ''Bool'
112−
113−instance ToByteString Bool' where
114− builder (B True) = "true"
115− builder (B False) = "false"
116−
117−instance QueryValues Bool'
118−
119−pattern T = B True
120−pattern F = B False
121−
122−newtype Date = D UTCTime
123− deriving (Eq, Ord, Show)
124−
125−makePrisms ''Date
126−
127−instance FromJSON Date where
128− parseJSON = fmap D . parseJSON
129−
130−instance ToJSON Date where
131− toJSON (D d) = toJSON d
132−
133−instance ToByteString Date where
134− builder (D d) = builder
135− (formatTime defaultTimeLocale (iso8601DateFormat $ Just "%XZ") d)
136−
137−instance QueryValues Date
138−
139−newtype TZ = TZ TimeZone
140− deriving (Eq, Show)
141−
142−makePrisms ''TZ
143−
144−instance FromJSON TZ where
145− parseJSON = undefined
146−
147−instance ToJSON TZ where
148− toJSON = toJSON . Text.decodeUtf8 . toByteString'
149−
150−instance ToByteString TZ where
151− builder (TZ tz) = builder (timeZoneName tz)
152−
153−instance QueryValues TZ
154−
155−instance Default TZ where
156− def = TZ utc
157−
158−data Security = Basic | Token
159− deriving (Eq, Show)
160−
161−data Auth (a :: Security) where
162− AuthBasic :: ByteString -> ByteString -> Auth Basic
163− AuthToken :: ByteString -> Auth Token
164−
165−deriving instance Eq (Auth a)
166−deriving instance Show (Auth a)
167−
168−newtype SubDomain = SubDomain ByteString
169− deriving (Eq, Show, IsString)
170−
171−domain :: SubDomain -> ByteString
172−domain (SubDomain s)
173− | base `BS.isSuffixOf` s = s
174− | otherwise = s <> base
175− where
176− base = ".pagerduty.com"
177−
178−newtype Code = Code Integer
179− deriving (Eq, Show)
180−
181−deriveJSON ''Code
182−
183−description :: Code -> Text
184−description (Code c) =
185− case c of
186− 2000 -> "Internal Error"
187− 2001 -> "Invalid Input Provided"
188− 2002 -> "Arguments Caused Error"
189− 2003 -> "Missing Arguments"
190− 2004 -> "Invalid 'since' or 'until' Parameter Values"
191− 2005 -> "Invalid Query Date Range"
192− 2006 -> "Authentication Failed"
193− 2007 -> "Account Not Found"
194− 2008 -> "Account Locked"
195− 2009 -> "Only HTTPS Allowed For This Call"
196− 2010 -> "Access Denied"
197− 2011 -> "The action requires a 'requester_id' to be specified"
198− 2012 -> "Your account is expired and cannot use the API"
199− _ -> "Unrecognised error code"
200−
201−data IntegrationError = IntegrationError
202− { _ieStatus :: Text
203− , _ieMessage :: Text
204− , _ieErrors :: [Text]
205− } deriving (Eq, Show)
206−
207−deriveRecord ''IntegrationError
208−
209−data RestError = RestError
210− { _reCode :: Code
211− , _reMessage :: Text
212− , _reErrors :: [Text]
213− } deriving (Eq, Show)
214−
215−deriveRecord ''RestError
216−
217−data Error
218− = Internal String
219− | Integration IntegrationError
220− | Rest RestError
221− deriving (Eq, Show)
222−
223−instance FromJSON Error where
224− parseJSON o = (Rest <$> parseJSON o)
225− <|> (Integration <$> parseJSON o)
226−
227−makePrisms ''Error
228−
229−data Pager = Pager
230− { _pgOffset :: !Int
231− -- ^ The offset used in the execution of the query.
232− , _pgLimit :: !Int
233− -- ^ The limit used in the execution of the query.
234− , _pgTotal :: !Int
235− -- ^ The total number of records available.
236− , _pgQuery :: Maybe Text
237− -- ^ An optional query= value to be added to the query string.
238− } deriving (Eq, Show)
239−
240−makeLenses ''Pager
241−
242−instance FromJSON a => FromJSON (a, Maybe Pager) where
243− parseJSON = withObject "paginated" $ \o -> (,)
244− <$> parseJSON (Object o)
245− <*> optional (parse o)
246− where
247− parse o = Pager
248− -- The offset of the first record returned.
249− -- Default is 0.
250− <$> o .: "offset" .!= 0
251− -- The number of records returned.
252− -- Default (and max limit) is 100 for most APIs.
253− <*> o .: "limit" .!= 100
254− <*> o .: "total"
255− <*> o .:? "query"
256−
257−instance ToJSON Pager where
258− toJSON p = object
259− [ "offset" .= _pgOffset p
260− , "limit" .= _pgLimit p
261− ]
262−
263−-- | A path segment.
264−data Path where
265− Path :: Path
266− Seg :: ToByteString a => a -> Path
267−
268−instance Monoid Path where
269− mempty = Path
270− mappend x Path = x
271− mappend Path y = y
272− mappend (Seg x) (Seg y) = Seg (builder x <> "/" <> builder y)
273−
274−instance IsString Path where
275− fromString = Seg
276−
277−instance ToByteString Path where
278− builder Path = mempty
279− builder (Seg x) = builder x
280−
281−(%) :: ToByteString a => Path -> a -> Path
282−a % b = a <> Seg b
283−
284−renderPath :: Path -> ByteString
285−renderPath = toByteString' . mappend v1
286− where
287− v1 :: Path
288− v1 = "/api/v1"
289−
290−data Request a (s :: Security) b where
291− Request :: (QueryLike a, ToJSON a)
292− => { _rqMeth :: !StdMethod
293− , _rqPath :: Path
294− , _rqQuery :: Query
295− , _rqBody :: a
296− , _rqPager :: Maybe Pager
297− , _rqUnwrap :: Value -> Parser Value
298− }
299− -> Request a s b
300−
301−instance ToJSON (Request a s b) where
302− -- Manually unwrapped to ensure GADT constraint holds.
303− toJSON (Request _ _ _ b p _) = Object $
304− let Object x = toJSON b
305− in case toJSON p of
306− (Object y) -> x <> y
307− _ -> x
308−
309−type Unwrap = Getting (First Value) Value Value
310−
311−-- | Create a defaulted request from the payload type.
312−mk :: (QueryLike a, ToJSON a) => a -> Request a s b
313−mk x = Request GET mempty mempty x Nothing pure
314−
315−empty :: Request Empty s r
316−empty = mk Empty
317−
318−-- | Lens into the body of a request.
319−upd :: (QueryLike a, ToJSON a) => Lens' (Request a s b) a
320−upd = lens _rqBody (\(Request m p q _ g u) x -> Request m p q x g u)
321−
322−-- | Drop the security constraint.
323−auth :: Request a s b -> Request a t b
324−auth (Request x m p q g u) = Request x m p q g u
325−
326−meth :: Lens' (Request a s b) StdMethod
327−meth = lens _rqMeth (\r x -> r { _rqMeth = x })
328−
329−path :: Lens' (Request a s b) Path
330−path = lens _rqPath (\r x -> r { _rqPath = x })
331−
332−query :: QueryValueLike v
333− => Lens (Request a s b) (Request a s b) Query [(ByteString, v)]
334−query = lens _rqQuery (\r x -> r { _rqQuery = toQuery x })
335−
336−pager :: Lens' (Request a s b) (Maybe Pager)
337−pager = lens _rqPager (\r x -> r { _rqPager = x })
338−
339−unwrap :: Setter (Request a s b) (Request a s b) (Value -> Parser Value) Unwrap
340−unwrap f r = f (_rqUnwrap r) <&> \k -> r { _rqUnwrap = g k }
341− where
342− g k x = maybe (fail "Failed to extract nested keys.") return (x ^? k)
343−
344−-- | Exists primarily to obtain a constraint for the 'paginate' function.
345−class Paginate a where
346− next :: Request a s b -> Maybe Pager -> Maybe (Request a s b)
347− next rq = maybe Nothing go
348− where
349− go x | x^.pgTotal == 0 = Nothing
350− | otherwise = Just $
351− rq & pager ?~ (x & pgOffset +~ x^.pgTotal)
352− & query %~ (add . clear)
353− where
354− add :: Query -> Query
355− add = maybe id ((:) . (k,) . Just . Text.encodeUtf8) (x^.pgQuery)
356−
357− clear :: Query -> Query
358− clear = deleteBy ((==) `on` fst) (k, Nothing)
359−
360− k :: ByteString
361− k = "query"
362−
363−newtype Key (a :: Symbol) = Key Text
364− deriving (Eq, Show, IsString)
365−
366−instance FromJSON (Key a) where
367− parseJSON = withText "key" (return . Key)
368−
369−instance ToJSON (Key a) where
370− toJSON (Key k) = toJSON k
371−
372−instance ToByteString (Key a) where
373− builder (Key k) = builder k
374−
375−instance QueryValues (Key a)
376−
377−instance QueryValueLike (Key a) where
378− toQueryValue = Just . toByteString'
379−
380−type ServiceKey = Key "service"
381−type IncidentKey = Key "incident"
382−
383−newtype Id (a :: Symbol) = Id Text
384− deriving (Eq, Show, IsString)
385−
386−instance FromJSON (Id a) where
387− parseJSON = withText "id" (return . Id)
388−
389−instance ToJSON (Id a) where
390− toJSON (Id i) = toJSON i
391−
392−instance ToByteString (Id a) where
393− builder (Id i) = builder i
394−
395−instance QueryValues (Id a)
396−
397−instance QueryValueLike (Id a) where
398− toQueryValue = Just . toByteString'
399−
400−type AlertId = Id "alert"
401−type ContactId = Id "contact"
402−type EmailFilterId = Id "email-filter"
403−type EscalationPolicyId = Id "escalation-policy"
404−type EscalationRuleId = Id "escalation-rule"
405−type IncidentId = Id "incident"
406−type LogEntryId = Id "log-entry"
407−type NoteId = Id "note"
408−type NotificationRuleId = Id "notification-rule"
409−type OverrideId = Id "schedule-override"
410−type RequesterId = Id "requester"
411−type ScheduleId = Id "schedule"
412−type ServiceId = Id "service"
413−type UserId = Id "user"
414−type VendorId = Id "vendor"
415−type WebhookId = Id "webhook"
416−type WindowId = Id "maintenance-window"
417−
418−data Empty = Empty
419−
420−instance ToJSON Empty where
421− toJSON = const (object [])
422−
423−instance FromJSON Empty where
424− parseJSON = withObject "empty" f
425− where
426− f !o | Map.null o = pure Empty
427− | otherwise = fail "Unexpected non-empty JSON object."
428−
429−instance QueryLike Empty where
430− toQuery = const []
431−
432−newtype Address = Address Text
433− deriving (Eq, Show)
434−
435−deriveJSON ''Address
436−makePrisms ''Address
437−
438−instance ToByteString Address where
439− builder (Address a) = builder a
440−
441−instance QueryValues Address
11+module Network.PagerDuty.Types
12+ (
13+ -- * Configuration
14+ -- ** Environment
15+ Env
16+ , envDomain
17+ , envAuth
18+ , envManager
19+ , envLogger
20+
21+ -- ** Logging
22+ , Logger (..)
23+ , debug
24+
25+ -- * Types
26+ -- ** Requests
27+ , Paginate
28+ , Request
29+
30+ -- ** Errors
31+ , Error
32+ , _Internal
33+ , _Integration
34+ , _REST
35+ -- *** Messages
36+ , HasMessage (..)
37+ -- *** Fields
38+ , HasErrors (..)
39+ -- *** Integration
40+ , IntegrationError
41+ , status
42+ -- *** REST
43+ , RESTError
44+ , Code
45+ , code
46+ , description
47+
48+ -- ** Authentication
49+ , Security (..)
50+ , Auth (..)
51+
52+ -- ** Keys
53+ , Key
54+ , mkKey
55+ -- *** Aliases
56+ , ServiceKey
57+ , IncidentKey
58+
59+ -- ** Identifiers
60+ , Id
61+ , mkId
62+ -- *** Aliases
63+ , AlertId
64+ , ContactId
65+ , EmailFilterId
66+ , EscalationPolicyId
67+ , EscalationRuleId
68+ , IncidentId
69+ , LogEntryId
70+ , NoteId
71+ , NotificationRuleId
72+ , OverrideId
73+ , RequesterId
74+ , ScheduleId
75+ , ServiceId
76+ , UserId
77+ , VendorId
78+ , WebhookId
79+ , WindowId
80+
81+ -- ** SubDomain
82+ , SubDomain
83+ , mkSubDomain
84+
85+ -- ** Address
86+ , Address
87+ , mkAddress
88+
89+ -- ** Miscellaneous
90+ , Empty (..)
91+ ) where
92+
93+import Network.PagerDuty.Internal.Types
stack.yamlnew file+7
@@ -0,0 +1,7 @@
1+resolver: lts-19.23
2+
3+packages:
4+- .
5+
6+nix:
7+ packages: [zlib]