packages feed

mackerel-client 0.1.0 → 0.2.0

raw patch · 12 files changed

+172/−31 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Web.Mackerel.Types.Invitation: InvitationAuthorityCollaborator :: InvitationAuthority
- Web.Mackerel.Types.Invitation: InvitationAuthorityManager :: InvitationAuthority
- Web.Mackerel.Types.Invitation: InvitationAuthorityViewer :: InvitationAuthority
- Web.Mackerel.Types.Invitation: data InvitationAuthority
- Web.Mackerel.Types.Invitation: instance Data.Aeson.Types.FromJSON.FromJSON Web.Mackerel.Types.Invitation.InvitationAuthority
- Web.Mackerel.Types.Invitation: instance Data.Aeson.Types.ToJSON.ToJSON Web.Mackerel.Types.Invitation.InvitationAuthority
- Web.Mackerel.Types.Invitation: instance GHC.Classes.Eq Web.Mackerel.Types.Invitation.InvitationAuthority
- Web.Mackerel.Types.Invitation: instance GHC.Read.Read Web.Mackerel.Types.Invitation.InvitationAuthority
- Web.Mackerel.Types.Invitation: instance GHC.Show.Show Web.Mackerel.Types.Invitation.InvitationAuthority
+ Web.Mackerel.Api.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Web.Mackerel.Api.Channel.ListChannelsResponse
+ Web.Mackerel.Api.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Web.Mackerel.Api.Channel.ListChannelsResponse
+ Web.Mackerel.Api.Channel: listChannels :: Client -> IO (Either ApiError [Channel])
+ Web.Mackerel.Api.Service: createService :: Client -> Service -> IO (Either ApiError Service)
+ Web.Mackerel.Api.Service: deleteService :: Client -> String -> IO (Either ApiError Service)
+ Web.Mackerel.Types.Authority: AuthorityCollaborator :: Authority
+ Web.Mackerel.Types.Authority: AuthorityManager :: Authority
+ Web.Mackerel.Types.Authority: AuthorityOwner :: Authority
+ Web.Mackerel.Types.Authority: AuthorityViewer :: Authority
+ Web.Mackerel.Types.Authority: data Authority
+ Web.Mackerel.Types.Authority: instance Data.Aeson.Types.FromJSON.FromJSON Web.Mackerel.Types.Authority.Authority
+ Web.Mackerel.Types.Authority: instance Data.Aeson.Types.ToJSON.ToJSON Web.Mackerel.Types.Authority.Authority
+ Web.Mackerel.Types.Authority: instance GHC.Classes.Eq Web.Mackerel.Types.Authority.Authority
+ Web.Mackerel.Types.Authority: instance GHC.Read.Read Web.Mackerel.Types.Authority.Authority
+ Web.Mackerel.Types.Authority: instance GHC.Show.Show Web.Mackerel.Types.Authority.Authority
+ Web.Mackerel.Types.Channel: Channel :: ChannelId -> String -> String -> Channel
+ Web.Mackerel.Types.Channel: ChannelId :: String -> ChannelId
+ Web.Mackerel.Types.Channel: [channelId] :: Channel -> ChannelId
+ Web.Mackerel.Types.Channel: [channelName] :: Channel -> String
+ Web.Mackerel.Types.Channel: [channelType] :: Channel -> String
+ Web.Mackerel.Types.Channel: data Channel
+ Web.Mackerel.Types.Channel: data ChannelId
+ Web.Mackerel.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Web.Mackerel.Types.Channel.Channel
+ Web.Mackerel.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Web.Mackerel.Types.Channel.ChannelId
+ Web.Mackerel.Types.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Web.Mackerel.Types.Channel.Channel
+ Web.Mackerel.Types.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Web.Mackerel.Types.Channel.ChannelId
+ Web.Mackerel.Types.Channel: instance GHC.Classes.Eq Web.Mackerel.Types.Channel.Channel
+ Web.Mackerel.Types.Channel: instance GHC.Classes.Eq Web.Mackerel.Types.Channel.ChannelId
+ Web.Mackerel.Types.Channel: instance GHC.Show.Show Web.Mackerel.Types.Channel.Channel
+ Web.Mackerel.Types.Channel: instance GHC.Show.Show Web.Mackerel.Types.Channel.ChannelId
+ Web.Mackerel.Types.User: [userAuthority] :: User -> Authority
- Web.Mackerel.Types.Invitation: Invitation :: String -> InvitationAuthority -> Invitation
+ Web.Mackerel.Types.Invitation: Invitation :: String -> Authority -> Invitation
- Web.Mackerel.Types.Invitation: [invitationAuthority] :: Invitation -> InvitationAuthority
+ Web.Mackerel.Types.Invitation: [invitationAuthority] :: Invitation -> Authority
- Web.Mackerel.Types.User: User :: UserId -> String -> String -> User
+ Web.Mackerel.Types.User: User :: UserId -> String -> String -> Authority -> User

