git.iko.soy/typeable/pagerduty
on develop help sign in
40 files changed+1922−1833
since splitsnapshots
unifiedsplit
.gitignore+1 .travis.yml+30 Makefile−17 README.md+14 pagerduty.cabal+59−49 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/API/Integration.hs−77 src/Network/PagerDuty/API/LogEntries.hs−28 src/Network/PagerDuty/API/MaintenanceWindows.hs−232 src/Network/PagerDuty/API/Services.hs−292 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+25−25 src/Network/PagerDuty/REST/EscalationPolicies.hs+21−21 src/Network/PagerDuty/REST/EscalationPolicies/EscalationRules.hs+21−20 src/Network/PagerDuty/REST/Incidents.hs+135−122 src/Network/PagerDuty/REST/Incidents/Notes.hs+12−12 src/Network/PagerDuty/REST/LogEntries.hs+10−11 src/Network/PagerDuty/REST/MaintenanceWindows.hs+10−10 src/Network/PagerDuty/REST/Reports.hs+11−12 src/Network/PagerDuty/REST/Schedules.hs+16−17 src/Network/PagerDuty/REST/Schedules/Overrides.hs+12−12 src/Network/PagerDuty/REST/Services.hs+24−24 src/Network/PagerDuty/REST/Services/EmailFilters.hs+14−14 src/Network/PagerDuty/REST/Users.hs+29−28 src/Network/PagerDuty/REST/Users/ContactMethods.hs+213−12 src/Network/PagerDuty/REST/Users/NotificationRules.hs+141−12 src/Network/PagerDuty/REST/Webhooks.hs+89−5 src/Network/PagerDuty/Types.hs+84−429 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−17
@@ -1,17 +0,0 @@
1−FLAGS := -j --disable-documentation --disable-library-coverage
2−
3−build:
4− cabal build $(addprefix -,$(findstring j,$(MAKEFLAGS)))
5−
6−install: cabal.sandbox.config
7− cabal install $(FLAGS) --only-dependencies
8−
9−clean:
10− cabal clean
11− rm -rf cabal.sandbox.config .cabal-sandbox
12−
13−doc:
14− cabal haddock
15−
16−cabal.sandbox.config:
17− 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+59−49
@@ -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
@@ -32,56 +43,55 @@ library
3243
3344 exposed-modules:
3445 Control.Monad.Trans.PagerDuty
35− -- , Network.PagerDuty.Integration
36− -- , Network.PagerDuty.REST
37− -- , Network.PagerDuty.REST.Alerts
38− -- , Network.PagerDuty.REST.EscalationPolicies
39−-- , Network.PagerDuty.REST.EscalationPolicies.EscalationRules
40− -- , Network.PagerDuty.REST.Incidents
41− -- , Network.PagerDuty.REST.Incidents.Notes
42− -- , Network.PagerDuty.REST.LogEntries
43− -- , Network.PagerDuty.REST.MaintenanceWindows
44− -- , Network.PagerDuty.REST.Reports
45− -- , Network.PagerDuty.REST.Schedules
46−-- , Network.PagerDuty.REST.Schedules.Overrides
47− -- , Network.PagerDuty.REST.Services
48−-- , Network.PagerDuty.REST.Services.EmailFilters
49−-- , Network.PagerDuty.REST.Users
46+ , Network.PagerDuty.Integration
47+ , Network.PagerDuty.REST
48+ , Network.PagerDuty.REST.Alerts
49+ , Network.PagerDuty.REST.EscalationPolicies
50+ , Network.PagerDuty.REST.EscalationPolicies.EscalationRules
51+ , Network.PagerDuty.REST.Incidents
52+ , Network.PagerDuty.REST.Incidents.Notes
53+ , Network.PagerDuty.REST.LogEntries
54+ , Network.PagerDuty.REST.MaintenanceWindows
55+ , Network.PagerDuty.REST.Reports
56+ , Network.PagerDuty.REST.Schedules
57+ , Network.PagerDuty.REST.Schedules.Overrides
58+ , Network.PagerDuty.REST.Services
59+ , Network.PagerDuty.REST.Services.EmailFilters
60+ , Network.PagerDuty.REST.Users
5061 , Network.PagerDuty.REST.Users.ContactMethods
5162 , Network.PagerDuty.REST.Users.NotificationRules
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 && <= 8.0
63− , base >= 4.5 && < 5.0
64−-- , base64-bytestring >= 1.0 && < 1.1
65− , bifunctors
66−
67− , bytestring >= 0.9 && < 1.0
74+ aeson >= 2.0
75+ , base >= 4.7 && < 5
76+ , bifunctors >= 4.1
77+ , bytestring >= 0.9
6878 , bytestring-conversion >= 0.2.1
69− , conduit >= 0.5.5
70− , data-default >= 0.5
79+ , conduit > 1.1
80+ , data-default-class >= 0.0.1
7181 , exceptions >= 0.6
72− , http-client >= 0.3.6 && < 0.5
73− , http-types >= 0.8 && < 1.0
74− , lens >= 4.0 && < 5.0
75− , lens-aeson >= 1.0
76− , mmorph >= 1.0
77− , mtl >= 2.2.1 && < 3.0
78− , old-locale
79− , text >= 1.1 && < 2.0
80− , time == 1.4.*
81− , transformers >= 0.4.1 && < 0.5
82+ , generics-sop >= 0.5.0.0
83+ , http-client >= 0.5 && < 1
84+ , http-types >= 0.8
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
91+ , text >= 1.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
8297 , unordered-containers >= 0.2.3
83−
84− , generics-sop
85− , monad-control
86− , template-haskell
87− , 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/API/Integration.hsdeleted−77
@@ -1,77 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−-- Module : Network.PagerDuty.Integration
6−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
7−-- License : This Source Code Form is subject to the terms of
8−-- the Mozilla Public License, v. 2.0.
9−-- A copy of the MPL can be found in the LICENSE file or
10−-- you can obtain it at http://mozilla.org/MPL/2.0/.
11−-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
12−-- Stability : experimental
13−-- Portability : non-portable (GHC extensions)
14−
15−-- | The "Integration API"
16−--
17−-- <http://developer.pagerduty.com/documentation/integration/events>
18−--
19−module Network.PagerDuty.API.Integration
20− ( Event (..)
21− , submitEvent
22−
23− -- * Re-exported
24− , ServiceKey
25− , IncidentKey
26− ) where
27−
28−import Control.Applicative
29−import Data.Aeson
30−import Data.Maybe (catMaybes)
31−import Data.Text (Text)
32−import GHC.Generics
33−import Network.PagerDuty.IO
34−import Network.PagerDuty.Types
35−
36−submitEvent :: Event -> PagerDuty a (Either Error IncidentKey)
37−submitEvent = fmap (fmap incident_key) . request defaultRequest
38− { method = methodPost
39− , host = "events.pagerduty.com"
40− , path = "/generic/2010-04-15/create_event.json"
41− }
42−
43−data Event
44− = Trigger !ServiceKey !(Maybe IncidentKey) !Text !(Maybe Object)
45− | Acknowledge !ServiceKey !IncidentKey !(Maybe Text) !(Maybe Object)
46− | Resolve !ServiceKey !IncidentKey !(Maybe Text) !(Maybe Object)
47− deriving (Eq, Show)
48−
49−instance ToJSON Event where
50− toJSON (Trigger svc minc desc mdets) =
51− jsonEvent "trigger" svc minc (Just desc) mdets
52− toJSON (Acknowledge svc inc mdesc mdets) =
53− jsonEvent "acknowledge" svc (Just inc) mdesc mdets
54− toJSON (Resolve svc inc mdesc mdets) =
55− jsonEvent "resolve" svc (Just inc) mdesc mdets
56−
57−jsonEvent :: Text
58− -> ServiceKey
59− -> Maybe IncidentKey
60− -> Maybe Text
61− -> Maybe Object
62− -> Value
63−jsonEvent typ skey ikey desc dets = object $ catMaybes
64− [ Just $ "event_type" .= typ
65− , Just $ "service_key" .= skey
66− , ("incident_key" .=) <$> ikey
67− , ("description" .=) <$> desc
68− , ("details" .=) <$> dets
69− ]
70−
71−data EventResponse = ER
72− { status :: !Text
73− , incident_key :: !IncidentKey
74− , message :: !Text
75− } deriving (Show, Generic)
76−
77−instance FromJSON EventResponse
src/Network/PagerDuty/API/LogEntries.hsdeleted−28
@@ -1,28 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−
3−-- Module : Network.PagerDuty.API.LogEntries
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.API.LogEntries where
14−
15−import Data.Aeson
16−import GHC.Generics
17−import Network.PagerDuty.Types
18−
19−data LogEntries = LogEntries
20− { lesTotal :: !Int
21− , leslogEntries :: [LogEntry]
22− } deriving (Eq, Show, Generic)
23−
24−instance FromJSON LogEntries
25−instance ToJSON LogEntries
26−
27−logEntries :: PagerDuty Authenticated (Either Error LogEntries)
28−logEntries = undefined
src/Network/PagerDuty/API/MaintenanceWindows.hsdeleted−232
@@ -1,232 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−
4−-- Module : Network.PagerDuty.API.MaintenanceWindows
5−-- Copyright : (c) 2013-2014 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.API.MaintenanceWindows
15− ( CreateMaintenanceWindow (..)
16− , MaintenanceWindowCounts (..)
17− , MaintenanceWindowCreatorDetails (..)
18− , MaintenanceWindowCreatorId
19− , MaintenanceWindowDetails (..)
20− , MaintenanceWindowFilter (..)
21− , MaintenanceWindowId
22− , ServiceInfo (..)
23− , UpdateMaintenanceWindow (..)
24−
25− , createMaintenanceWindow
26− , createMaintenanceWindow'
27− , updateMaintenanceWindow
28− , listMaintenanceWindows
29− , getMaintenanceWindow
30− , deleteMaintenaceWindow
31− ) where
32−
33−import Control.Applicative
34−import Data.Aeson
35−import Data.ByteString (ByteString)
36−import Data.Maybe
37−import Data.Monoid
38−import Data.Text (Text)
39−import qualified Data.Text as T
40−import Data.Text.Encoding
41−import Data.Time (UTCTime)
42−import GHC.Generics
43−import Network.PagerDuty.Internal
44−import Network.PagerDuty.IO
45−import Network.PagerDuty.Types
46−
47−type A a = Authenticated a
48−
49−bASE_PATH :: ByteString
50−bASE_PATH = "/api/v1/maintenance_windows/"
51−
52−createMaintenanceWindow :: CreateMaintenanceWindow
53− -> RequesterId
54− -> PagerDuty (A Token) (Either Error MaintenanceWindowDetails)
55−createMaintenanceWindow mw rid =
56− fmap (fmap dr_maintenance_window)
57− . request defaultRequest
58− { method = methodPost
59− , path = bASE_PATH
60− }
61− $ CreateMaintenanceWindowRequest
62− { cmwr_maintenance_window = mw
63− , cmwr_requester_id = Just rid
64− }
65−
66−createMaintenanceWindow' :: CreateMaintenanceWindow
67− -> PagerDuty (A BasicAuth) (Either Error MaintenanceWindowDetails)
68−createMaintenanceWindow' mw =
69− fmap (fmap dr_maintenance_window)
70− . request defaultRequest
71− { method = methodPost
72− , path = bASE_PATH
73− }
74− $ CreateMaintenanceWindowRequest
75− { cmwr_maintenance_window = mw
76− , cmwr_requester_id = Nothing
77− }
78−
79−updateMaintenanceWindow :: MaintenanceWindowId
80− -> UpdateMaintenanceWindow
81− -> PagerDuty (A a) (Either Error MaintenanceWindowDetails)
82−updateMaintenanceWindow (Id mwid) =
83− fmap (fmap dr_maintenance_window)
84− . request defaultRequest
85− { method = methodPut
86− , path = bASE_PATH <> encodeUtf8 mwid
87− }
88−
89−listMaintenanceWindows :: Maybe Text
90− -> [ServiceId]
91− -> Maybe MaintenanceWindowFilter
92− -> PagerDuty (A a) (Either Error (MaintenanceWindowCounts, [MaintenanceWindowDetails]))
93−listMaintenanceWindows qry sids filt =
94− fmap (fmap (liftA2 (,) lr_counts lr_maintenance_windows))
95− . request defaultRequest
96− { method = methodGet
97− , path = bASE_PATH
98− , queryString = renderSimpleQuery True mkQuery
99− }
100− $ T.empty
101− where
102− mkQuery :: [(ByteString, ByteString)]
103− mkQuery = (catMaybes [ fmap ((,) "query" . encodeUtf8) qry
104− , fmap ((,) "filter" . filterToBS) filt
105− ])
106− ++ map (\ (Id sid) -> ("service_ids[]", encodeUtf8 sid)) sids
107−
108−getMaintenanceWindow :: MaintenanceWindowId
109− -> PagerDuty (A a) (Either Error MaintenanceWindowDetails)
110−getMaintenanceWindow (Id mwid) =
111− fmap (fmap dr_maintenance_window)
112− . request defaultRequest
113− { method = methodGet
114− , path = bASE_PATH <> encodeUtf8 mwid
115− }
116− $ T.empty
117−
118−deleteMaintenaceWindow :: MaintenanceWindowId
119− -> PagerDuty (A a) (Either Error Empty)
120−deleteMaintenaceWindow (Id mwid) = request defaultRequest
121− { method = methodDelete
122− , path = bASE_PATH <> encodeUtf8 mwid
123− } $ T.empty
124−
125−data MaintenanceWindow
126−data MaintenanceWindowCreator
127−
128−type MaintenanceWindowId = Id MaintenanceWindow
129−type MaintenanceWindowCreatorId = Id MaintenanceWindowCreator
130−
131−data CreateMaintenanceWindow = CreateMaintenanceWindow
132− { cmw_start_time :: !UTCTime
133− , cmw_end_time :: !UTCTime
134− , cmw_description :: Maybe Text
135− , cmw_service_ids :: [ServiceId]
136− } deriving (Show, Generic)
137−
138−instance ToJSON CreateMaintenanceWindow where
139− toJSON = gToJson "cmw_"
140−
141−data UpdateMaintenanceWindow = UpdateMaintenanceWindow
142− { umw_start_time :: Maybe UTCTime
143− , umw_end_time :: Maybe UTCTime
144− , umw_description :: Maybe Text
145− , umw_service_ids :: [ServiceId]
146− } deriving (Show, Generic)
147−
148−instance ToJSON UpdateMaintenanceWindow where
149− toJSON = gToJson "umw_"
150−
151−data CreateMaintenanceWindowRequest = CreateMaintenanceWindowRequest
152− { cmwr_maintenance_window :: !CreateMaintenanceWindow
153− , cmwr_requester_id :: Maybe RequesterId
154− } deriving (Show, Generic)
155−
156−instance ToJSON CreateMaintenanceWindowRequest where
157− toJSON = gToJson "cmwr_"
158−
159−data MaintenanceWindowDetails = MaintenanceWindowDetails
160− { mwd_id :: !MaintenanceWindowId
161− , mwd_sequence_number :: !Int
162− , mwd_start_time :: !UTCTime
163− , mwd_end_time :: !UTCTime
164− , mwd_description :: Maybe Text
165− , mwd_created_by :: !MaintenanceWindowCreatorDetails
166− , mwd_services :: [ServiceInfo]
167− } deriving (Show, Generic)
168−
169−instance FromJSON MaintenanceWindowDetails where
170− parseJSON = gFromJson "mwd_"
171−
172−-- possibly used elsewhere (UserDetails or somesuch)
173−data MaintenanceWindowCreatorDetails = MaintenanceWindowCreatorDetails
174− { mwcd_id :: !MaintenanceWindowCreatorId
175− , mwcd_name :: !Text
176− , mwcd_email :: !Text
177− , mwcd_time_zone :: !Text
178− , mwcd_color :: !Text -- wtf?
179− , mwcd_role :: !Text
180− , mwcd_avatar_url :: !Text
181− , mwcd_user_url :: !Text
182− , mwcd_invitation_sent :: !Bool
183− } deriving (Show, Generic)
184−
185−instance FromJSON MaintenanceWindowCreatorDetails where
186− parseJSON = gFromJson "mwcd_"
187−
188−data ServiceInfo = ServiceInfo
189− { si_name :: !Text
190− , si_url :: !Text
191− , si_id :: !ServiceId
192− } deriving (Show, Generic)
193−
194−instance FromJSON ServiceInfo where
195− parseJSON = gFromJson "si_"
196−
197−data ListResponse = ListResponse
198− { lr_maintenance_windows :: [MaintenanceWindowDetails]
199− , lr_query :: Maybe Text
200− , lr_counts :: !MaintenanceWindowCounts
201− } deriving (Show, Generic)
202−
203−instance FromJSON ListResponse where
204− parseJSON = gFromJson "lr_"
205−
206−data MaintenanceWindowCounts = MaintenanceWindowCounts
207− { mwc_ongoing :: !Int
208− , mwc_future :: !Int
209− , mwc_past :: !Int
210− , mwc_all :: !Int
211− } deriving (Show, Generic)
212−
213−instance FromJSON MaintenanceWindowCounts where
214− parseJSON = gFromJson "mwc_"
215−
216−newtype DetailsResponse = DetailsResponse
217− { dr_maintenance_window :: MaintenanceWindowDetails
218− } deriving (Show, Generic)
219−
220−instance FromJSON DetailsResponse where
221− parseJSON = gFromJson "dr_"
222−
223−data MaintenanceWindowFilter
224− = Past
225− | Future
226− | Ongoing
227− deriving Show
228−
229−filterToBS :: MaintenanceWindowFilter -> ByteString
230−filterToBS Past = "past"
231−filterToBS Future = "future"
232−filterToBS Ongoing = "ongoing"
src/Network/PagerDuty/API/Services.hsdeleted−292
@@ -1,292 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−-- Module : Network.PagerDuty.API.Services
6−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
7−-- License : This Source Code Form is subject to the terms of
8−-- the Mozilla Public License, v. 2.0.
9−-- A copy of the MPL can be found in the LICENSE file or
10−-- you can obtain it at http://mozilla.org/MPL/2.0/.
11−-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
12−-- Stability : experimental
13−-- Portability : non-portable (GHC extensions)
14−
15−module Network.PagerDuty.API.Services
16− ( ServiceDetails (..)
17− , CreateService (..)
18− , UpdateService (..)
19− , ServiceStatus (..)
20− , ServiceType (..)
21− , EmailFilterMode (..)
22− , IncidentCounts (..)
23− , EmailIncidentCreation (..)
24−
25− , createService
26− , updateService
27− , listServices
28− , getService
29− , deleteService
30− , disableService
31− , disableService'
32− , enableService
33− , enableService'
34− , regenerateServiceKey
35− ) where
36−
37−import Control.Applicative
38−import Control.Monad
39−import Data.Aeson
40−import Data.ByteString (ByteString)
41−import Data.Monoid
42−import Data.Text (Text)
43−import qualified Data.Text as T
44−import Data.Text.Encoding
45−import Data.Time
46−import GHC.Generics
47−import Network.PagerDuty.Internal
48−import Network.PagerDuty.IO
49−import Network.PagerDuty.Types
50−
51−type A a = Authenticated a
52−
53−bASE_PATH :: ByteString
54−bASE_PATH = "/api/v1/services/"
55−
56−createService :: CreateService -> PagerDuty (A a) (Either Error ServiceDetails)
57−createService = fmap (fmap service) . request defaultRequest
58− { method = methodPost
59− , path = bASE_PATH
60− }
61− . CreateServiceRequest
62−
63−updateService :: ServiceId
64− -> UpdateService
65− -> PagerDuty (A a) (Either Error ServiceDetails)
66−updateService (Id sid) = fmap (fmap service) . request defaultRequest
67− { method = methodPut
68− , path = bASE_PATH <> encodeUtf8 sid
69− }
70− . UpdateServiceRequest
71−
72−listServices :: PagerDuty (A a) (Either Error [ServiceDetails])
73−listServices = fmap (fmap services) . request defaultRequest
74− { method = methodGet
75− , path = bASE_PATH
76− , queryString = "?include[]=escalation_policy&include[]=email_filters"
77− } $ T.empty
78−
79−getService :: ServiceId -> PagerDuty (A a) (Either Error ServiceDetails)
80−getService (Id sid) = fmap (fmap service) . request defaultRequest
81− { method = methodGet
82− , path = bASE_PATH <> encodeUtf8 sid
83− , queryString = "?include[]=escalation_policy&include[]=email_filters"
84− } $ T.empty
85−
86−deleteService :: ServiceId -> PagerDuty (A a) (Either Error Empty)
87−deleteService (Id sid) = request defaultRequest
88− { method = methodDelete
89− , path = bASE_PATH <> encodeUtf8 sid
90− } $ T.empty
91−
92−disableService :: ServiceId
93− -> RequesterId
94− -> PagerDuty (A Token) (Either Error Empty)
95−disableService (Id sid) (Id rid) = request defaultRequest
96− { method = methodPut
97− , path = bASE_PATH <> encodeUtf8 sid <> "/disable"
98− , queryString = "?requester_id=" <> encodeUtf8 rid
99− } $ T.empty
100−
101−disableService' :: ServiceId -> PagerDuty (A BasicAuth) (Either Error Empty)
102−disableService' (Id sid) = request defaultRequest
103− { method = methodPut
104− , path = bASE_PATH <> encodeUtf8 sid <> "/disable"
105− } $ T.empty
106−
107−enableService :: ServiceId
108− -> RequesterId
109− -> PagerDuty (A Token) (Either Error Empty)
110−enableService (Id sid) (Id rid) = request defaultRequest
111− { method = methodPut
112− , path = bASE_PATH <> encodeUtf8 sid <> "/enable"
113− , queryString = "?requester_id=" <> encodeUtf8 rid
114− } $ T.empty
115−
116−enableService' :: ServiceId -> PagerDuty (A BasicAuth) (Either Error Empty)
117−enableService' (Id sid) = request defaultRequest
118− { method = methodPut
119− , path = bASE_PATH <> encodeUtf8 sid <> "/enable"
120− } $ T.empty
121−
122−regenerateServiceKey :: ServiceId -> PagerDuty (A a) (Either Error ServiceKey)
123−regenerateServiceKey (Id sid) = fmap (fmap (sd_service_key . service)) . request defaultRequest
124− { method = methodPost
125− , path = bASE_PATH <> encodeUtf8 sid <> "/regenerate_key"
126− } $ T.empty
127−
128−newtype CreateServiceRequest = CreateServiceRequest
129− { csr_service :: CreateService
130− } deriving (Show, Generic)
131−
132−instance ToJSON CreateServiceRequest where
133− toJSON = gToJson "csr_"
134−
135−newtype UpdateServiceRequest = UpdateServiceRequest
136− { usr_service :: UpdateService
137− } deriving (Show, Generic)
138−
139−instance ToJSON UpdateServiceRequest where
140− toJSON = gToJson "usr_"
141−
142−newtype DetailsListResponse = DLR { services :: [ServiceDetails] }
143− deriving (Show, Generic)
144−
145−instance FromJSON DetailsListResponse
146−
147−newtype DetailsResponse = DR { service :: ServiceDetails }
148− deriving (Show, Generic)
149−
150−instance FromJSON DetailsResponse
151−
152−data CreateService = CreateService
153− { cs_name :: !Text
154− , cs_escalation_policy_id :: !Text
155− , cs_type :: !ServiceType
156− , cs_description :: Maybe Text
157− , cs_acknowledgement_timeout :: Maybe Int
158− , cs_auto_resolve_timeout :: Maybe Int
159− , cs_severity_filter :: Maybe Text
160− } deriving (Show, Generic)
161−
162−instance ToJSON CreateService where toJSON = gToJson "cs_"
163−
164−data UpdateService = UpdateService
165− { us_name :: Maybe Text
166− , us_escalation_policy_id :: Maybe Text
167− , us_type :: Maybe ServiceType
168− , us_description :: Maybe Text
169− , us_acknowledgement_timeout :: Maybe Int
170− , us_auto_resolve_timeout :: Maybe Int
171− , us_severity_filter :: Maybe Text
172− } deriving (Show, Generic)
173−
174−instance ToJSON UpdateService where toJSON = gToJson "us_"
175−
176−data ServiceDetails = ServiceDetails
177− { sd_id :: !ServiceId
178− , sd_name :: !Text
179− , sd_description :: !Text
180− , sd_service_url :: !Text
181− , sd_service_key :: !ServiceKey
182− , sd_auto_resolve_timeout :: !Int
183− , sd_acknowledgement_timeout :: !Int
184− , sd_created_at :: !ZonedTime
185− , sd_deleted_at :: Maybe ZonedTime
186− , sd_status :: !ServiceStatus
187− , sd_last_incident_timestamp :: Maybe ZonedTime
188− , sd_email_incident_creation :: Maybe EmailIncidentCreation
189− , sd_incident_counts :: !IncidentCounts
190− , sd_email_filter_mode :: !EmailFilterMode
191− , sd_type :: !ServiceType
192− , sd_escalation_policy :: Maybe Object -- todo
193− , sd_email_filters :: Maybe Object -- todo
194− , sd_severity_filter :: Maybe Text -- todo?
195− } deriving (Show, Generic)
196−
197−instance FromJSON ServiceDetails where
198− parseJSON = gFromJson "sd_"
199−
200−data ServiceStatus
201− = Active
202− | Warning
203− | Critical
204− | Maintenance
205− | Disabled
206− deriving (Eq, Show)
207−
208−instance FromJSON ServiceStatus where
209− parseJSON (String s) = case s of
210− "active" -> pure Active
211− "warning" -> pure Warning
212− "critical" -> pure Critical
213− "maintenance" -> pure Maintenance
214− "disabled" -> pure Disabled
215− _ -> mzero
216−
217− parseJSON _ = mzero
218−
219−data IncidentCounts = IncidentCounts
220− { triggered :: !Int
221− , acknowledged :: !Int
222− , resolved :: !Int
223− , total :: !Int
224− } deriving (Show, Generic)
225−
226−instance FromJSON IncidentCounts
227−
228−data EmailIncidentCreation
229− = OnNewEmail
230− | OnNewEmailSubject
231− | OnlyIfNoOpenIncidents
232− deriving (Eq, Show)
233−
234−instance FromJSON EmailIncidentCreation where
235− parseJSON (String s) = case s of
236− "on_new_email" -> pure OnNewEmail
237− "on_new_email_subject" -> pure OnNewEmailSubject
238− "only_if_no_open_incidents" -> pure OnlyIfNoOpenIncidents
239− _ -> mzero
240−
241− parseJSON _ = mzero
242−
243−data EmailFilterMode
244− = AllEmail
245− | OrRulesEmail
246− | AndRulesEmail
247− deriving (Eq, Show)
248−
249−instance FromJSON EmailFilterMode where
250− parseJSON (String s) = case s of
251− "all-email" -> pure AllEmail
252− "or-rules-email" -> pure OrRulesEmail
253− "and-rules-email" -> pure AndRulesEmail
254− _ -> mzero
255−
256− parseJSON _ = mzero
257−
258−data ServiceType
259− = CloudKick
260− | GenericEmail
261− | GenericEventsApi
262− | Keynote
263− | Nagios
264− | Pingdom
265− | ServerDensity
266− | SqlMonitor
267− deriving (Eq, Show)
268−
269−instance FromJSON ServiceType where
270− parseJSON (String s) = case s of
271− "cloudkick" -> pure CloudKick
272− "generic_email" -> pure GenericEmail
273− "generic_events_api" -> pure GenericEventsApi
274− "keynote" -> pure Keynote
275− "nagios" -> pure Nagios
276− "pingdom" -> pure Pingdom
277− "server_density" -> pure ServerDensity
278− "sql_monitor" -> pure SqlMonitor
279− _ -> mzero
280−
281− parseJSON _ = mzero
282−
283−instance ToJSON ServiceType where
284− toJSON st = String $ case st of
285− CloudKick -> "cloudkick"
286− GenericEmail -> "generic_email"
287− GenericEventsApi -> "generic_events_api"
288− Keynote -> "keynote"
289− Nagios -> "nagios"
290− Pingdom -> "pingdom"
291− ServerDensity -> "server_density"
292− SqlMonitor -> "sql_monitor"
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
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
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+25−25
@@ -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"
@@ -83,24 +83,6 @@ instance Paginate ListAlerts
8383
8484queryRequest ''ListAlerts
8585
86−-- | List existing alerts for a given time range, optionally filtered by type
87−-- (SMS, Email, Phone, or Push).
88−--
89−-- @GET \/alerts@
90−--
91−-- /See:/ <http://developer.pagerduty.com/documentation/rest/alerts/list>
92−listAlerts :: Date -- ^ 'laSince'
93− -> Date -- ^ 'laUntil'
94− -> Request ListAlerts s [Alert]
95−listAlerts s u =
96− mk ListAlerts
97− { _laSince' = s
98− , _laUntil' = u
99− , _laFilter' = Nothing
100− , _laTimeZone' = Nothing
101− } & path .~ alerts
102− & unwrap .~ key "alerts"
103−
10486-- | The start of the date range over which you want to search.
10587laSince :: Lens' (Request ListAlerts s b) UTCTime
10688laSince = upd.laSince'._D
@@ -121,3 +103,21 @@ laFilter = upd.laFilter'
121103-- /Default:/ account time zone.
122104laTimeZone :: Lens' (Request ListAlerts s b) (Maybe TimeZone)
123105laTimeZone = upd.laTimeZone'.mapping _TZ
106+
107+-- | List existing alerts for a given time range, optionally filtered by type
108+-- (SMS, Email, Phone, or Push).
109+--
110+-- @GET \/alerts@
111+--
112+-- /See:/ <http://developer.pagerduty.com/documentation/rest/alerts/list>
113+listAlerts :: Date -- ^ 'laSince'
114+ -> Date -- ^ 'laUntil'
115+ -> Request ListAlerts s [Alert]
116+listAlerts s u =
117+ mk ListAlerts
118+ { _laSince' = s
119+ , _laUntil' = u
120+ , _laFilter' = Nothing
121+ , _laTimeZone' = Nothing
122+ } & path .~ alerts
123+ & unwrap .~ key "alerts"
src/Network/PagerDuty/REST/EscalationPolicies.hs+21−21
@@ -1,10 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
4−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
6+
7+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
58
69-- Module : Network.PagerDuty.REST.EscalationPolicies
7−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
811-- License : This Source Code Form is subject to the terms of
912-- the Mozilla Public License, v. 2.0.
1013-- A copy of the MPL can be found in the LICENSE file or
@@ -57,26 +60,23 @@ module Network.PagerDuty.REST.EscalationPolicies
5760 , pServices
5861 ) where
5962
60−import Control.Applicative ((<$>))
61−import Control.Lens
62−import Data.Aeson
63+import Control.Lens hiding (Empty)
6364import Data.Aeson.Lens
64−import qualified Data.HashMap.Strict as Map
65−import Data.Text (Text)
66−import qualified Data.Text as Text
65+import Data.Text (Text)
6766import Network.HTTP.Types
68−import Network.PagerDuty.REST.Services (Service)
69−import Network.PagerDuty.REST.Users
70−import Network.PagerDuty.TH
71−import Network.PagerDuty.Types
67+import Network.PagerDuty.Internal.TH
68+import Network.PagerDuty.Internal.Types
69+import Network.PagerDuty.REST.Services (Service)
70+
71+import Network.PagerDuty.REST.EscalationPolicies.EscalationRules
7272
73−import Network.PagerDuty.REST.EscalationPolicies.EscalationRules
73+default (Path)
7474
7575policies :: Path
7676policies = "escalation_policies"
7777
7878data Policy = Policy
79− { _pId :: PolicyId
79+ { _pId :: EscalationPolicyId
8080 , _pName :: Text
8181 , _pNumLoops :: !Int
8282 , _pRules :: [Rule]
@@ -170,7 +170,7 @@ cpEscalationRules = upd.cpEscalationRules'
170170-- @POST \/escalation_policies@
171171--
172172-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/create>
173−createPolicy :: PolicyId
173+createPolicy :: EscalationPolicyId
174174 -> Text -- ^ 'creName'
175175 -> [Rule] -- ^ 'creEscalationRules'
176176 -> Request CreatePolicy s Policy
@@ -189,7 +189,7 @@ createPolicy i n rs =
189189-- @GET \/escalation_policies\/\:id@
190190--
191191-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/show>
192−getPolicy :: PolicyId -> Request Empty s Policy
192+getPolicy :: EscalationPolicyId -> Request Empty s Policy
193193getPolicy i = empty & path .~ policies % i & unwrap .~ key "escalation_policy"
194194
195195data UpdatePolicy = UpdatePolicy
@@ -223,7 +223,7 @@ upEscalationRules = upd.upEscalationRules'
223223-- @PUT \/escalation_policies\/\:id@
224224--
225225-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/update>
226−updatePolicy :: PolicyId -> Request UpdatePolicy s Policy
226+updatePolicy :: EscalationPolicyId -> Request UpdatePolicy s Policy
227227updatePolicy i =
228228 mk UpdatePolicy
229229 { _upName' = Nothing
@@ -240,5 +240,5 @@ updatePolicy i =
240240-- @DELETE \/escalation_policies\/\:id@
241241--
242242-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/delete>
243−deletePolicy :: PolicyId -> Request Empty s Empty
243+deletePolicy :: EscalationPolicyId -> Request Empty s Empty
244244deletePolicy i = empty & meth .~ DELETE & path .~ policies % i
src/Network/PagerDuty/REST/EscalationPolicies/EscalationRules.hs+21−20
@@ -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,20 +64,21 @@ 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 Data.ByteString.Builder (Builder)
71−import qualified Data.HashMap.Strict as Map
72−import Data.Text (Text)
70+import qualified Data.Aeson.KeyMap as Map
71+import Data.Text (Text)
7372import Network.HTTP.Types
73+import Network.PagerDuty.Internal.TH
74+import Network.PagerDuty.Internal.Types
7475import Network.PagerDuty.REST.Users
75−import Network.PagerDuty.TH
76−import Network.PagerDuty.Types
7776
7877default (Path)
7978
80−rules :: PolicyId -> Path
79+-- FIXME: The lenses here need to operate over (Request x s b) using upd
80+
81+rules :: EscalationPolicyId -> Path
8182rules p = "escalation_policies" % p % "escalation_rules"
8283
8384data TargetType
@@ -137,7 +138,7 @@ instance ToJSON Target where
137138 TUser u -> ("user", toJSON u)
138139
139140data Rule = Rule
140− { _rId :: RuleId
141+ { _rId :: EscalationRuleId
141142 , _rEscalationDelayInMinutes :: !Int
142143 , _rTargets :: [Target]
143144 } deriving (Eq, Show)
@@ -158,7 +159,7 @@ makeLens "_rTargets" ''Rule
158159-- @GET \/escalation_policies\/\:escalation_policy_id\/escalation_rules@
159160--
160161-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/escalation_rules/list>
161−listRules :: PolicyId -> Request Empty s [Rule]
162+listRules :: EscalationPolicyId -> Request Empty s [Rule]
162163listRules p = empty & path .~ rules p
163164
164165-- | Show the escalation rule for an existing escalation policy.
@@ -166,7 +167,7 @@ listRules p = empty & path .~ rules p
166167-- @GET \/escalation_policies\/:escalation_policy_id\/escalation_rules\/\:id@
167168--
168169-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/escalation_rules/show>
169−getRule :: PolicyId -> RuleId -> Request Empty s Rule
170+getRule :: EscalationPolicyId -> EscalationRuleId -> Request Empty s Rule
170171getRule p r = empty & path .~ rules p % r
171172
172173data CreateRule = CreateRule
@@ -194,7 +195,7 @@ makeLens "_crTargets" ''CreateRule
194195-- @POST \/escalation_policies\/\:escalation_policy_id\/escalation_rules@
195196--
196197-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/escalation_rules/create>
197−createRule :: PolicyId
198+createRule :: EscalationPolicyId
198199 -> Int -- ^ 'crEscalationDelayInMinutes'
199200 -> [TargetId] -- ^ 'crTargets'
200201 -> Request CreateRule s Rule
@@ -225,7 +226,7 @@ makeLens "_urEscalationRules" ''UpdateRules
225226-- @PUT \/escalation_policies\/\:escalation_policy_id\/escalation_rules@
226227--
227228-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/escalation_rules/multi_update>
228−updateRules :: PolicyId
229+updateRules :: EscalationPolicyId
229230 -> [TargetId] -- ^ 'urEscalationRules'
230231 -> Request UpdateRules s [Rule]
231232updateRules p rs =
@@ -258,7 +259,7 @@ makeLens "_urTargets" ''UpdateRule
258259-- @PUT \/escalation_policies\/\:escalation_policy_id\/escalation_rules\/\:id@
259260--
260261-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/escalation_rules/update>
261−updateRule :: PolicyId -> RuleId -> Request UpdateRule s Rule
262+updateRule :: EscalationPolicyId -> EscalationRuleId -> Request UpdateRule s Rule
262263updateRule p r =
263264 mk UpdateRule
264265 { _urEscalationDelayInMinutes = Nothing
@@ -272,5 +273,5 @@ updateRule p r =
272273-- @DELETE \/escalation_policies\/\:escalation_policy_id\/escalation_rules\/\:id@
273274--
274275-- /See:/ <http://developer.pagerduty.com/documentation/rest/escalation_policies/escalation_rules/delete>
275−deleteRule :: PolicyId -> RuleId -> Request Empty s Empty
276+deleteRule :: EscalationPolicyId -> EscalationRuleId -> Request Empty s Empty
276277deleteRule p r = empty & meth .~ DELETE & path .~ rules p % r
src/Network/PagerDuty/REST/Incidents.hs+135−122
@@ -2,6 +2,7 @@
22{-# LANGUAGE ExtendedDefaultRules #-}
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5+{-# LANGUAGE LambdaCase #-}
56{-# LANGUAGE OverloadedStrings #-}
67{-# LANGUAGE TemplateHaskell #-}
78{-# LANGUAGE TypeFamilies #-}
@@ -9,7 +10,7 @@
910{-# OPTIONS_GHC -fno-warn-type-defaults #-}
1011
1112-- Module : Network.PagerDuty.REST.Incidents
12−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
13+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1314-- License : This Source Code Form is subject to the terms of
1415-- the Mozilla Public License, v. 2.0.
1516-- A copy of the MPL can be found in the LICENSE file or
@@ -124,35 +125,25 @@ module Network.PagerDuty.REST.Incidents
124125 , aAt
125126 , aObject
126127
128+ , HasIncident (..)
127129 , Incident
128− , iIncidentNumber
129− , iStatus
130− , iCreatedOn
131− , iHtmlUrl
132− , iIncidentKey
133− , iService
134− , iEscalationPolicy
135− , iAssignedTo
136− , iAcknowledgers
137− , iLastStatusChangeBy
138− , iLastStatusChangeOn
139− , iTriggerSummaryData
140− , iTriggerDetailsHtmlUrl
141130 ) where
142131
143−import Control.Applicative hiding (empty)
144−import Control.Lens
132+import Control.Applicative hiding (empty)
133+import Control.Lens hiding (Empty)
145134import Data.Aeson
146−import Data.ByteString.Conversion (ToByteString(..), toByteString')
147−import Data.Default
148−import Data.Monoid hiding (All)
149−import Data.Text (Text)
150−import qualified Data.Text.Encoding as Text
135+import Data.ByteString.Conversion (ToByteString (..),
136+ toByteString')
137+import Data.Default.Class
138+import Data.Maybe
139+import Data.Monoid hiding (All)
140+import Data.Text (Text)
141+import qualified Data.Text.Encoding as Text
151142import Data.Time
152143import Network.HTTP.Types
153−import Network.PagerDuty.Query
154−import Network.PagerDuty.TH
155−import Network.PagerDuty.Types
144+import Network.PagerDuty.Internal.Query
145+import Network.PagerDuty.Internal.TH
146+import Network.PagerDuty.Internal.Types
156147
157148default (Path)
158149
@@ -198,18 +189,18 @@ data IncidentStatus
198189 deriving (Eq, Show)
199190
200191instance ToByteString IncidentStatus where
201− builder ITriggered = "triggered"
202− builder IAcknowledged = "acknowledged"
203− builder IResolved = "resolved"
204− builder (IOther t) = builder t
192+ builder = \case
193+ ITriggered -> "triggered"
194+ IAcknowledged -> "acknowledged"
195+ IResolved -> "resolved"
196+ IOther t -> builder t
205197
206198instance FromJSON IncidentStatus where
207− parseJSON = withText "status" $ \t ->
208− return $ case t of
209− "triggered" -> ITriggered
210− "acknowledged" -> IAcknowledged
211− "resolved" -> IResolved
212− _ -> IOther t
199+ parseJSON = withText "status" $ pure . \case
200+ "triggered" -> ITriggered
201+ "acknowledged" -> IAcknowledged
202+ "resolved" -> IResolved
203+ t -> IOther t
213204
214205instance ToJSON IncidentStatus where
215206 toJSON = String . Text.decodeUtf8 . toByteString'
@@ -222,76 +213,104 @@ data Assignee = Assignee
222213deriveRecord ''Assignee
223214
224215data Incident = Incident
225− { _iIncidentNumber :: !Int
226− , _iStatus :: !IncidentStatus
227− , _iCreatedOn :: Date
228− , _iHtmlUrl :: Text
229− , _iIncidentKey :: Maybe IncidentKey
230− , _iService :: Object
231− , _iEscalationPolicy :: Maybe Object
232− , _iAssignedTo :: [Assignee]
233− , _iAcknowledgers :: [Assignee]
234− , _iLastStatusChangeBy :: Maybe Assignee
235− , _iLastStatusChangeOn :: Maybe Date
236− , _iTriggerSummaryData :: Object
237− , _iTriggerDetailsHtmlUrl :: Text
216+ { _iIncidentNumber' :: !Int
217+ , _iStatus' :: !IncidentStatus
218+ , _iCreatedOn' :: Date
219+ , _iHtmlUrl' :: Text
220+ , _iIncidentKey' :: Maybe IncidentKey
221+ , _iService' :: Object
222+ , _iEscalationPolicy' :: Maybe Object
223+ , _iAssignedTo' :: [Assignee]
224+ , _iAcknowledgers' :: [Assignee]
225+ , _iLastStatusChangeBy' :: Maybe Assignee
226+ , _iLastStatusChangeOn' :: Maybe Date
227+ , _iTriggerSummaryData' :: Object
228+ , _iTriggerDetailsHtmlUrl' :: Text
238229 } deriving (Eq, Show)
239230
240−deriveJSON ''Incident
241−
242−-- | The number of the incident. This is unique across your account.
243−makeLens "_iIncidentNumber" ''Incident
244−
245−-- | The current status of the incident. Valid statuses are:
246−makeLens "_iStatus" ''Incident
247−
248−-- | The date/time the incident was triggered.
249−iCreatedOn :: Lens' Incident UTCTime
250−iCreatedOn = lens _iCreatedOn (\i x -> i { _iCreatedOn = x }) . _D
251−
252−-- | The PagerDuty website URL where the incident can be viewed and further
253−-- actions taken. This is not the resource URL.
254−makeLens "_iHtmlUrl" ''Incident
255−
256−-- | The incident's de-duplication key. See the PagerDuty Integration API docs
257−-- for further details.
258−makeLens "_iIncidentKey" ''Incident
259−
260−-- | The PagerDuty service that the incident belongs to. The service will
261−-- contain fields of its own.
262−makeLens "_iService" ''Incident
263−
264−-- | The escalation policy that the incident belongs to. The policy will
265−-- contain fields of its own.
266−makeLens "_iEscalationPolicy" ''Incident
267−
268−-- | The list of assignments of the incident. An assignment is an object
269−-- containing the assigned user as well as the date/time the incident was assigned
270−-- to that user. The user will contain fields of its own. This list is empty if
271−-- the status of the incident is resolved.
272−makeLens "_iAssignedTo" ''Incident
273−
274−-- | The list of acknowledgements of the incident. An acknowledgement is an
275−-- object containing the acknowleding object (either a user or the integration
276−-- API) as well as the date/time the incident was acknowledged. This field is only
277−-- present if the status of the incident is acknowledged. This field is sorted in
278−-- ascending order by acknowledgement time.
279−makeLens "_iAcknowledgers" ''Incident
280−
281−-- | The user who is responsible for the incident's last status change. If the incident is in the acknowledged or resolved status, this will be the user that took the first acknowledged or resolved action. If the incident was automatically resolved (say through the Event Integration API), or if the incident is in the triggered state, this will be null. User fields are the same as in the assignedToUser field above.
282−makeLens "_iLastStatusChangeBy" ''Incident
283−
284−-- | The date/time the incident's status last changed.
285−iLastStatusChangeOn :: Lens' Incident (Maybe UTCTime)
286−iLastStatusChangeOn =
287− lens _iLastStatusChangeOn (\i x -> i { _iLastStatusChangeOn = x })
288− . mapping _D
289−
290−-- | Some condensed information regarding the initial event that triggered this incident. This data will be a set of key/value pairs that vary depending on what sort of event triggered the incident (email, Event API request, etc). For instance, if an email triggered the incident, then the triggerSummaryData will likely contain a subject. There are no guarantees on the full presence of this data for every incident.
291−makeLens "_iTriggerSummaryData" ''Incident
292−
293−-- | The PagerDuty website URL where the full details regarding the initial event that triggered this incident can be found. (This is not the resource URL.)
294−makeLens "_iTriggerDetailsHtmlUrl" ''Incident
231+deriveRecord ''Incident
232+
233+class HasIncident a where
234+ incident :: Lens' a Incident
235+
236+ -- | The number of the incident. This is unique across your account.
237+ iIncidentNumber :: Lens' a Int
238+
239+ -- | The current status of the incident. Valid statuses are:
240+ iStatus :: Lens' a IncidentStatus
241+
242+ -- | The date/time the incident was triggered.
243+ iCreatedOn :: Lens' a UTCTime
244+
245+ -- | The PagerDuty website URL where the incident can be viewed and further
246+ -- actions taken. This is not the resource URL.
247+ iHtmlUrl :: Lens' a Text
248+
249+ -- | The incident's de-duplication key. See the PagerDuty Integration API
250+ -- docs for further details.
251+ iIncidentKey :: Lens' a (Maybe IncidentKey)
252+
253+ -- | The PagerDuty service that the incident belongs to. The service will
254+ -- contain fields of its own.
255+ iService :: Lens' a Object
256+
257+ -- | The escalation policy that the incident belongs to. The policy will
258+ -- contain fields of its own.
259+ iEscalationPolicy :: Lens' a (Maybe Object)
260+
261+ -- | The list of assignments of the incident. An assignment is an object
262+ -- containing the assigned user as well as the date/time the incident was
263+ -- assigned to that user. The user will contain fields of its own.
264+ -- This list is empty if the status of the incident is resolved.
265+ iAssignedTo :: Lens' a [Assignee]
266+
267+ -- | The list of acknowledgements of the incident. An acknowledgement is an
268+ -- object containing the acknowleding object (either a user or the
269+ -- integration API) as well as the date/time the incident was acknowledged.
270+ -- This field is only present if the status of the incident is acknowledged.
271+ -- This field is sorted in ascending order by acknowledgement time.
272+ iAcknowledgers :: Lens' a [Assignee]
273+
274+ -- | The user who is responsible for the incident's last status change. If
275+ -- the incident is in the acknowledged or resolved status, this will be the user
276+ -- that took the first acknowledged or resolved action. If the incident was
277+ -- automatically resolved (say through the Event Integration API), or if the
278+ -- incident is in the triggered state, this will be null. User fields are the
279+ -- same as in the assignedToUser field above.
280+ iLastStatusChangeBy :: Lens' a (Maybe Assignee)
281+
282+ -- | The date/time the incident's status last changed.
283+ iLastStatusChangeOn :: Lens' a (Maybe UTCTime)
284+
285+ -- | Some condensed information regarding the initial event that triggered
286+ -- this incident. This data will be a set of key/value pairs that vary depending
287+ -- on what sort of event triggered the incident (email, Event API request,
288+ -- etc). For instance, if an email triggered the incident, then the
289+ -- triggerSummaryData will likely contain a subject. There are no guarantees
290+ -- o nthe full presence of this data for every incident.
291+ iTriggerSummaryData :: Lens' a Object
292+
293+ -- | The PagerDuty website URL where the full details regarding the initial
294+ -- event that triggered this incident can be found. (This is not the resource
295+ -- URL.)
296+ iTriggerDetailsHtmlUrl :: Lens' a Text
297+
298+ iIncidentNumber = incident.iIncidentNumber'
299+ iStatus = incident.iStatus'
300+ iCreatedOn = incident.iCreatedOn'._D
301+ iHtmlUrl = incident.iHtmlUrl'
302+ iIncidentKey = incident.iIncidentKey'
303+ iService = incident.iService'
304+ iEscalationPolicy = incident.iEscalationPolicy'
305+ iAssignedTo = incident.iAssignedTo'
306+ iAcknowledgers = incident.iAcknowledgers'
307+ iLastStatusChangeBy = incident.iLastStatusChangeBy'
308+ iLastStatusChangeOn = incident.iLastStatusChangeOn'.mapping _D
309+ iTriggerSummaryData = incident.iTriggerSummaryData'
310+ iTriggerDetailsHtmlUrl = incident.iTriggerDetailsHtmlUrl'
311+
312+instance HasIncident Incident where
313+ incident = id
295314
296315data ListIncidents = ListIncidents
297316 { _lsSince' :: Maybe Date
@@ -328,13 +347,10 @@ lsUntil = upd.lsUntil'.mapping _D
328347-- | When set, the since and until parameters and defaults are
329348-- ignored. Use this to get all incidents since the account was created.
330349lsDateRange :: Lens' (Request ListIncidents s b) Bool
331−lsDateRange = upd . lens get' set'
350+lsDateRange = upd.lens get_ (flip set_)
332351 where
333− get' x
334− | Just All <- _lsDateRange' x = True
335− | otherwise = False
336−
337− 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]
338354
339355-- | Returns only the incidents currently in the passed status(es).
340356lsStatus :: Lens' (Request ListIncidents s b) (Maybe [IncidentStatus])
@@ -421,12 +437,12 @@ cSince = upd.cSince'.mapping _D
421437
422438-- | The end of the date range over which you want to search.
423439--
424−-- /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
425441-- applied to your open ended range. Not including the since parameter will set
426−-- the date range to until - 30 days. Likewise, if you leave off until,
427−-- 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.
428444--
429−-- 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
430446-- range must be less than 180 days.
431447cUntil :: Lens' (Request CountIncidents s b) (Maybe UTCTime)
432448cUntil = upd.cUntil'.mapping _D
@@ -434,13 +450,10 @@ cUntil = upd.cUntil'.mapping _D
434450-- | When set, the since and until parameters and defaults are
435451-- ignored. Use this to get all counts since the account was created.
436452cDateRange :: Lens' (Request CountIncidents s b) Bool
437−cDateRange = upd . lens get' set'
453+cDateRange = upd.lens get_ (flip set_)
438454 where
439− get' x
440− | Just All <- _cDateRange' x = True
441− | otherwise = False
442−
443− 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]
444457
445458-- | Only counts the incidents currently in the passed status(es).
446459cStatus :: Lens' (Request CountIncidents s b) (Maybe [IncidentStatus])
@@ -503,7 +516,7 @@ data UpdateIncident = UpdateIncident
503516 { _iiId :: IncidentId
504517 , _iiStatus :: Maybe UpdateStatus
505518 , _iiEscalationLevel :: Maybe Int
506− , _iiEscalationPolicy :: Maybe PolicyId
519+ , _iiEscalationPolicy :: Maybe EscalationPolicyId
507520 , _iiAssignedToUser :: Maybe (CSV UserId)
508521 } deriving (Eq, Show)
509522
@@ -554,7 +567,7 @@ updateIncidents r = auth updateIncidentsBasic & query .~ [("requester_id", r)]
554567
555568-- | A version of 'updateIncidents' which uses HTTP Basic authentication and
556569-- doesn't require a 'RequesterId'.
557−updateIncidentsBasic :: Request UpdateIncidents Basic [UpdatedIncidents]
570+updateIncidentsBasic :: Request UpdateIncidents 'Basic [UpdatedIncidents]
558571updateIncidentsBasic =
559572 mk UpdateIncidents
560573 { _uiIncidents' = []
@@ -595,7 +608,7 @@ acknowledgeIncidentBasic i =
595608 empty & meth .~ PUT & path .~ incidents % i % "acknowledge"
596609
597610data ReassignIncident = ReassignIncident
598− { _riEscalationPolicy' :: Maybe PolicyId
611+ { _riEscalationPolicy' :: Maybe EscalationPolicyId
599612 , _riEscalationLevel' :: Maybe Int
600613 , _riAssignedToUser' :: Maybe (CSV UserId)
601614 } deriving (Eq, Show)
@@ -604,7 +617,7 @@ jsonRequest ''ReassignIncident
604617
605618-- | The ID of an escalation policy. Delegate the incident to this escalation
606619-- policy.
607−riEscalationPolicy :: Lens' (Request ReassignIncident s b) (Maybe PolicyId)
620+riEscalationPolicy :: Lens' (Request ReassignIncident s b) (Maybe EscalationPolicyId)
608621riEscalationPolicy = upd.riEscalationPolicy'
609622
610623-- | Escalate incident to this level in the escalation policy.
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+10−11
@@ -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
118−import Data.Default
119−import qualified Data.HashMap.Strict as Map
120−import Data.Text (Text)
121−import qualified Data.Text as Text
117+import qualified Data.Aeson.KeyMap as Map
118+import Data.Default.Class
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"
@@ -326,7 +325,7 @@ data LogEntry = LogEntry'
326325 } deriving (Eq, Show)
327326
328327instance FromJSON LogEntry where
329− parseJSON = withObject "log_entry" $ \o -> do
328+ parseJSON = withObject "log_entry" $ \o ->
330329 LogEntry' <$> o .: "id"
331330 <*> o .: "type"
332331 <*> o .: "created_at"
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−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.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,12 +58,11 @@ module Network.PagerDuty.REST.Reports
5858 , irNumberOfIncidents
5959 ) where
6060
61−import Control.Lens
62−import Data.Aeson.Lens
63−import Data.ByteString.Builder (Builder)
64−import Data.Time
65−import Network.PagerDuty.TH
66−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
6766
6867default (Path)
6968
src/Network/PagerDuty/REST/Schedules.hs+16−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.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,15 +110,14 @@ module Network.PagerDuty.REST.Schedules
110110 , sFinalSchedule
111111 ) where
112112
113−import Control.Lens hiding ((.=))
114−import Data.Aeson
115−import Data.ByteString.Builder (Builder)
116−import Data.Text (Text)
117−import Data.Time
118−import Network.HTTP.Types
119−import Network.PagerDuty.REST.Users (User)
120−import Network.PagerDuty.TH
121−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)
122121
123122default (Path)
124123
@@ -226,7 +225,7 @@ data ScheduleInfo = ScheduleInfo
226225 , _siName' :: Text
227226 , _siTimeZone' :: TZ
228227 , _siToday' :: Date
229− , _siEscalationPolicies' :: [PolicyId]
228+ , _siEscalationPolicies' :: [EscalationPolicyId]
230229 } deriving (Eq, Show)
231230
232231deriveRecord ''ScheduleInfo
@@ -243,7 +242,7 @@ class HasScheduleInfo a where
243242 -- | The current day in the schedule's time zone.
244243 sToday :: Lens' a UTCTime
245244 -- | An list of all the escalation policies that uses this schedule.
246− sEscalationPolicies :: Lens' a [PolicyId]
245+ sEscalationPolicies :: Lens' a [EscalationPolicyId]
247246
248247 sId = scheduleInfo.siId'
249248 sName = scheduleInfo.siName'
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+24−24
@@ -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.ByteString.Builder (Builder)
112−import Data.Text (Text)
113−import Data.Time
114−import Network.HTTP.Types
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
@@ -187,7 +187,7 @@ data ServiceType
187187deriveNullary ''ServiceType
188188
189189data PolicyInfo = PolicyInfo
190− { _pinfoId :: PolicyId
190+ { _pinfoId :: EscalationPolicyId
191191 , _pinfoName :: Text
192192 } deriving (Eq, Show)
193193
@@ -223,8 +223,8 @@ data Service = Service
223223 , _svcIncidentCounts :: IncidentCounts
224224 , _svcEmailFilterMode :: EmailFilterMode
225225 , _svcType :: ServiceType
226− , _svcEscalationPolicy :: Maybe PolicyInfo -- FIXME: extract from inline.
227− , _svcEmailFilters :: Maybe EmailFilters -- FIXME: extract from inline.
226+ , _svcEscalationPolicy :: Maybe PolicyInfo -- FIXME: extract from inline.
227+ , _svcEmailFilters :: Maybe [EmailFilterInfo] -- FIXME: extract from inline.
228228 , _svcSeverityFilter :: Maybe SeverityFilter
229229 } deriving (Eq, Show)
230230
@@ -322,7 +322,7 @@ listServices =
322322
323323data CreateService = CreateService
324324 { _csName' :: Text
325− , _csEscalationPolicyId' :: PolicyId
325+ , _csEscalationPolicyId' :: EscalationPolicyId
326326 , _csType' :: !ServiceType
327327 , _csVendorId' :: Maybe VendorId
328328 , _csDescription' :: Maybe Text
@@ -351,7 +351,7 @@ csVendorId :: Lens' (Request CreateService s r) (Maybe VendorId)
351351csVendorId = upd.csVendorId'
352352
353353-- | The id of the escalation policy to be used by this service.
354−csEscalationPolicyId :: Lens' (Request CreateService s r) PolicyId
354+csEscalationPolicyId :: Lens' (Request CreateService s r) EscalationPolicyId
355355csEscalationPolicyId = upd.csEscalationPolicyId'
356356
357357-- | The duration in seconds before an incidents acknowledged in this service
@@ -377,7 +377,7 @@ csSeverityFilter = upd.csSeverityFilter'
377377--
378378-- /See:/ <http://developer.pagerduty.com/documentation/rest/services/create>
379379createService :: Text
380− -> PolicyId
380+ -> EscalationPolicyId
381381 -> ServiceType
382382 -> Request CreateService s Service
383383createService n p t =
@@ -407,7 +407,7 @@ getService i = empty
407407data UpdateService = UpdateService
408408 { _usName' :: Maybe Text
409409 , _usDescription' :: Maybe Text
410− , _usEscalationPolicyId' :: Maybe PolicyId
410+ , _usEscalationPolicyId' :: Maybe EscalationPolicyId
411411 , _usAcknowledgementTimeout' :: Maybe Int
412412 , _usAutoResolveTimeout' :: Maybe Int
413413 , _usSeverityFilter' :: Maybe SeverityFilter
@@ -424,7 +424,7 @@ usDescription :: Lens' (Request UpdateService s r) (Maybe Text)
424424usDescription = upd.usDescription'
425425
426426-- | The id of the escalation policy to be used by this service.
427−usEscalationPolicyId :: Lens' (Request UpdateService s r) (Maybe PolicyId)
427+usEscalationPolicyId :: Lens' (Request UpdateService s r) (Maybe EscalationPolicyId)
428428usEscalationPolicyId = upd.usEscalationPolicyId'
429429
430430-- | The duration in seconds before an incidents acknowledged in this service
@@ -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
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+29−28
@@ -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,15 +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
88−import Data.Text (Text)
89−import Data.Time
90−import Network.HTTP.Types
91−import Network.PagerDuty.TH
92−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
9394
9495default (Path)
9596
@@ -144,7 +145,7 @@ instance HasUserInfo UserInfo where
144145 userInfo = id
145146
146147data PolicyInfo = PolicyInfo
147− { _piId :: PolicyId
148+ { _piId :: EscalationPolicyId
148149 , _piName :: Text
149150 } deriving (Eq, Show)
150151
@@ -192,17 +193,17 @@ instance FromJSON User where
192193 <*> o .: "invitation_sent"
193194 <*> o .:? "job_title"
194195
195−-- instance ToJSON User where
196−-- toJSON u = Object (x <> y)
197−-- where
198−-- Object x = toJSON (_uInfo u)
199−-- Object y = object
200−-- [ "role" .= _uRole u
201−-- , "avatar_url" .= _uAvatarUrl u
202−-- , "user_url" .= _uUserUrl u
203−-- , "invitation_sent" .= _uInvitationSent' u
204−-- , "job_title"
205−-- ]
196+instance ToJSON User where
197+ toJSON u = Object (x <> y)
198+ where
199+ Object x = toJSON (_uInfo u)
200+ Object y = object
201+ [ "role" .= _uRole u
202+ , "avatar_url" .= _uAvatarUrl u
203+ , "user_url" .= _uUserUrl u
204+ , "invitation_sent" .= _uInvitationSent' u
205+ , "job_title" .= _uJobTitle u
206+ ]
206207
207208instance HasUserInfo User where
208209 userInfo = uInfo
@@ -314,7 +315,7 @@ createUser r n e = auth (createUserBasic n e) & query .~ [("requester_id", r)]
314315-- doesn't require a 'RequesterId'.
315316createUserBasic :: Text -- ^ 'cuName'
316317 -> Address -- ^ 'cuEmail'
317− -> Request CreateUser Basic User
318+ -> Request CreateUser 'Basic User
318319createUserBasic n e =
319320 mk CreateUser
320321 { _cuName' = n
src/Network/PagerDuty/REST/Users/ContactMethods.hs+213−12
@@ -1,8 +1,11 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
4+
5+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
36
47-- Module : Network.PagerDuty.REST.Users.ContactMethods
5−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
69-- License : This Source Code Form is subject to the terms of
710-- the Mozilla Public License, v. 2.0.
811-- A copy of the MPL can be found in the LICENSE file or
@@ -20,16 +23,214 @@
2023-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/contact_methods>
2124module Network.PagerDuty.REST.Users.ContactMethods
2225 (
26+ -- * List Contacts
27+ listContacts
28+
29+ -- * Create Contact
30+ , CreateContact
31+ , createContact
32+ , ccType
33+ , ccAddress
34+ , ccCountryCode
35+ , ccLabel
36+ , ccSendShortEmail
37+
38+ -- * Get Contact
39+ , getContact
40+
41+ -- * Update Contact
42+ , UpdateContact
43+ , updateContact
44+ , ucAddress
45+ , ucCountryCode
46+ , ucLabel
47+ , ucSendShortEmail
48+
49+ -- * Delete Contact
50+ , deleteContact
51+
52+ -- * Types
53+ , ContactType (..)
54+
55+ , HasContact (..)
56+ , Contact
2357 ) where
2458
25−import Control.Lens
26−import Data.Monoid
27−import Data.Text (Text)
28−import Data.Time
29−import Network.HTTP.Types
30−import Network.PagerDuty.TH
31−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
65+
66+default (Path)
67+
68+contacts :: UserId -> Path
69+contacts u = "users" % u % "contact_methods"
70+
71+data ContactType
72+ = SMS
73+ | Phone
74+ | Email
75+ deriving (Eq, Show)
76+
77+deriveNullary ''ContactType
78+
79+data Contact = Contact
80+ { _cId :: ContactId
81+ , _cUserId :: UserId
82+ , _cLabel :: Text
83+ , _cAddress :: Address
84+ , _cType :: !ContactType
85+ , _cCountryCode :: Maybe Int
86+ , _cSendShortEmail :: Maybe Bool'
87+ , _cBlacklisted :: Maybe Bool'
88+ } deriving (Eq, Show)
89+
90+deriveJSON ''Contact
91+makeClassy ''Contact
92+
93+-- | List existing contact methods for the specified user.
94+--
95+-- @GET \/users\/\:user_id\/contact_methods@
96+--
97+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/contact_methods/list>
98+listContacts :: UserId -> Request Empty s [Contact]
99+listContacts u = empty & path .~ contacts u
100+
101+-- | Get details for a contact method.
102+--
103+-- @GET \/users\/\:user_id\/contact_methods\/\:id@
104+--
105+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/contact_methods/show>
106+getContact :: UserId -> ContactId -> Request Empty s Contact
107+getContact u c = empty & path .~ contacts u % c
108+
109+data CreateContact = CreateContact
110+ { _ccType' :: !ContactType
111+ , _ccAddress' :: Address
112+ , _ccCountryCode' :: Maybe Int
113+ , _ccLabel' :: Maybe Text
114+ , _ccSendShortEmail' :: Maybe Bool'
115+ } deriving (Eq, Show)
116+
117+jsonRequest ''CreateContact
118+
119+-- | The type of the contact method.
120+ccType :: Lens' (Request CreateContact s b) ContactType
121+ccType = upd.ccType'
122+
123+-- | The id of the contact method. For 'SMS' and 'Phone' it is the number, and for
124+-- 'Email' it is the email address.
125+ccAddress :: Lens' (Request CreateContact s b) Address
126+ccAddress = upd.ccAddress'
127+
128+-- | The number code for your country. Not used for 'Email'.
129+--
130+-- /Default:/ 1
131+ccCountryCode :: Lens' (Request CreateContact s b) (Maybe Int)
132+ccCountryCode = upd.ccCountryCode'
133+
134+-- | A human friendly label for the contact method.
135+--
136+-- /Example:/ "Home Phone", "Work Email", etc.
137+--
138+-- /Default:/ The type of the contact method and the address (with country code
139+-- for phone numbers).
140+ccLabel :: Lens' (Request CreateContact s b) (Maybe Text)
141+ccLabel = upd.ccLabel'
142+
143+-- | Send an abbreviated email message instead of the standard email
144+-- output. Useful for email-to-SMS gateways and email based pagers. Only valid for
145+-- 'Email' contact methods.
146+--
147+-- /Default:/ false.
148+ccSendShortEmail :: Lens' (Request CreateContact s b) (Maybe Bool)
149+ccSendShortEmail = upd.ccSendShortEmail'.mapping _B
150+
151+-- | Create a new contact method for a given user. A contact method can be one
152+-- of the following types: SMS, email, and phone. push_notification contact
153+-- methods cannot be created using this API, they are added automatically during
154+-- device registration.
155+--
156+-- @POST \/users\/\:user_id\/contact_methods@
157+--
158+-- /Note:/ The contact info must be unique.
159+--
160+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/contact_methods/create>
161+createContact :: UserId
162+ -> ContactType
163+ -> Address
164+ -> Request CreateContact s Contact
165+createContact u t a =
166+ mk CreateContact
167+ { _ccType' = t
168+ , _ccAddress' = a
169+ , _ccCountryCode' = Nothing
170+ , _ccLabel' = Nothing
171+ , _ccSendShortEmail' = Nothing
172+ } & meth .~ POST
173+ & path .~ contacts u
174+ & unwrap .~ key "contact_method"
175+
176+data UpdateContact = UpdateContact
177+ { _ucAddress' :: Maybe Address
178+ , _ucCountryCode' :: Maybe Int
179+ , _ucLabel' :: Maybe Text
180+ , _ucSendShortEmail' :: Maybe Bool'
181+ } deriving (Eq, Show)
182+
183+jsonRequest ''UpdateContact
32184
33−users :: Path
34−users = "users"
185+-- | The id of the contact method. For 'SMS' and 'Phone' it is the number, and for
186+-- 'Email' it is the email address.
187+ucAddress :: Lens' (Request UpdateContact s b) (Maybe Address)
188+ucAddress = upd.ucAddress'
35189
190+-- | The number code for your country. Not used for 'Email'.
191+--
192+-- /Default:/ 1
193+ucCountryCode :: Lens' (Request UpdateContact s b) (Maybe Int)
194+ucCountryCode = upd.ucCountryCode'
195+
196+-- | A human friendly label for the contact method.
197+--
198+-- /Example:/ "Home Phone", "Work Email", etc.
199+--
200+-- /Default:/ The type of the contact method and the address (with country code
201+-- for phone numbers).
202+ucLabel :: Lens' (Request UpdateContact s b) (Maybe Text)
203+ucLabel = upd.ucLabel'
204+
205+-- | Send an abbreviated email message instead of the standard email
206+-- output. Useful for email-to-SMS gateways and email based pagers. Only valid for
207+-- 'Email' contact methods.
208+--
209+-- /Default:/ false.
210+ucSendShortEmail :: Lens' (Request UpdateContact s b) (Maybe Bool)
211+ucSendShortEmail = upd.ucSendShortEmail'.mapping _B
212+
213+-- | Update an existing contact method of a given user. Note that you cannot
214+-- change the type of an existing method.
215+--
216+-- @PUT \/users\/\:user_id\/contact_methods\/\:id@
217+--
218+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/contact_methods/update>
219+updateContact :: UserId -> ContactId -> Request UpdateContact s Contact
220+updateContact u c =
221+ mk UpdateContact
222+ { _ucAddress' = Nothing
223+ , _ucCountryCode' = Nothing
224+ , _ucLabel' = Nothing
225+ , _ucSendShortEmail' = Nothing
226+ } & meth .~ PUT
227+ & path .~ contacts u % c
228+ & unwrap .~ key "contact_method"
229+
230+-- | Remove a contact method and any corresponding notification rules.
231+--
232+-- @DELETE \/users\/\:user_id\/contact_methods\/\:id@
233+--
234+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/contact_methods/delete>
235+deleteContact :: UserId -> ContactId -> Request Empty s Empty
236+deleteContact u c = empty & meth .~ DELETE & path .~ contacts u % c
src/Network/PagerDuty/REST/Users/NotificationRules.hs+141−12
@@ -1,8 +1,11 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
4+
5+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
36
47-- Module : Network.PagerDuty.REST.Users.NotificationRules
5−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
69-- License : This Source Code Form is subject to the terms of
710-- the Mozilla Public License, v. 2.0.
811-- A copy of the MPL can be found in the LICENSE file or
@@ -20,16 +23,142 @@
2023-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/notification_rules>
2124module Network.PagerDuty.REST.Users.NotificationRules
2225 (
26+ -- * List Rules
27+ listRules
28+
29+ -- * Create Rule
30+ , CreateRule
31+ , createRule
32+ , crStartDelayInMinutes
33+ , crContactMethodId
34+
35+ -- * Get Rule
36+ , getRule
37+
38+ -- * Update Rule
39+ , UpdateRule
40+ , updateRule
41+ , urStartDelayInMinutes
42+ , urContactMethodId
43+
44+ -- * Delete Rule
45+ , deleteRule
46+
47+ -- * Types
48+ , Rule
49+ , rId
50+ , rStartDelayInMinutes
51+ , rContactMethod
2352 ) where
2453
25−import Control.Lens
26−import Data.Monoid
27−import Data.Text (Text)
28−import Data.Time
29−import Network.HTTP.Types
30−import Network.PagerDuty.TH
31−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
60+
61+default (Path)
62+
63+rules :: UserId -> Path
64+rules u = "users" % u % "notification_rules"
65+
66+data Rule = Rule
67+ { _rId :: NotificationRuleId
68+ , _rStartDelayInMinutes :: !Int
69+ , _rContactMethod :: Contact
70+ } deriving (Eq, Show)
71+
72+deriveJSON ''Rule
73+makeLenses ''Rule
74+
75+instance HasContact Rule where
76+ contact = rContactMethod
77+
78+-- | List existing notification rules for the specified user.
79+--
80+-- @GET \/users\/\:user_id\/notification_rules@
81+--
82+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/notification_rules/list>
83+listRules :: UserId -> Request Empty s Rule
84+listRules u = empty & path .~ rules u
85+
86+-- | Get details for a notification rule.
87+--
88+-- @GET \/users\/\:user_id\/notification_rules\/\:id@
89+--
90+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/notification_rules/show>
91+getRule :: UserId -> NotificationRuleId -> Request Empty s Rule
92+getRule u n = empty & path .~ rules u % n
93+
94+data CreateRule = CreateRule
95+ { _crStartDelayInMinutes' :: !Int
96+ , _crContactMethodId' :: ContactId
97+ } deriving (Eq, Show)
98+
99+jsonRequest ''CreateRule
100+
101+-- | Number of minutes it will take for the notification rule to be activated
102+-- (from the time the incident is assigned to the owning user) and an alert be
103+-- fired.
104+crStartDelayInMinutes :: Lens' (Request CreateRule s b) Int
105+crStartDelayInMinutes = upd.crStartDelayInMinutes'
106+
107+-- | The id of the contact method.
108+crContactMethodId :: Lens' (Request CreateRule s b) ContactId
109+crContactMethodId = upd.crContactMethodId'
110+
111+-- | Create a new notification rule for the specified user.
112+--
113+-- @POST \/users\/\:user_id\/notification_rules@
114+--
115+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/notification_rules/create>
116+createRule :: UserId -> ContactId -> Int -> Request CreateRule s Rule
117+createRule u c n =
118+ mk CreateRule
119+ { _crStartDelayInMinutes' = n
120+ , _crContactMethodId' = c
121+ } & meth .~ POST
122+ & path .~ rules u
123+ & unwrap .~ key "notification_rule"
124+
125+data UpdateRule = UpdateRule
126+ { _urStartDelayInMinutes' :: Maybe Int
127+ , _urContactMethodId' :: Maybe ContactId
128+ } deriving (Eq, Show)
129+
130+jsonRequest ''UpdateRule
131+
132+-- | Number of minutes it will take for the notification rule to be activated
133+-- (from the time the incident is assigned to the owning user) and an alert be
134+-- fired.
135+urStartDelayInMinutes :: Lens' (Request UpdateRule s b) (Maybe Int)
136+urStartDelayInMinutes = upd.urStartDelayInMinutes'
137+
138+-- | The id of the contact method.
139+urContactMethodId :: Lens' (Request UpdateRule s b) (Maybe ContactId)
140+urContactMethodId = upd.urContactMethodId'
32141
33−users :: Path
34−users = "users"
142+-- | Update an existing notification rule.
143+--
144+-- @PUT \/users\/\:user_id\/notification_rules\/\:id@
145+--
146+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/notification_rules/update>
147+updateRule :: UserId -> NotificationRuleId -> Request UpdateRule s Rule
148+updateRule u r =
149+ mk UpdateRule
150+ { _urStartDelayInMinutes' = Nothing
151+ , _urContactMethodId' = Nothing
152+ } & meth .~ PUT
153+ & path .~ rules u % r
154+ & unwrap .~ key "notification_rule"
35155
156+-- | Remove a notification rule.
157+--
158+-- @DELETE \/users\/\:user_id\/notification_rules\/\:id@
159+--
160+-- /See:/ <http://developer.pagerduty.com/documentation/rest/users/notification_rules/delete>
161+deleteRule :: UserId
162+ -> NotificationRuleId
163+ -> Request Empty s Empty
164+deleteRule u n = empty & meth .~ DELETE & path .~ rules u % n
src/Network/PagerDuty/REST/Webhooks.hs+89−5
@@ -1,8 +1,9 @@
1+{-# LANGUAGE LambdaCase #-}
12{-# LANGUAGE OverloadedStrings #-}
23{-# LANGUAGE TemplateHaskell #-}
34
45-- Module : Network.PagerDuty.REST.Webhooks
5−-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
6+-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
67-- License : This Source Code Form is subject to the terms of
78-- the Mozilla Public License, v. 2.0.
89-- A copy of the MPL can be found in the LICENSE file or
@@ -24,9 +25,92 @@
2425--
2526-- /See:/ <http://developer.pagerduty.com/documentation/rest/webhooks>
2627module Network.PagerDuty.REST.Webhooks
27− (
28−
28+ ( WebhookType (..)
29+ , Webhook
30+ , wId
31+ , wType
32+ , wCreatedOn
2933 ) where
3034
31−-- Just create the types + fromJSON instances
32−decodeWebhook = undefined
35+import Control.Applicative hiding (empty)
36+import Control.Lens
37+import Data.Aeson
38+import Data.ByteString.Conversion (ToByteString (..),
39+ toByteString')
40+import Data.Text (Text)
41+import qualified Data.Text.Encoding as Text
42+import Data.Time
43+import Network.PagerDuty.Internal.TH
44+import Network.PagerDuty.Internal.Types
45+import Network.PagerDuty.REST.Incidents
46+
47+data WebhookType
48+ = WTrigger
49+ -- ^ Sent when an incident is newly created/triggered.
50+ | WAcknowledge
51+ -- ^ Sent when an incident has had its status changed from triggered to
52+ -- acknowledged.
53+ | WUnacknowledge
54+ -- ^ Sent when an incident is unacknowledged due to timeout.
55+ | WResolve
56+ -- ^ Sent when an incident has been resolved.
57+ | WAssign
58+ -- ^ Sent when an incident has been manually reassigned to another user
59+ -- in a different escalation chain.
60+ | WEscalate
61+ -- ^ Sent when an incident has been escalated to another user in the
62+ -- same escalation chain.
63+ | WDelegate
64+ -- ^ Sent when an incident has been reassigned to another escalation chain.
65+ | WOther Text
66+ -- ^ /Note:/ As new types of incident actions are supported,
67+ -- new incident webhook message types will be added.
68+ deriving (Eq, Show)
69+
70+instance ToByteString WebhookType where
71+ builder = \case
72+ WTrigger -> "incident.trigger"
73+ WAcknowledge -> "incident.acknowledge"
74+ WUnacknowledge -> "incident.unacknowledge"
75+ WResolve -> "incident.resolve"
76+ WAssign -> "incident.assign"
77+ WEscalate -> "incident.escalate"
78+ WDelegate -> "incident.delegate"
79+ WOther t -> builder t
80+
81+instance FromJSON WebhookType where
82+ parseJSON = withText "status" $ pure . \case
83+ "incident.trigger" -> WTrigger
84+ "incident.acknowledge" -> WAcknowledge
85+ "incident.unacknowledge" -> WUnacknowledge
86+ "incident.resolve" -> WResolve
87+ "incident.assign" -> WAssign
88+ "incident.escalate" -> WEscalate
89+ "incident.delegate" -> WDelegate
90+ t -> (WOther t)
91+
92+instance ToJSON WebhookType where
93+ toJSON = String . Text.decodeUtf8 . toByteString'
94+
95+data Webhook = Webhook
96+ { _wId :: WebhookId
97+ , _wType :: !WebhookType
98+ , _wCreatedOn :: !Date
99+ , _wData :: Incident
100+ } deriving (Eq, Show)
101+
102+deriveJSON ''Webhook
103+
104+instance HasIncident Webhook where
105+ incident = lens _wData (\s x -> s { _wData = x })
106+
107+-- | Uniquely identifies this outgoing webhook message; can be used for
108+-- idempotency when processing the messages.
109+makeLens "_wId" ''Webhook
110+
111+-- | The webhook message type.
112+makeLens "_wType" ''Webhook
113+
114+-- | The date/time when the incident changed state.
115+wCreatedOn :: Lens' Webhook UTCTime
116+wCreatedOn = lens _wCreatedOn (\i x -> i { _wCreatedOn = x }) . _D
src/Network/PagerDuty/Types.hs+84−429
@@ -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,417 +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
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 EmailFilterId = Id "email-filter"
402−type IncidentId = Id "incident"
403−type LogEntryId = Id "log-entry"
404−type NoteId = Id "note"
405−type OverrideId = Id "schedule-override"
406−type PolicyId = Id "escalation-policy"
407−type RequesterId = Id "requester"
408−type RuleId = Id "rule"
409−type ScheduleId = Id "schedule"
410−type ServiceId = Id "service"
411−type UserId = Id "user"
412−type VendorId = Id "vendor"
413−type WindowId = Id "maintenance-window"
414−
415−data Empty = Empty
416−
417−instance ToJSON Empty where
418− toJSON = const (object [])
419−
420−instance FromJSON Empty where
421− parseJSON = withObject "empty" f
422− where
423− f !o | Map.null o = pure Empty
424− | otherwise = fail "Unexpected non-empty JSON object."
425−
426−instance QueryLike Empty where
427− toQuery = const []
428−
429−newtype Address = Address Text
430− deriving (Eq, Show)
431−
432−deriveJSON ''Address
433−makePrisms ''Address
434−
435−instance ToByteString Address where
436− builder (Address a) = builder a
437−
438−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]