git.iko.soy/typeable/pagerduty
on 163eb08 help sign in
38 files changed+1089−1311
since splitsnapshots
unifiedsplit
.gitignore−1 .travis.yml−30 Makefile+20 README.md−14 pagerduty.cabal+29−41 script/generate-pages+25 script/travis-lifecycle-before_install−11 script/travis-lifecycle-install−13 script/travis-lifecycle-script−9 script/travis-timeout−15 script/upload-documentation+37 src/Control/Monad/Trans/PagerDuty.hs+72−55 src/Network/PagerDuty/IO.hs+66 src/Network/PagerDuty/Integration.hs+150−190 src/Network/PagerDuty/Internal/IO.hs−76 src/Network/PagerDuty/Internal/Types.hs−497 src/Network/PagerDuty/Internal/Options.hs → src/Network/PagerDuty/Options.hs+6−6 src/Network/PagerDuty/Internal/Query.hs → src/Network/PagerDuty/Query.hs+15−17 src/Network/PagerDuty/REST.hs+30−42 src/Network/PagerDuty/REST/Alerts.hs+7−7 src/Network/PagerDuty/REST/EscalationPolicies.hs+14−14 src/Network/PagerDuty/REST/EscalationPolicies/EscalationRules.hs+11−11 src/Network/PagerDuty/REST/Incidents.hs+27−23 src/Network/PagerDuty/REST/Incidents/Notes.hs+12−12 src/Network/PagerDuty/REST/LogEntries.hs+9−8 src/Network/PagerDuty/REST/MaintenanceWindows.hs+10−10 src/Network/PagerDuty/REST/Reports.hs+11−11 src/Network/PagerDuty/REST/Schedules.hs+14−14 src/Network/PagerDuty/REST/Schedules/Overrides.hs+12−12 src/Network/PagerDuty/REST/Services.hs+16−16 src/Network/PagerDuty/REST/Services/EmailFilters.hs+14−14 src/Network/PagerDuty/REST/Users.hs+17−17 src/Network/PagerDuty/REST/Users/ContactMethods.hs+10−10 src/Network/PagerDuty/REST/Users/NotificationRules.hs+10−10 src/Network/PagerDuty/REST/Webhooks.hs+4−5 src/Network/PagerDuty/Internal/TH.hs → src/Network/PagerDuty/TH.hs+9−9 src/Network/PagerDuty/Types.hs+432−84 stack.yaml−7
.gitignore−1
@@ -9,7 +9,6 @@
99cabal.sandbox.config
1010
1111# Dirs
12−.stack-work
1312cabal-dev
1413bin
1514dist
.travis.ymldeleted−30
@@ -1,30 +0,0 @@
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] } }
Makefilenew file+20
@@ -0,0 +1,20 @@
1+FLAGS := -j --disable-documentation --disable-library-coverage
2+
3+build:
4+ cabal build $(addprefix -,$(findstring j,$(MAKEFLAGS)))
5+
6+all:
7+ make clean; make install && make build
8+
9+install: cabal.sandbox.config
10+ cabal install $(FLAGS) --only-dependencies
11+
12+clean:
13+ cabal clean
14+ rm -rf cabal.sandbox.config .cabal-sandbox
15+
16+doc:
17+ cabal haddock
18+
19+cabal.sandbox.config:
20+ cabal sandbox init
README.md−14
@@ -1,14 +0,0 @@
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+29−41
@@ -1,32 +1,21 @@
11name: pagerduty
2−version: 0.0.8
3−synopsis: Client library for PagerDuty Integration and REST APIs.
2+version: 0.1.0
3+synopsis: Pager Duty API Client
44homepage: http://github.com/brendanhay/pagerduty
55license: OtherLicense
66license-file: LICENSE
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
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
1111build-type: Simple
1212cabal-version: >= 1.10
1313
1414description:
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:
15+ Client library for the the PagerDuty REST APIs documented here:
2116 .
2217 * Integration API - <http://developer.pagerduty.com/documentation/integration>
23− .
2418 * 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>.
3019
3120extra-source-files:
3221 README.md
@@ -63,35 +52,34 @@ library
6352 , Network.PagerDuty.REST.Webhooks
6453
6554 other-modules:
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
55+ Network.PagerDuty.IO
56+ , Network.PagerDuty.Options
57+ , Network.PagerDuty.Query
58+ , Network.PagerDuty.TH
7159 , Network.PagerDuty.Types
7260
7361 build-depends:
74− aeson >= 2.0
75− , base >= 4.7 && < 5
76− , bifunctors >= 4.1
62+ aeson > 0.7 && <= 0.8
63+ , base >= 4.5 && < 5.0
64+ , bifunctors
7765 , bytestring >= 0.9
7866 , bytestring-conversion >= 0.2.1
79− , conduit > 1.1
80− , data-default-class >= 0.0.1
67+ , conduit >= 0.5.5
68+ , data-default-class
8169 , exceptions >= 0.6
82− , generics-sop >= 0.5.0.0
83− , http-client >= 0.5 && < 1
70+ , http-client >= 0.3.6
8471 , 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
72+ , lens >= 4.0
73+ , lens-aeson >= 1.0
74+ , mmorph >= 1.0
75+ , mtl >= 2.2.1
76+ , old-locale
9177 , 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
78+ , time == 1.4.*
79+ , transformers >= 0.4.1
9780 , unordered-containers >= 0.2.3
81+
82+ , generics-sop
83+ , monad-control
84+ , template-haskell
85+ , transformers-base
script/generate-pagesnew file+25
@@ -0,0 +1,25 @@
1+#!/usr/bin/env bash
2+
3+set -e
4+set -x
5+set -o errexit
6+
7+branch=$(git symbolic-ref -q HEAD)
8+branch=${branch##refs/heads/}
9+branch=${branch:-HEAD}
10+
11+cabal configure --disable-tests
12+
13+DOCDIR=`mktemp -d -t pages.XXXXXX`
14+cabal haddock --haddock-option=-o$DOCDIR
15+
16+HEAD=`git rev-parse HEAD`
17+
18+git checkout gh-pages
19+
20+mv $DOCDIR/* .
21+
22+git add *.html *.js *.css *.gif *.png
23+git commit -m "Generated documentation from $HEAD on $branch"
24+git push origin gh-pages
25+git checkout $branch
script/travis-lifecycle-before_installdeleted−11
@@ -1,11 +0,0 @@
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-installdeleted−13
@@ -1,13 +0,0 @@
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-scriptdeleted−9
@@ -1,9 +0,0 @@
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-timeoutdeleted−15
@@ -1,15 +0,0 @@
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
script/upload-documentationnew file+37
@@ -0,0 +1,37 @@
1+#!/usr/bin/env bash
2+
3+set -e
4+
5+package=${PWD##*/}
6+
7+echo "Package: ${package}"
8+read -p "Version: " version
9+read -p "Hackage user: " user
10+read -sp "Hackage password (not echoed): " password
11+
12+echo
13+echo "BUILDING"
14+echo
15+
16+cabal configure
17+cabal build
18+cabal haddock \
19+ --hyperlink-source \
20+ --html-location='/package/$pkg-$version/docs' \
21+ --contents-location='/package/$pkg'
22+
23+echo
24+echo "ARCHIVING"
25+echo
26+
27+cd dist/doc/html
28+DDIR="${package}-${version}-docs"
29+cp -r "${package}" "${DDIR}" && gtar -c -v -z -Hustar -f "${DDIR}.tar.gz" "${DDIR}"
30+
31+echo
32+echo "UPLOADING"
33+echo
34+
35+curl -X PUT -H 'Content-Type: application/x-tar' \
36+ -H 'Content-Encoding: gzip' --data-binary "@${DDIR}.tar.gz" \
37+ "http://${user}:${password}@hackage.haskell.org/package/${package}-${version}/docs"
src/Control/Monad/Trans/PagerDuty.hs+72−55
@@ -2,12 +2,15 @@
22{-# LANGUAGE FlexibleContexts #-}
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5+{-# LANGUAGE KindSignatures #-}
56{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE RecordWildCards #-}
8+{-# LANGUAGE TemplateHaskell #-}
69{-# LANGUAGE TypeFamilies #-}
710{-# LANGUAGE UndecidableInstances #-}
811
912-- Module : Control.Monad.Trans.PagerDuty
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
13+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1114-- License : This Source Code Form is subject to the terms of
1215-- the Mozilla Public License, v. 2.0.
1316-- A copy of the MPL can be found in the LICENSE file or
@@ -19,50 +22,57 @@
1922module Control.Monad.Trans.PagerDuty
2023 (
2124 -- * Transformer
22− PagerDuty
23− , PagerDutyT
25+ PD
26+ , PDT
2427
25− -- * Running
26− , runPagerDutyT
28+ -- * Run
29+ , runPDT
2730
28− -- * Integration events
31+ -- * Environment
32+ , Env
33+ , envDomain
34+ , envAuth
35+ , envManager
36+-- , envLogging
37+
38+ -- * Integration API
2939 , submit
30− , submitCatch
3140
32− -- * REST requests
41+ -- * REST API
3342 , send
34− , sendCatch
3543 , paginate
36− , paginateCatch
37−
38− -- ** Lifting errors
39− , hoistError
40−
41− , module Network.PagerDuty.Types
4244 ) where
4345
4446import Control.Applicative
45−import Control.Monad
47+import Control.Lens
4648import Control.Monad.Base
4749import Control.Monad.Catch
48−import Control.Monad.Except (MonadError (..))
50+import Control.Monad.Except
4951import Control.Monad.Morph
5052import Control.Monad.Reader
5153import Control.Monad.Trans.Control
52−import Control.Monad.Trans.Except
5354import Data.Aeson
5455import Data.Conduit
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
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
5960import Network.PagerDuty.Types
6061
61−-- | A convenient alias for 'PagerDutyT' 'IO'.
62−type PagerDuty s = PagerDutyT s IO
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
6373
64−newtype PagerDutyT s m a = PagerDutyT
65− { unPagerDutyT :: ReaderT (Env s) (ExceptT Error m) a
74+newtype PDT s m a = PDT
75+ { unPDT :: ReaderT (Env s) (ExceptT Error m) a
6676 } deriving
6777 ( Functor
6878 , Applicative
@@ -74,48 +84,50 @@ newtype PagerDutyT s m a = PagerDutyT
7484 , MonadError Error
7585 )
7686
77−instance MonadTrans (PagerDutyT s) where
78− lift = PagerDutyT . lift . lift
87+instance MonadTrans (PDT s) where
88+ lift = PDT . lift . lift
7989 {-# INLINE lift #-}
8090
81−instance MonadBase b m => MonadBase b (PagerDutyT s m) where
91+instance MonadBase b m => MonadBase b (PDT s m) where
8292 liftBase = liftBaseDefault
8393 {-# INLINE liftBase #-}
8494
85−instance MonadTransControl (PagerDutyT s) where
86− type StT (PagerDutyT s) a = StT (ExceptT Error) (StT (ReaderT (Env s)) a)
95+instance MonadTransControl (PDT s) where
96+ newtype StT (PDT s) a = StTAWS
97+ { unStTAWS :: StT (ExceptT Error) (StT (ReaderT (Env s)) a)
98+ }
8799
88− liftWith f = PagerDutyT $
100+ liftWith f = PDT $
89101 liftWith $ \g ->
90− liftWith $ \h ->
91− f (h . g . unPagerDutyT)
102+ liftWith $ \h ->
103+ f (liftM StTAWS . h . g . unPDT)
92104 {-# INLINE liftWith #-}
93105
94− restoreT = PagerDutyT . restoreT . restoreT
106+ restoreT = PDT . restoreT . restoreT . liftM unStTAWS
95107 {-# INLINE restoreT #-}
96108
97−instance MonadBaseControl b m => MonadBaseControl b (PagerDutyT s m) where
98− type StM (PagerDutyT s m) a = ComposeSt (PagerDutyT s) m a
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 }
99111
100− liftBaseWith = defaultLiftBaseWith
112+ liftBaseWith = defaultLiftBaseWith StMPDT
101113 {-# INLINE liftBaseWith #-}
102114
103− restoreM = defaultRestoreM
115+ restoreM = defaultRestoreM unStMPDT
104116 {-# INLINE restoreM #-}
105117
106−instance MFunctor (PagerDutyT s) where
107− hoist nat m = PagerDutyT (ReaderT (ExceptT . nat . runPagerDutyT m))
118+instance MFunctor (PDT s) where
119+ hoist nat m = PDT (ReaderT (ExceptT . nat . runPDT m))
108120 {-# INLINE hoist #-}
109121
110−instance MMonad (PagerDutyT s) where
111− embed f m = ask >>= f . runPagerDutyT m >>= either throwError return
122+instance MMonad (PDT s) where
123+ embed f m = ask >>= f . runPDT m >>= either throwError return
112124 {-# INLINE embed #-}
113125
114−runPagerDutyT :: PagerDutyT s m a -> Env s -> m (Either Error a)
115−runPagerDutyT (PagerDutyT k) = runExceptT . runReaderT k
126+runPDT :: PDT s m a -> Env s -> m (Either Error a)
127+runPDT (PDT k) = runExceptT . runReaderT k
116128
117−hoistError :: (MonadError Error m) => Either Error a -> m a
118−hoistError = either throwError return
129+hoistEither :: (MonadError Error m) => Either Error a -> m a
130+hoistEither = either throwError return
119131
120132scoped :: MonadReader (Env s) m => (Env s -> m a) -> m a
121133scoped f = ask >>= f
@@ -123,17 +135,20 @@ scoped f = ask >>= f
123135submit :: ( MonadIO m
124136 , MonadReader (Env s) m
125137 , MonadError Error m
138+ , Event a
126139 )
127− => Event
140+ => a
128141 -> m Response
129−submit = submitCatch >=> hoistError
142+submit = submitCatch >=> hoistEither
130143
131144submitCatch :: ( MonadIO m
132145 , MonadReader (Env s) m
146+ , Event a
133147 )
134− => Event
148+ => a
135149 -> m (Either Error Response)
136−submitCatch x = scoped $ \e -> Int.submitWith (_envManager e) (_envLogger e) x
150+submitCatch x = scoped $ \e ->
151+ Int.submit (_envManager e) x
137152
138153send :: ( MonadIO m
139154 , MonadReader (Env s) m
@@ -142,7 +157,7 @@ send :: ( MonadIO m
142157 )
143158 => Request a s b
144159 -> m b
145−send = sendCatch >=> hoistError
160+send = sendCatch >=> hoistEither
146161
147162sendCatch :: ( MonadIO m
148163 , MonadReader (Env s) m
@@ -150,7 +165,8 @@ sendCatch :: ( MonadIO m
150165 )
151166 => Request a s b
152167 -> m (Either Error b)
153−sendCatch x = scoped (`REST.sendWith` x)
168+sendCatch x = scoped $ \Env{..} ->
169+ REST.send _envAuth _envDomain _envManager x
154170
155171paginate :: ( MonadIO m
156172 , MonadReader (Env s) m
@@ -160,7 +176,7 @@ paginate :: ( MonadIO m
160176 )
161177 => Request a s b
162178 -> Source m b
163−paginate x = paginateCatch x $= awaitForever (hoistError >=> yield)
179+paginate x = paginateCatch x $= awaitForever (hoistEither >=> yield)
164180
165181paginateCatch :: ( MonadIO m
166182 , MonadReader (Env s) m
@@ -169,4 +185,5 @@ paginateCatch :: ( MonadIO m
169185 )
170186 => Request a s b
171187 -> Source m (Either Error b)
172−paginateCatch x = scoped (`REST.paginateWith` x)
188+paginateCatch x = scoped $ \Env{..} ->
189+ REST.paginate _envAuth _envDomain _envManager x
src/Network/PagerDuty/IO.hsnew file+66
@@ -0,0 +1,66 @@
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+150−190
@@ -1,12 +1,10 @@
1−{-# LANGUAGE FlexibleInstances #-}
2−{-# LANGUAGE FunctionalDependencies #-}
3−{-# LANGUAGE LambdaCase #-}
4−{-# LANGUAGE MultiParamTypeClasses #-}
5−{-# LANGUAGE OverloadedStrings #-}
6−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE GADTs #-}
2+{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
75
86-- Module : Network.PagerDuty.Integration
9−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
7+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
108-- License : This Source Code Form is subject to the terms of
119-- the Mozilla Public License, v. 2.0.
1210-- A copy of the MPL can be found in the LICENSE file or
@@ -38,57 +36,52 @@
3836-- /See:/ <http://developer.pagerduty.com/documentation/integration/events>
3937module Network.PagerDuty.Integration
4038 (
41− -- * Sending events
39+ -- * Events
4240 submit
43− , submitWith
4441
4542 -- ** Trigger
4643 , Trigger
4744 , trigger
48− , client
49− , clientUrl
45+ , tDescription
46+ , tIncidentKey
47+ , tClient
48+ , tClientUrl
49+ , tDetails
5050
5151 -- ** Acknowledge
5252 , Acknowledge
5353 , acknowledge
54+ , aDescription
55+ , aDetails
5456
5557 -- ** Resolve
5658 , Resolve
5759 , resolve
58−
59− -- * Fields
60− , HasServiceKey (..)
61− , HasIncidentKey (..)
62− , HasDescription (..)
63− , HasDetails (..)
60+ , rDescription
61+ , rDetails
6462
6563 -- * Types
66− , Event (..)
67− , _Trigger
68− , _Acknowledge
69− , _Resolve
64+ , Event
65+ , AnyEvent (..)
7066
7167 , Response
7268 , rsStatus
7369 , rsMessage
7470 , rsIncidentKey
75−
76− , Generic
77−
78− , module Network.PagerDuty.Types
7971 ) where
8072
8173import Control.Lens
8274import Control.Monad.IO.Class
8375import Data.Aeson
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)
76+import Data.Default.Class
77+import qualified Data.HashMap.Strict as Map
78+import Data.Monoid
79+import Data.Text (Text)
80+import Network.HTTP.Client (Manager)
81+import qualified Network.HTTP.Client as Client
82+import Network.PagerDuty.IO
83+import Network.PagerDuty.TH
84+import Network.PagerDuty.Types
9285
9386data Response = Response
9487 { _rsStatus :: Text
@@ -107,161 +100,128 @@ makeLens "_rsMessage" ''Response
107100-- | The key of the incident that will be affected by the request.
108101makeLens "_rsIncidentKey" ''Response
109102
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
143− } deriving (Eq, Show)
103+class Event a where
104+ eventType :: a -> Text
105+ eventPayload :: a -> Object
144106
145−deriveRecord ''Trigger
107+ default eventPayload :: ToJSON a => a -> Object
108+ eventPayload x = let Object o = toJSON x in o
146109
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'
110+data AnyEvent where
111+ Event :: Event a => a -> AnyEvent
151112
152−-- | The name of the monitoring client that is triggering this event.
153−client :: Lens' Trigger (Maybe Text)
154−client = tClient'
113+instance Event AnyEvent where
114+ eventType (Event x) = eventType x
115+ eventPayload (Event x) = eventPayload x
155116
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
117+data Generic = Generic
118+ { _gServiceKey :: ServiceKey
119+ , _gDescription :: Maybe Text
120+ , _gIncidentKey :: IncidentKey
121+ , _gDetails :: Object
165122 } deriving (Eq, Show)
166123
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
124+deriveJSON ''Generic
125+
126+makeLens "_gDescription" ''Generic
127+makeLens "_gDetails" ''Generic
128+
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)
137+
138+deriveJSON ''Trigger
139+
140+instance Event Trigger where
141+ eventType = const "trigger"
228142
229143-- | Your monitoring tools should send PagerDuty a trigger event to report a new
230144-- or ongoing problem. When PagerDuty receives a trigger event, it will either open
231145-- a new incident, or add a new trigger log entry to an existing incident,
232146-- depending on the provided incident_key.
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
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
245158 }
246159
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+
247192-- | Acknowledge events cause the referenced incident to enter the acknowledged
248193-- state.
249194--
250195-- While an incident is acknowledged, it won't generate any additional
251196-- notifications, even if it receives new trigger events. Your monitoring tools
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
197+-- should send PagerDuty an acknowledge event when they know someone is presently
198+-- working on the problem.
199+acknowledge :: ServiceKey -> IncidentKey -> Acknowledge
257200acknowledge k i =
258− Acknowledge Generic'
259− { _gServiceKey' = k
260− , _gIncidentKey' = i
261− , _gDescription' = Nothing
262− , _gDetails' = Nothing
201+ Acknowledge Generic
202+ { _gServiceKey = k
203+ , _gDescription = Nothing
204+ , _gIncidentKey = i
205+ , _gDetails = mempty
263206 }
264207
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+
265225-- | Resolve events cause the referenced incident to enter the resolved state.
266226--
267227-- Once an incident is resolved, it won't generate any additional
@@ -269,30 +229,30 @@ acknowledge k i =
269229-- incident won't re-open the incident. Instead, a new incident will be
270230-- created. Your monitoring tools should send PagerDuty a resolve event when the
271231-- problem that caused the initial trigger event has been fixed.
272−resolve :: ServiceKey -- ^ 'serviceKey'
273− -> IncidentKey -- ^ 'incidentKey'
274− -> Event
232+resolve :: ServiceKey -> IncidentKey -> Resolve
275233resolve k i =
276− Resolve Generic'
277− { _gServiceKey' = k
278− , _gIncidentKey' = i
279− , _gDescription' = Nothing
280− , _gDetails' = Nothing
234+ Resolve Generic
235+ { _gServiceKey = k
236+ , _gDescription = Nothing
237+ , _gIncidentKey = i
238+ , _gDetails = mempty
281239 }
282240
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+
283250-- | Send an event to the integration API.
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− }
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)
src/Network/PagerDuty/Internal/IO.hsdeleted−76
@@ -1,76 +0,0 @@
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/Internal/Types.hsdeleted−497
@@ -1,497 +0,0 @@
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/Internal/Options.hs → src/Network/PagerDuty/Options.hsrenamed+6−6
@@ -1,5 +1,5 @@
1−-- Module : Network.PagerDuty.Internal.Options
2−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
1+-- Module : Network.PagerDuty.Options
2+-- Copyright : (c) 2013-2014 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.Internal.Options
11+module Network.PagerDuty.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/Internal/Query.hs → src/Network/PagerDuty/Query.hsrenamed+15−17
@@ -1,13 +1,12 @@
11{-# LANGUAGE ConstraintKinds #-}
22{-# LANGUAGE DefaultSignatures #-}
3−{-# LANGUAGE FlexibleContexts #-}
43{-# LANGUAGE GADTs #-}
54{-# LANGUAGE OverloadedStrings #-}
65{-# LANGUAGE ScopedTypeVariables #-}
76{-# LANGUAGE TupleSections #-}
87
9−-- Module : Network.PagerDuty.Internal.Query
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Module : Network.PagerDuty.Query
9+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1110-- License : This Source Code Form is subject to the terms of
1211-- the Mozilla Public License, v. 2.0.
1312-- A copy of the MPL can be found in the LICENSE file or
@@ -16,7 +15,7 @@
1615-- Stability : experimental
1716-- Portability : non-portable (GHC extensions)
1817
19−module Network.PagerDuty.Internal.Query
18+module Network.PagerDuty.Query
2019 ( QueryValues (..)
2120 , gquery
2221 , gqueryWith
@@ -24,17 +23,17 @@ module Network.PagerDuty.Internal.Query
2423
2524import Data.Aeson.Types
2625import Data.Bifunctor
27−import Data.ByteString (ByteString)
28−import qualified Data.ByteString.Char8 as BS
26+import Data.ByteString (ByteString)
27+import qualified Data.ByteString.Char8 as BS
2928import Data.ByteString.Conversion
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
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
3534import Generics.SOP
3635import Network.HTTP.Types
37−import Network.PagerDuty.Internal.Options
36+import Network.PagerDuty.Options
3837
3938class QueryValues a where
4039 queryValues :: a -> [ByteString]
@@ -59,15 +58,14 @@ gqueryWith :: forall a. (Generic a, HasDatatypeInfo a, All2 QueryValues (Code a)
5958 -> a
6059 -> Query
6160gqueryWith o a = case datatypeInfo (Proxy :: Proxy a) of
62− ADT _ _ cs _ -> go cs (from a)
63− Newtype _ _ c -> go (c :* Nil) (from a)
61+ ADT _ _ cs -> go cs (from a)
62+ Newtype _ _ c -> go (c :* Nil) (from a)
6463 where
65− go :: (All2 QueryValues xss, SListI xss)
64+ go :: (All2 QueryValues xss, SingI xss)
6665 => NP ConstructorInfo xss
6766 -> SOP I xss
6867 -> Query
69− go cs (SOP sop) =
70− group . hcollapse $ hcliftA2' p (gctor o) cs sop
68+ go cs (SOP sop) = group . unI . hcollapse $ hcliftA2' p (gctor o) cs sop
7169
7270 group :: [(ByteString, ByteString)] -> Query
7371 group = concatMap f . groupBy ((==) `on` fst)
src/Network/PagerDuty/REST.hs+30−42
@@ -2,7 +2,7 @@
22{-# LANGUAGE OverloadedStrings #-}
33
44-- Module : Network.PagerDuty.REST
5−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
5+-- Copyright : (c) 2013-2014 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,11 +15,7 @@ module Network.PagerDuty.REST
1515 (
1616 -- * Sending requests
1717 send
18− , sendWith
1918 , paginate
20− , paginateWith
21−
22− , module Network.PagerDuty.Types
2319 ) where
2420
2521import Control.Applicative
@@ -27,69 +23,61 @@ import Control.Lens
2723import Control.Monad
2824import Control.Monad.IO.Class
2925import Control.Monad.Trans
30−import Data.Aeson (FromJSON)
26+import Data.Aeson (FromJSON)
3127import Data.Conduit
28+import Data.Default.Class
3229import Data.Monoid
33−import Network.HTTP.Client (Manager)
34−import qualified Network.HTTP.Client as Client
30+import Network.HTTP.Client (Manager)
31+import qualified Network.HTTP.Client as Client
3532import Network.HTTP.Types
36−import Network.PagerDuty.Internal.IO
37−import Network.PagerDuty.Internal.Types
33+import Network.PagerDuty.IO
3834import Network.PagerDuty.Types
3935
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
4341
44−-- | /See:/ 'sendWith'
42+-- FIXME: Ensure requesterid parameter is always first
43+
4544send :: (MonadIO m, FromJSON b)
46− => SubDomain
47− -> Auth s
45+ => Auth s
46+ -> SubDomain
4847 -> Manager
4948 -> Request a s b
5049 -> m (Either Error b)
51−send d a m = sendWith (prod d a m)
50+send a s m = liftM (fmap fst) . http a s m
5251
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'
6052paginate :: (MonadIO m, Paginate a, FromJSON b)
61− => SubDomain
62− -> Auth s
53+ => Auth s
54+ -> SubDomain
6355 -> Manager
6456 -> Request a s b
6557 -> Source m (Either Error b)
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
58+paginate a d m = go
7359 where
7460 go rq = do
75− rs <- lift (http e rq)
76− yield (_pgItem <$> rs)
61+ rs <- lift (http a d m rq)
62+ yield (fst <$> rs)
7763 either (const (return ()))
78− (maybe (return ()) go . next rq . _pgPager)
64+ (maybe (return ()) go . next rq . snd)
7965 rs
8066
8167http :: (MonadIO m, FromJSON b)
82− => Env s
68+ => Auth s
69+ -> SubDomain
70+ -> Manager
8371 -> Request a s b
84− -> m (Either Error (Page b))
85−http e rq = request (e ^. envManager) (e ^. envLogger) rq $ raw
86− { Client.host = domain (e ^. envDomain)
72+ -> m (Either Error (b, Maybe Pager))
73+http a (SubDomain h) m rq = request m rq $ raw
74+ { Client.host = h
8775 , Client.path = renderPath (rq ^. path)
8876 , Client.queryString = renderQuery False (rq ^. query)
8977 }
9078 where
91− raw = case e ^. envAuth of
92− AuthBasic u p -> Client.applyBasicAuth u p Client.defaultRequest
93− AuthToken t -> Client.defaultRequest
79+ raw = case a of
80+ AuthBasic u p -> Client.applyBasicAuth u p def
81+ AuthToken t -> def
9482 { Client.requestHeaders = [("Authorization", "Token token=" <> t)]
9583 }
src/Network/PagerDuty/REST/Alerts.hs+7−7
@@ -4,7 +4,7 @@
44{-# LANGUAGE TypeFamilies #-}
55
66-- Module : Network.PagerDuty.REST.Alerts
7−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
7+-- Copyright : (c) 2013-2014 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 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)
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
5252
5353alerts :: Path
5454alerts = "alerts"
src/Network/PagerDuty/REST/EscalationPolicies.hs+14−14
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.EscalationPolicies
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -60,15 +60,15 @@ module Network.PagerDuty.REST.EscalationPolicies
6060 , pServices
6161 ) where
6262
63−import Control.Lens hiding (Empty)
64−import Data.Aeson.Lens
65−import Data.Text (Text)
66−import Network.HTTP.Types
67−import Network.PagerDuty.Internal.TH
68−import Network.PagerDuty.Internal.Types
69−import Network.PagerDuty.REST.Services (Service)
63+import Control.Lens
64+import Data.Aeson.Lens
65+import Data.Text (Text)
66+import Network.HTTP.Types
67+import Network.PagerDuty.REST.Services (Service)
68+import Network.PagerDuty.TH
69+import Network.PagerDuty.Types
7070
71−import Network.PagerDuty.REST.EscalationPolicies.EscalationRules
71+import Network.PagerDuty.REST.EscalationPolicies.EscalationRules
7272
7373default (Path)
7474
src/Network/PagerDuty/REST/EscalationPolicies/EscalationRules.hs+11−11
@@ -1,12 +1,12 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
55
66{-# OPTIONS_GHC -fno-warn-type-defaults #-}
77
88-- Module : Network.PagerDuty.REST.EscalationPolicies.EscalationRules
9−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
9+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1010-- License : This Source Code Form is subject to the terms of
1111-- the Mozilla Public License, v. 2.0.
1212-- A copy of the MPL can be found in the LICENSE file or
@@ -64,15 +64,15 @@ module Network.PagerDuty.REST.EscalationPolicies.EscalationRules
6464 , rTargets
6565 ) where
6666
67−import Control.Applicative ((<$>))
68−import Control.Lens hiding ((.=))
67+import Control.Applicative ((<$>))
68+import Control.Lens hiding ((.=))
6969import Data.Aeson
70−import qualified Data.Aeson.KeyMap as Map
71−import Data.Text (Text)
70+import qualified Data.HashMap.Strict as Map
71+import Data.Text (Text)
7272import Network.HTTP.Types
73−import Network.PagerDuty.Internal.TH
74−import Network.PagerDuty.Internal.Types
7573import Network.PagerDuty.REST.Users
74+import Network.PagerDuty.TH
75+import Network.PagerDuty.Types
7676
7777default (Path)
7878
src/Network/PagerDuty/REST/Incidents.hs+27−23
@@ -10,7 +10,7 @@
1010{-# OPTIONS_GHC -fno-warn-type-defaults #-}
1111
1212-- Module : Network.PagerDuty.REST.Incidents
13−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
13+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1414-- License : This Source Code Form is subject to the terms of
1515-- the Mozilla Public License, v. 2.0.
1616-- A copy of the MPL can be found in the LICENSE file or
@@ -129,21 +129,19 @@ module Network.PagerDuty.REST.Incidents
129129 , Incident
130130 ) where
131131
132−import Control.Applicative hiding (empty)
133−import Control.Lens hiding (Empty)
132+import Control.Applicative hiding (empty)
133+import Control.Lens
134134import Data.Aeson
135−import Data.ByteString.Conversion (ToByteString (..),
136− toByteString')
135+import Data.ByteString.Conversion (ToByteString(..), toByteString')
137136import 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
137+import Data.Monoid hiding (All)
138+import Data.Text (Text)
139+import qualified Data.Text.Encoding as Text
142140import Data.Time
143141import Network.HTTP.Types
144−import Network.PagerDuty.Internal.Query
145−import Network.PagerDuty.Internal.TH
146−import Network.PagerDuty.Internal.Types
142+import Network.PagerDuty.Query
143+import Network.PagerDuty.TH
144+import Network.PagerDuty.Types
147145
148146default (Path)
149147
@@ -347,10 +345,13 @@ lsUntil = upd.lsUntil'.mapping _D
347345-- | When set, the since and until parameters and defaults are
348346-- ignored. Use this to get all incidents since the account was created.
349347lsDateRange :: Lens' (Request ListIncidents s b) Bool
350−lsDateRange = upd.lens get_ (flip set_)
348+lsDateRange = upd . lens get_ set_
351349 where
352− get_ = (Just All ==) . view lsDateRange'
353− set_ x = lsDateRange' .~ listToMaybe [All | x]
350+ get_ x
351+ | Just All <- _lsDateRange' x = True
352+ | otherwise = False
353+
354+ set_ l x = l { _lsDateRange' = if x then Just All else Nothing }
354355
355356-- | Returns only the incidents currently in the passed status(es).
356357lsStatus :: Lens' (Request ListIncidents s b) (Maybe [IncidentStatus])
@@ -437,12 +438,12 @@ cSince = upd.cSince'.mapping _D
437438
438439-- | The end of the date range over which you want to search.
439440--
440−-- /Note:/ If you leave off either since or until, a 30 day default range is
441+-- /Note: If you leave off either since or until, a 30 day default range is
441442-- applied to your open ended range. Not including the since parameter will set
442−-- the date range to until @-30@ days. Likewise, if you leave off until,
443−-- it is set to since @+30@ days.
443+-- the date range to until - 30 days. Likewise, if you leave off until,
444+-- it is set to since + 30 days.
444445--
445−-- /Default:/ The last 30 days if you leave off both. The size of the date
446+-- Defaults to the last 30 days if you leave off both. The size of the date
446447-- range must be less than 180 days.
447448cUntil :: Lens' (Request CountIncidents s b) (Maybe UTCTime)
448449cUntil = upd.cUntil'.mapping _D
@@ -450,10 +451,13 @@ cUntil = upd.cUntil'.mapping _D
450451-- | When set, the since and until parameters and defaults are
451452-- ignored. Use this to get all counts since the account was created.
452453cDateRange :: Lens' (Request CountIncidents s b) Bool
453−cDateRange = upd.lens get_ (flip set_)
454+cDateRange = upd . lens get_ set_
454455 where
455− get_ = (Just All ==) . view cDateRange'
456− set_ x = cDateRange' .~ listToMaybe [All | x]
456+ get_ x
457+ | Just All <- _cDateRange' x = True
458+ | otherwise = False
459+
460+ set_ l x = l { _cDateRange' = if x then Just All else Nothing }
457461
458462-- | Only counts the incidents currently in the passed status(es).
459463cStatus :: Lens' (Request CountIncidents s b) (Maybe [IncidentStatus])
@@ -567,7 +571,7 @@ updateIncidents r = auth updateIncidentsBasic & query .~ [("requester_id", r)]
567571
568572-- | A version of 'updateIncidents' which uses HTTP Basic authentication and
569573-- doesn't require a 'RequesterId'.
570−updateIncidentsBasic :: Request UpdateIncidents 'Basic [UpdatedIncidents]
574+updateIncidentsBasic :: Request UpdateIncidents Basic [UpdatedIncidents]
571575updateIncidentsBasic =
572576 mk UpdateIncidents
573577 { _uiIncidents' = []
src/Network/PagerDuty/REST/Incidents/Notes.hs+12−12
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Incidents.Notes
8−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2014 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.Internal.TH
45−import Network.PagerDuty.Internal.Types
46−import Network.PagerDuty.REST.Users
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
4747
4848default (Path)
4949
src/Network/PagerDuty/REST/LogEntries.hs+9−8
@@ -5,7 +5,7 @@
55{-# LANGUAGE TypeFamilies #-}
66
77-- Module : Network.PagerDuty.REST.LogEntries
8−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2014 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,18 +111,19 @@ module Network.PagerDuty.REST.LogEntries
111111 , nAddress
112112 ) where
113113
114−import Control.Lens hiding (Empty)
114+import Control.Applicative
115+import Control.Lens
115116import Data.Aeson
116117import Data.Aeson.Lens
117−import qualified Data.Aeson.KeyMap as Map
118118import Data.Default.Class
119−import Data.Text (Text)
120−import qualified Data.Text as Text
119+import qualified Data.HashMap.Strict as Map
120+import Data.Text (Text)
121+import qualified Data.Text as Text
121122import Data.Time
122123import Network.HTTP.Types
123−import Network.PagerDuty.Internal.TH
124−import Network.PagerDuty.Internal.Types
125−import Network.PagerDuty.REST.Users (User)
124+import Network.PagerDuty.REST.Users (User)
125+import Network.PagerDuty.TH
126+import Network.PagerDuty.Types
126127
127128logs :: Path
128129logs = "log_entries"
src/Network/PagerDuty/REST/MaintenanceWindows.hs+10−10
@@ -4,7 +4,7 @@
44{-# LANGUAGE TypeFamilies #-}
55
66-- Module : Network.PagerDuty.REST.MaintenanceWindows
7−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
7+-- Copyright : (c) 2013-2014 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 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)
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
8585
8686windows :: Path
8787windows = "maintenance_windows"
@@ -214,7 +214,7 @@ createWindow r s e xs =
214214createWindowBasic :: UTCTime -- ^ 'cwStartTime'
215215 -> UTCTime -- ^ 'cwEndTime'
216216 -> [ServiceId] -- ^ 'cwServiceIds'
217− -> Request CreateWindow 'Basic MaintenanceWindow
217+ -> Request CreateWindow Basic MaintenanceWindow
218218createWindowBasic s e xs =
219219 mk CreateWindow
220220 { _cwRequesterId' = Nothing
src/Network/PagerDuty/REST/Reports.hs+11−11
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Reports
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -58,11 +58,11 @@ module Network.PagerDuty.REST.Reports
5858 , irNumberOfIncidents
5959 ) where
6060
61−import Control.Lens hiding (Empty)
62−import Data.Aeson.Lens
63−import Data.Time
64−import Network.PagerDuty.Internal.TH
65−import Network.PagerDuty.Internal.Types
61+import Control.Lens
62+import Data.Aeson.Lens
63+import Data.Time
64+import Network.PagerDuty.TH
65+import Network.PagerDuty.Types
6666
6767default (Path)
6868
src/Network/PagerDuty/REST/Schedules.hs+14−14
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Schedules
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -110,14 +110,14 @@ module Network.PagerDuty.REST.Schedules
110110 , sFinalSchedule
111111 ) where
112112
113−import Control.Lens hiding (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)
113+import Control.Lens hiding ((.=))
114+import Data.Aeson
115+import Data.Text (Text)
116+import Data.Time
117+import Network.HTTP.Types
118+import Network.PagerDuty.REST.Users (User)
119+import Network.PagerDuty.TH
120+import Network.PagerDuty.Types
121121
122122default (Path)
123123
src/Network/PagerDuty/REST/Schedules/Overrides.hs+12−12
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Schedules
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2014 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.Internal.TH
57−import Network.PagerDuty.Internal.Types
58−import Network.PagerDuty.REST.Users
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
5959
6060overrides :: ScheduleId -> Path
6161overrides i = "schedules" % i % "overrides"
src/Network/PagerDuty/REST/Services.hs+16−16
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Services
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2014 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 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
109+import Control.Lens
110+import Data.Aeson.Lens
111+import Data.Text (Text)
112+import Data.Time
113+import Network.HTTP.Types
114+import Network.PagerDuty.REST.Services.EmailFilters
115+import Network.PagerDuty.TH
116+import Network.PagerDuty.Types
117117
118118default (Path)
119119
@@ -483,7 +483,7 @@ enableService r i =
483483
484484-- | A version of 'enableService' which uses HTTP Basic authentication and
485485-- doesn't require a 'RequesterId'.
486−enableServiceBasic :: ServiceId -> Request Empty 'Basic Empty
486+enableServiceBasic :: ServiceId -> Request Empty Basic Empty
487487enableServiceBasic i = empty & meth .~ PUT & path .~ services % i % "enable"
488488
489489-- | Disable a service. Once a service is disabled, it will not be able to
@@ -498,7 +498,7 @@ disableService r i =
498498
499499-- | A version of 'disableService' which uses HTTP Basic authentication and
500500-- doesn't require a 'RequesterId'.
501−disableServiceBasic :: ServiceId -> Request Empty 'Basic Empty
501+disableServiceBasic :: ServiceId -> Request Empty Basic Empty
502502disableServiceBasic i = empty & meth .~ PUT & path .~ services % i % "disable"
503503
504504-- | Regenerate a new service key for an existing service.
src/Network/PagerDuty/REST/Services/EmailFilters.hs+14−14
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Services.EmailFilters
8−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -39,15 +39,15 @@ module Network.PagerDuty.REST.Services.EmailFilters
3939 , efId
4040 ) where
4141
42−import Control.Applicative hiding (empty)
43−import Control.Lens hiding ((.=))
44−import Data.Aeson
45−import Data.Default.Class
46−import Data.Monoid
47−import Data.Text (Text)
48−import Network.HTTP.Types
49−import Network.PagerDuty.Internal.TH
50−import Network.PagerDuty.Internal.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.TH
50+import Network.PagerDuty.Types
5151
5252default (Path)
5353
@@ -65,7 +65,7 @@ deriveNullaryWith hyphenated ''MatchMode
6565-- FIXME: Tighten up this type! Make the regex required for match/no-match and
6666-- encode the conditional invariants.
6767data EmailFilterInfo = EmailFilterInfo
68− { _efSubjectMode' :: Maybe MatchMode
68+ { _efSubjectMode' :: Maybe MatchMode
6969 , _efSubjectRegex' :: Maybe Text
7070 , _efBodyMode' :: Maybe MatchMode
7171 , _efBodyRegex' :: Maybe Text
src/Network/PagerDuty/REST/Users.hs+17−17
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE ExtendedDefaultRules #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeFamilies #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE ExtendedDefaultRules #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeFamilies #-}
66
77{-# OPTIONS_GHC -fno-warn-type-defaults #-}
88
99-- Module : Network.PagerDuty.REST.Users
10−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
10+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
1111-- License : This Source Code Form is subject to the terms of
1212-- the Mozilla Public License, v. 2.0.
1313-- A copy of the MPL can be found in the LICENSE file or
@@ -81,16 +81,16 @@ module Network.PagerDuty.REST.Users
8181 , uJobTitle
8282 ) where
8383
84−import Control.Applicative hiding (empty)
85−import Control.Lens hiding (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
84+import Control.Applicative hiding (empty)
85+import Control.Lens hiding ((.=))
86+import Data.Aeson
87+import Data.Default.Class
88+import Data.Monoid
89+import Data.Text (Text)
90+import Data.Time
91+import Network.HTTP.Types
92+import Network.PagerDuty.TH
93+import Network.PagerDuty.Types
9494
9595default (Path)
9696
@@ -315,7 +315,7 @@ createUser r n e = auth (createUserBasic n e) & query .~ [("requester_id", r)]
315315-- doesn't require a 'RequesterId'.
316316createUserBasic :: Text -- ^ 'cuName'
317317 -> Address -- ^ 'cuEmail'
318− -> Request CreateUser 'Basic User
318+ -> Request CreateUser Basic User
319319createUserBasic n e =
320320 mk CreateUser
321321 { _cuName' = n
src/Network/PagerDuty/REST/Users/ContactMethods.hs+10−10
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Users.ContactMethods
8−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -56,12 +56,12 @@ module Network.PagerDuty.REST.Users.ContactMethods
5656 , Contact
5757 ) where
5858
59−import Control.Lens
60−import Data.Aeson.Lens
61−import Data.Text (Text)
62−import Network.HTTP.Types
63−import Network.PagerDuty.Internal.TH
64−import Network.PagerDuty.Internal.Types
59+import Control.Lens
60+import Data.Aeson.Lens
61+import Data.Text (Text)
62+import Network.HTTP.Types
63+import Network.PagerDuty.TH
64+import Network.PagerDuty.Types
6565
6666default (Path)
6767
src/Network/PagerDuty/REST/Users/NotificationRules.hs+10−10
@@ -1,11 +1,11 @@
1−{-# LANGUAGE ExtendedDefaultRules #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
1+{-# LANGUAGE ExtendedDefaultRules #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TemplateHaskell #-}
44
55{-# OPTIONS_GHC -fno-warn-type-defaults #-}
66
77-- Module : Network.PagerDuty.REST.Users.NotificationRules
8−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
8+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
99-- License : This Source Code Form is subject to the terms of
1010-- the Mozilla Public License, v. 2.0.
1111-- A copy of the MPL can be found in the LICENSE file or
@@ -51,12 +51,12 @@ module Network.PagerDuty.REST.Users.NotificationRules
5151 , rContactMethod
5252 ) where
5353
54−import Control.Lens
55−import Data.Aeson.Lens
56−import Network.HTTP.Types
57−import Network.PagerDuty.Internal.TH
58−import Network.PagerDuty.Internal.Types
59−import Network.PagerDuty.REST.Users.ContactMethods
54+import Control.Lens
55+import Data.Aeson.Lens
56+import Network.HTTP.Types
57+import Network.PagerDuty.REST.Users.ContactMethods
58+import Network.PagerDuty.TH
59+import Network.PagerDuty.Types
6060
6161default (Path)
6262
src/Network/PagerDuty/REST/Webhooks.hs+4−5
@@ -3,7 +3,7 @@
33{-# LANGUAGE TemplateHaskell #-}
44
55-- Module : Network.PagerDuty.REST.Webhooks
6−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
6+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
77-- License : This Source Code Form is subject to the terms of
88-- the Mozilla Public License, v. 2.0.
99-- A copy of the MPL can be found in the LICENSE file or
@@ -35,14 +35,13 @@ module Network.PagerDuty.REST.Webhooks
3535import Control.Applicative hiding (empty)
3636import Control.Lens
3737import Data.Aeson
38−import Data.ByteString.Conversion (ToByteString (..),
39− toByteString')
38+import Data.ByteString.Conversion (ToByteString(..), toByteString')
4039import Data.Text (Text)
4140import qualified Data.Text.Encoding as Text
4241import Data.Time
43−import Network.PagerDuty.Internal.TH
44−import Network.PagerDuty.Internal.Types
4542import Network.PagerDuty.REST.Incidents
43+import Network.PagerDuty.TH
44+import Network.PagerDuty.Types
4645
4746data WebhookType
4847 = WTrigger
src/Network/PagerDuty/Internal/TH.hs → src/Network/PagerDuty/TH.hsrenamed+9−9
@@ -1,7 +1,7 @@
11{-# LANGUAGE TemplateHaskell #-}
22
3−-- Module : Network.PagerDuty.Internal.TH
4−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
3+-- Module : Network.PagerDuty.TH
4+-- Copyright : (c) 2013-2014 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.Internal.TH
13+module Network.PagerDuty.TH
1414 (
1515 -- * Requests
1616 jsonRequest
@@ -40,15 +40,15 @@ module Network.PagerDuty.Internal.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.Internal.Options
51−import Network.PagerDuty.Internal.Query
50+import Network.PagerDuty.Query
51+import Network.PagerDuty.Options
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 emptyObject|]
64+ , [d|instance ToJSON $(conT n) where toJSON = const (toJSON (object []))|]
6565 , [d|instance QueryLike $(conT n) where toQuery = gquery|]
6666 ]
6767
src/Network/PagerDuty/Types.hs+432−84
@@ -1,5 +1,19 @@
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+
115-- Module : Network.PagerDuty.Types
2−-- Copyright : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
16+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
317-- License : This Source Code Form is subject to the terms of
418-- the Mozilla Public License, v. 2.0.
519-- A copy of the MPL can be found in the LICENSE file or
@@ -8,86 +22,420 @@
822-- Stability : experimental
923-- Portability : non-portable (GHC extensions)
1024
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
25+module Network.PagerDuty.Types where
26+ -- (
27+ -- -- * Requests
28+ -- Auth (..)
29+ -- , Cred (..)
30+ -- , Domain (..)
31+
32+ -- , Request (..)
33+ -- , Request'
34+
35+ -- , Paginate (..)
36+
37+ -- -- * Errors
38+ -- , Code (..)
39+ -- , message
40+ -- , RestError (..)
41+ -- , Error (..)
42+
43+ -- -- * Primitives
44+ -- , Key (..)
45+ -- , ServiceKey
46+ -- , IncidentKey
47+
48+ -- , Id (..)
49+ -- , ServiceId
50+ -- , RequesterId
51+
52+ -- , Empty (..)
53+ -- ) where
54+
55+import Control.Applicative
56+import Control.Lens hiding ((.=))
57+import Data.Aeson hiding (Error)
58+import Data.Aeson.Types (Parser)
59+import Data.ByteString (ByteString)
60+import qualified Data.ByteString.Char8 as BS
61+import Data.ByteString.Conversion hiding (List)
62+import Data.Default.Class
63+import Data.Function (on)
64+import qualified Data.HashMap.Strict as Map
65+import Data.List (deleteBy, intersperse)
66+import Data.Monoid
67+import Data.String
68+import Data.Text (Text)
69+import qualified Data.Text as Text
70+import qualified Data.Text.Encoding as Text
71+import Data.Time
72+import GHC.TypeLits
73+import Network.HTTP.Types
74+import Network.HTTP.Types.QueryLike
75+import Network.PagerDuty.Query
76+import Network.PagerDuty.TH
77+import System.Locale
78+
79+-- FIXME: Verify IncidentId/IncidentKey .. *Id/*Key are actually different or needed
80+
81+newtype CSV a = CSV [a]
82+ deriving (Eq, Show, Monoid)
83+
84+makePrisms ''CSV
85+
86+instance ToByteString a => QueryValues (CSV a)
87+
88+instance ToByteString a => ToByteString (CSV a) where
89+ builder (CSV xs) = mconcat . intersperse "," $ map builder xs
90+
91+instance FromJSON a => FromJSON (CSV a) where
92+ parseJSON = withText "comma_separated_value" $
93+ fmap CSV . traverse (parseJSON . String) . Text.split (== ',')
94+
95+instance ToByteString a => ToJSON (CSV a) where
96+ toJSON = String . Text.decodeUtf8 . toByteString'
97+
98+newtype List a = L [a]
99+ deriving (Eq, Show, Monoid)
100+
101+deriveJSON ''List
102+makePrisms ''List
103+
104+instance QueryValues a => QueryValues (List a) where
105+ queryValues (L xs) = concatMap queryValues xs
106+
107+newtype Bool' = B Bool
108+ deriving (Eq, Show)
109+
110+deriveJSON ''Bool'
111+makePrisms ''Bool'
112+
113+instance ToByteString Bool' where
114+ builder (B True) = "true"
115+ builder (B False) = "false"
116+
117+instance QueryValues Bool'
118+
119+pattern T = B True
120+pattern F = B False
121+
122+newtype Date = D UTCTime
123+ deriving (Eq, Ord, Show)
124+
125+makePrisms ''Date
126+
127+instance FromJSON Date where
128+ parseJSON = fmap D . parseJSON
129+
130+instance ToJSON Date where
131+ toJSON (D d) = toJSON d
132+
133+instance ToByteString Date where
134+ builder (D d) = builder
135+ (formatTime defaultTimeLocale (iso8601DateFormat $ Just "%XZ") d)
136+
137+instance QueryValues Date
138+
139+newtype TZ = TZ TimeZone
140+ deriving (Eq, Show)
141+
142+makePrisms ''TZ
143+
144+instance FromJSON TZ where
145+ parseJSON = undefined
146+
147+instance ToJSON TZ where
148+ toJSON = toJSON . Text.decodeUtf8 . toByteString'
149+
150+instance ToByteString TZ where
151+ builder (TZ tz) = builder (timeZoneName tz)
152+
153+instance QueryValues TZ
154+
155+instance Default TZ where
156+ def = TZ utc
157+
158+data Security = Basic | Token
159+ deriving (Eq, Show)
160+
161+data Auth (a :: Security) where
162+ AuthBasic :: ByteString -> ByteString -> Auth Basic
163+ AuthToken :: ByteString -> Auth Token
164+
165+deriving instance Eq (Auth a)
166+deriving instance Show (Auth a)
167+
168+newtype SubDomain = SubDomain ByteString
169+ deriving (Eq, Show, IsString)
170+
171+domain :: SubDomain -> ByteString
172+domain (SubDomain s)
173+ | base `BS.isSuffixOf` s = s
174+ | otherwise = s <> base
175+ where
176+ base = ".pagerduty.com"
177+
178+newtype Code = Code Integer
179+ deriving (Eq, Show)
180+
181+deriveJSON ''Code
182+
183+description :: Code -> Text
184+description (Code c) =
185+ case c of
186+ 2000 -> "Internal Error"
187+ 2001 -> "Invalid Input Provided"
188+ 2002 -> "Arguments Caused Error"
189+ 2003 -> "Missing Arguments"
190+ 2004 -> "Invalid 'since' or 'until' Parameter Values"
191+ 2005 -> "Invalid Query Date Range"
192+ 2006 -> "Authentication Failed"
193+ 2007 -> "Account Not Found"
194+ 2008 -> "Account Locked"
195+ 2009 -> "Only HTTPS Allowed For This Call"
196+ 2010 -> "Access Denied"
197+ 2011 -> "The action requires a 'requester_id' to be specified"
198+ 2012 -> "Your account is expired and cannot use the API"
199+ _ -> "Unrecognised error code"
200+
201+data IntegrationError = IntegrationError
202+ { _ieStatus :: Text
203+ , _ieMessage :: Text
204+ , _ieErrors :: [Text]
205+ } deriving (Eq, Show)
206+
207+deriveRecord ''IntegrationError
208+
209+data RestError = RestError
210+ { _reCode :: Code
211+ , _reMessage :: Text
212+ , _reErrors :: [Text]
213+ } deriving (Eq, Show)
214+
215+deriveRecord ''RestError
216+
217+data Error
218+ = Internal String
219+ | Integration IntegrationError
220+ | Rest RestError
221+ deriving (Eq, Show)
222+
223+instance FromJSON Error where
224+ parseJSON o = (Rest <$> parseJSON o)
225+ <|> (Integration <$> parseJSON o)
226+
227+makePrisms ''Error
228+
229+data Pager = Pager
230+ { _pgOffset :: !Int
231+ -- ^ The offset used in the execution of the query.
232+ , _pgLimit :: !Int
233+ -- ^ The limit used in the execution of the query.
234+ , _pgTotal :: !Int
235+ -- ^ The total number of records available.
236+ , _pgQuery :: Maybe Text
237+ -- ^ An optional query= value to be added to the query string.
238+ } deriving (Eq, Show)
239+
240+makeLenses ''Pager
241+
242+instance FromJSON a => FromJSON (a, Maybe Pager) where
243+ parseJSON = withObject "paginated" $ \o -> (,)
244+ <$> parseJSON (Object o)
245+ <*> optional (parse o)
246+ where
247+ parse o = Pager
248+ -- The offset of the first record returned.
249+ -- Default is 0.
250+ <$> o .: "offset" .!= 0
251+ -- The number of records returned.
252+ -- Default (and max limit) is 100 for most APIs.
253+ <*> o .: "limit" .!= 100
254+ <*> o .: "total"
255+ <*> o .:? "query"
256+
257+instance ToJSON Pager where
258+ toJSON p = object
259+ [ "offset" .= _pgOffset p
260+ , "limit" .= _pgLimit p
261+ ]
262+
263+-- | A path segment.
264+data Path where
265+ Path :: Path
266+ Seg :: ToByteString a => a -> Path
267+
268+instance Monoid Path where
269+ mempty = Path
270+ mappend x Path = x
271+ mappend Path y = y
272+ mappend (Seg x) (Seg y) = Seg (builder x <> "/" <> builder y)
273+
274+instance IsString Path where
275+ fromString = Seg
276+
277+instance ToByteString Path where
278+ builder Path = mempty
279+ builder (Seg x) = builder x
280+
281+(%) :: ToByteString a => Path -> a -> Path
282+a % b = a <> Seg b
283+
284+renderPath :: Path -> ByteString
285+renderPath = toByteString' . mappend v1
286+ where
287+ v1 :: Path
288+ v1 = "/api/v1"
289+
290+data Request a (s :: Security) b where
291+ Request :: (QueryLike a, ToJSON a)
292+ => { _rqMeth :: !StdMethod
293+ , _rqPath :: Path
294+ , _rqQuery :: Query
295+ , _rqBody :: a
296+ , _rqPager :: Maybe Pager
297+ , _rqUnwrap :: Value -> Parser Value
298+ }
299+ -> Request a s b
300+
301+instance ToJSON (Request a s b) where
302+ -- Manually unwrapped to ensure GADT constraint holds.
303+ toJSON (Request _ _ _ b p _) = Object $
304+ let Object x = toJSON b
305+ in case toJSON p of
306+ (Object y) -> x <> y
307+ _ -> x
308+
309+type Unwrap = Getting (First Value) Value Value
310+
311+-- | Create a defaulted request from the payload type.
312+mk :: (QueryLike a, ToJSON a) => a -> Request a s b
313+mk x = Request GET mempty mempty x Nothing pure
314+
315+empty :: Request Empty s r
316+empty = mk Empty
317+
318+-- | Lens into the body of a request.
319+upd :: (QueryLike a, ToJSON a) => Lens' (Request a s b) a
320+upd = lens _rqBody (\(Request m p q _ g u) x -> Request m p q x g u)
321+
322+-- | Drop the security constraint.
323+auth :: Request a s b -> Request a t b
324+auth (Request x m p q g u) = Request x m p q g u
325+
326+meth :: Lens' (Request a s b) StdMethod
327+meth = lens _rqMeth (\r x -> r { _rqMeth = x })
328+
329+path :: Lens' (Request a s b) Path
330+path = lens _rqPath (\r x -> r { _rqPath = x })
331+
332+query :: QueryValueLike v
333+ => Lens (Request a s b) (Request a s b) Query [(ByteString, v)]
334+query = lens _rqQuery (\r x -> r { _rqQuery = toQuery x })
335+
336+pager :: Lens' (Request a s b) (Maybe Pager)
337+pager = lens _rqPager (\r x -> r { _rqPager = x })
338+
339+unwrap :: Setter (Request a s b) (Request a s b) (Value -> Parser Value) Unwrap
340+unwrap f r = f (_rqUnwrap r) <&> \k -> r { _rqUnwrap = g k }
341+ where
342+ g k x = maybe (fail "Failed to extract nested keys.") return (x ^? k)
343+
344+-- | Exists primarily to obtain a constraint for the 'paginate' function.
345+class Paginate a where
346+ next :: Request a s b -> Maybe Pager -> Maybe (Request a s b)
347+ next rq = maybe Nothing go
348+ where
349+ go x | x^.pgTotal == 0 = Nothing
350+ | otherwise = Just $
351+ rq & pager ?~ (x & pgOffset +~ x^.pgTotal)
352+ & query %~ (add . clear)
353+ where
354+ add :: Query -> Query
355+ add = maybe id ((:) . (k,) . Just . Text.encodeUtf8) (x^.pgQuery)
356+
357+ clear :: Query -> Query
358+ clear = deleteBy ((==) `on` fst) (k, Nothing)
359+
360+ k :: ByteString
361+ k = "query"
362+
363+newtype Key (a :: Symbol) = Key Text
364+ deriving (Eq, Show, IsString)
365+
366+instance FromJSON (Key a) where
367+ parseJSON = withText "key" (return . Key)
368+
369+instance ToJSON (Key a) where
370+ toJSON (Key k) = toJSON k
371+
372+instance ToByteString (Key a) where
373+ builder (Key k) = builder k
374+
375+instance QueryValues (Key a)
376+
377+instance QueryValueLike (Key a) where
378+ toQueryValue = Just . toByteString'
379+
380+type ServiceKey = Key "service"
381+type IncidentKey = Key "incident"
382+
383+newtype Id (a :: Symbol) = Id Text
384+ deriving (Eq, Show, IsString)
385+
386+instance FromJSON (Id a) where
387+ parseJSON = withText "id" (return . Id)
388+
389+instance ToJSON (Id a) where
390+ toJSON (Id i) = toJSON i
391+
392+instance ToByteString (Id a) where
393+ builder (Id i) = builder i
394+
395+instance QueryValues (Id a)
396+
397+instance QueryValueLike (Id a) where
398+ toQueryValue = Just . toByteString'
399+
400+type AlertId = Id "alert"
401+type ContactId = Id "contact"
402+type EmailFilterId = Id "email-filter"
403+type EscalationPolicyId = Id "escalation-policy"
404+type EscalationRuleId = Id "escalation-rule"
405+type IncidentId = Id "incident"
406+type LogEntryId = Id "log-entry"
407+type NoteId = Id "note"
408+type NotificationRuleId = Id "notification-rule"
409+type OverrideId = Id "schedule-override"
410+type RequesterId = Id "requester"
411+type ScheduleId = Id "schedule"
412+type ServiceId = Id "service"
413+type UserId = Id "user"
414+type VendorId = Id "vendor"
415+type WebhookId = Id "webhook"
416+type WindowId = Id "maintenance-window"
417+
418+data Empty = Empty
419+
420+instance ToJSON Empty where
421+ toJSON = const (object [])
422+
423+instance FromJSON Empty where
424+ parseJSON = withObject "empty" f
425+ where
426+ f !o | Map.null o = pure Empty
427+ | otherwise = fail "Unexpected non-empty JSON object."
428+
429+instance QueryLike Empty where
430+ toQuery = const []
431+
432+newtype Address = Address Text
433+ deriving (Eq, Show)
434+
435+deriveJSON ''Address
436+makePrisms ''Address
437+
438+instance ToByteString Address where
439+ builder (Address a) = builder a
440+
441+instance QueryValues Address
stack.yamldeleted−7
@@ -1,7 +0,0 @@
1−resolver: lts-19.23
2−
3−packages:
4−- .
5−
6−nix:
7− packages: [zlib]