Files

mackerel-client.cabal view
@@ -1,5 +1,5 @@ name:                   mackerel-client-version:                0.1.0+version:                0.2.0 author:                 itchyny maintainer:             itchyny <itchyny@hatena.ne.jp> license:                MIT@@ -24,11 +24,13 @@                       , Web.Mackerel.Types.Organization                       , Web.Mackerel.Types.User                       , Web.Mackerel.Types.Invitation+                      , Web.Mackerel.Types.Authority                       , Web.Mackerel.Types.Service                       , Web.Mackerel.Types.Role                       , Web.Mackerel.Types.Host                       , Web.Mackerel.Types.Metadata                       , Web.Mackerel.Types.Monitor+                      , Web.Mackerel.Types.Channel                       , Web.Mackerel.Types.Alert                       , Web.Mackerel.Types.Dashboard                       , Web.Mackerel.Types.GraphAnnotation@@ -41,6 +43,7 @@                       , Web.Mackerel.Api.Host                       , Web.Mackerel.Api.Metadata                       , Web.Mackerel.Api.Monitor+                      , Web.Mackerel.Api.Channel                       , Web.Mackerel.Api.Alert                       , Web.Mackerel.Api.Dashboard                       , Web.Mackerel.Api.GraphAnnotation@@ -76,6 +79,7 @@                       , Types.HostSpec                       , Types.MetadataSpec                       , Types.MonitorSpec+                      , Types.ChannelSpec                       , Types.AlertSpec                       , Types.DashboardSpec                       , Types.GraphAnnotationSpec
src/Web/Mackerel/Api.hs view
@@ -1,6 +1,7 @@ module Web.Mackerel.Api (module Api, ApiError, errorStatusCode, errorMessage) where  import Web.Mackerel.Api.Alert as Api+import Web.Mackerel.Api.Channel as Api import Web.Mackerel.Api.Dashboard as Api import Web.Mackerel.Api.GraphAnnotation as Api import Web.Mackerel.Api.Host as Api
+ src/Web/Mackerel/Api/Channel.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}+-- | Channel API.+module Web.Mackerel.Api.Channel (listChannels) where++import Data.Aeson.TH (deriveJSON)+import Network.HTTP.Types (StdMethod(..))++import Web.Mackerel.Client+import Web.Mackerel.Internal.Api+import Web.Mackerel.Internal.TH+import Web.Mackerel.Types.Channel++data ListChannelsResponse = ListChannelsResponse { responseChannels :: [Channel] }+$(deriveJSON options ''ListChannelsResponse)++listChannels :: Client -> IO (Either ApiError [Channel])+listChannels client+  = request client GET "/api/v0/channels" [] emptyBody (createHandler responseChannels)
src/Web/Mackerel/Api/Service.hs view
@@ -2,6 +2,8 @@ -- | Service API. module Web.Mackerel.Api.Service   ( listServices+  , createService+  , deleteService   , listServiceMetricNames   ) where @@ -21,6 +23,14 @@ listServices :: Client -> IO (Either ApiError [Service]) listServices client   = request client GET "/api/v0/services" [] emptyBody (createHandler responseServices)++createService :: Client -> Service -> IO (Either ApiError Service)+createService client service+  = request client POST "/api/v0/services" [] (Just service) (createHandler id)++deleteService :: Client -> String -> IO (Either ApiError Service)+deleteService client name+  = request client DELETE ("/api/v0/services/" <> BS.pack name) [] emptyBody (createHandler id)  data ListMetricNamesResponse = ListMetricNamesResponse { responseNames :: [String] } $(deriveJSON options ''ListMetricNamesResponse)
src/Web/Mackerel/Types.hs view
@@ -1,6 +1,7 @@ module Web.Mackerel.Types (module Types) where  import Web.Mackerel.Types.Alert as Types+import Web.Mackerel.Types.Channel as Types import Web.Mackerel.Types.Dashboard as Types import Web.Mackerel.Types.GraphAnnotation as Types import Web.Mackerel.Types.Host as Types
+ src/Web/Mackerel/Types/Authority.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell #-}+module Web.Mackerel.Types.Authority where++import Data.Aeson+import qualified Data.Aeson as Aeson+import Data.Aeson.Types (typeMismatch)+import qualified Data.Text as Text++data Authority = AuthorityOwner+               | AuthorityManager+               | AuthorityCollaborator+               | AuthorityViewer+               deriving Eq++instance Show Authority where+  show AuthorityOwner = "owner"+  show AuthorityManager = "manager"+  show AuthorityCollaborator = "collaborator"+  show AuthorityViewer = "viewer"++instance Read Authority where+  readsPrec _ xs = [ (hs, drop (length str) xs) | (hs, str) <- pairs', take (length str) xs == str ]+    where pairs' = [+            (AuthorityOwner, "owner"),+            (AuthorityManager, "manager"),+            (AuthorityCollaborator, "collaborator"),+            (AuthorityViewer, "viewer")]++instance FromJSON Authority where+  parseJSON (Aeson.String txt)+    | str == "owner" = return AuthorityOwner+    | str == "manager" = return AuthorityManager+    | str == "collaborator" = return AuthorityCollaborator+    | str == "viewer" = return AuthorityViewer+    where str = Text.unpack txt+  parseJSON o = typeMismatch "Authority" o++instance ToJSON Authority where+  toJSON method = toJSON (show method)
+ src/Web/Mackerel/Types/Channel.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE TemplateHaskell #-}+module Web.Mackerel.Types.Channel where++import Data.Aeson+import qualified Data.Aeson as Aeson+import Data.Aeson.TH (deriveJSON)+import Data.Aeson.Types (typeMismatch)+import qualified Data.Text as Text++import Web.Mackerel.Internal.TH++data ChannelId = ChannelId String+               deriving (Eq, Show)++instance FromJSON ChannelId where+  parseJSON (Aeson.String channelId) = return $ ChannelId $ Text.unpack channelId+  parseJSON o = typeMismatch "ChannelId" o++instance ToJSON ChannelId where+  toJSON (ChannelId channelId) = toJSON channelId++data Channel+  = Channel {+    channelId :: ChannelId,+    channelName :: String,+    channelType :: String+  } deriving (Eq, Show)++$(deriveJSON options ''Channel)
src/Web/Mackerel/Types/Invitation.hs view
@@ -8,36 +8,12 @@ import qualified Data.Text as Text  import Web.Mackerel.Internal.TH--data InvitationAuthority = InvitationAuthorityManager-                         | InvitationAuthorityCollaborator-                         | InvitationAuthorityViewer-                         deriving Eq--instance Show InvitationAuthority where-  show InvitationAuthorityManager = "manager"-  show InvitationAuthorityCollaborator = "collaborator"-  show InvitationAuthorityViewer = "viewer"--instance Read InvitationAuthority where-  readsPrec _ xs = [ (hs, drop (length str) xs) | (hs, str) <- pairs', take (length str) xs == str ]-    where pairs' = [(InvitationAuthorityManager, "manager"), (InvitationAuthorityCollaborator, "collaborator"), (InvitationAuthorityViewer, "viewer")]--instance FromJSON InvitationAuthority where-  parseJSON (Aeson.String txt)-    | str == "manager" = return InvitationAuthorityManager-    | str == "collaborator" = return InvitationAuthorityCollaborator-    | str == "viewer" = return InvitationAuthorityViewer-    where str = Text.unpack txt-  parseJSON o = typeMismatch "InvitationAuthority" o--instance ToJSON InvitationAuthority where-  toJSON method = toJSON (show method)+import Web.Mackerel.Types.Authority  data Invitation   = Invitation {     invitationEmail :: String,-    invitationAuthority :: InvitationAuthority+    invitationAuthority :: Authority   } deriving (Eq, Show)  $(deriveJSON options ''Invitation)
src/Web/Mackerel/Types/User.hs view
@@ -8,6 +8,7 @@ import qualified Data.Text as Text  import Web.Mackerel.Internal.TH+import Web.Mackerel.Types.Authority  data UserId = UserId String             deriving (Eq, Show)@@ -23,7 +24,8 @@   = User {     userId :: UserId,     userScreenName :: String,-    userEmail :: String+    userEmail :: String,+    userAuthority :: Authority   } deriving (Eq, Show)  $(deriveJSON options ''User)
+ test/Types/ChannelSpec.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}+module Types.ChannelSpec where++import Control.Monad (forM_)+import Data.Aeson (decode, encode, Value(..))+import Data.Aeson.QQ+import qualified Data.HashMap.Lazy as HM+import Test.Hspec++import Web.Mackerel.Types.Channel++spec :: Spec+spec = do++  let channel1 = Channel {+        channelId = ChannelId "abcde1",+        channelName = "Example Channel 1",+        channelType = "slack"+      }++  let json1 = [aesonQQ|+    {+      "id": "abcde1",+      "name": "Example Channel 1",+      "type": "slack"+    }+  |]++  let channel2 = Channel {+        channelId = ChannelId "abcde2",+        channelName = "Example Channel 2",+        channelType = "email"+      }++  let json2 = [aesonQQ|+    {+      "id": "abcde2",+      "name": "Example Channel 2",+      "type": "email"+    }+  |]++  describe "Channel FromJSON" $ do+    it "should parse a json" $+      forM_ [(channel1, json1), (channel2, json2)] $ \(channel, json) ->+        decode (encode json) `shouldBe` Just channel++    it "should reject an invalid json" $ do+      decode "{}" `shouldBe` (Nothing :: Maybe Channel)+      let (Object hm) = json1+      forM_ ["id", "name", "type"] $ \key ->+        decode (encode (Object (HM.delete key hm))) `shouldBe` (Nothing :: Maybe Channel)++  describe "Channel ToJSON" $+    it "should encode into a json" $+      forM_ [(channel1, json1), (channel2, json2)] $ \(channel, json) ->+        decode (encode channel) `shouldBe` Just json
test/Types/InvitationSpec.hs view
@@ -7,6 +7,7 @@ import qualified Data.HashMap.Lazy as HM import Test.Hspec +import Web.Mackerel.Types.Authority import Web.Mackerel.Types.Invitation  spec :: Spec@@ -14,7 +15,7 @@    let invitation' = Invitation {         invitationEmail = "foobar@example.com",-        invitationAuthority = InvitationAuthorityManager+        invitationAuthority = AuthorityManager       }    let json = [aesonQQ|
test/Types/UserSpec.hs view
@@ -7,6 +7,7 @@ import qualified Data.HashMap.Lazy as HM import Test.Hspec +import Web.Mackerel.Types.Authority import Web.Mackerel.Types.User  spec :: Spec@@ -15,14 +16,16 @@   let user = User {         userId = UserId "abcde",         userScreenName = "Example Mackerel",-        userEmail = "mackerel@example.com"+        userEmail = "mackerel@example.com",+        userAuthority = AuthorityCollaborator       }    let json = [aesonQQ|     {       "id": "abcde",       "screenName": "Example Mackerel",-      "email": "mackerel@example.com"+      "email": "mackerel@example.com",+      "authority": "collaborator"     }   |]