{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE ScopedTypeVariables #-} module Network.Linode.Api where import qualified Network.Linode.Request as Req (Linode, Disk, Config, Config) import qualified Network.Linode.Response as Rsp (Linode (id), Linodes, Service, Services, Datacenter, Datacenters, Distribution, Distributions, DNSZone, DNSZones, Kernel, Kernels, Disks, Disk, Configs, Config) import Prelude hiding (id) import Data.Aeson import qualified Data.List (intercalate) import qualified Data.ByteString as S (ByteString) import qualified Data.ByteString.Char8 (pack) import qualified Data.Maybe (Maybe (Just, Nothing)) import qualified Network.HTTP.Conduit (parseRequest_) import qualified Network.HTTP.Simple (Request, httpJSON, addRequestHeader, getResponseBody, setRequestBodyJSON) import qualified System.Environment (getEnv) import qualified Text.Printf (printf) apiRoot :: String apiRoot = "https://api.alpha.linode.com/v4" setAuthHeader :: Network.HTTP.Simple.Request -> IO Network.HTTP.Simple.Request setAuthHeader request = do token <- System.Environment.getEnv "LINODE_TOKEN" let authorizationValue :: S.ByteString = Data.ByteString.Char8.pack $ Text.Printf.printf "token %s" token return $ Network.HTTP.Simple.addRequestHeader "Authorization" authorizationValue request getJson :: Data.Aeson.FromJSON a => String -> [String] -> IO (Data.Maybe.Maybe a) getJson method urlFragments = do let endpoint = Data.List.intercalate "/" urlFragments let requestString = Text.Printf.printf "%s %s%s" method apiRoot endpoint request <- setAuthHeader $ Network.HTTP.Conduit.parseRequest_ requestString response <- Network.HTTP.Simple.httpJSON request return $ Network.HTTP.Simple.getResponseBody response get :: Data.Aeson.FromJSON a => [String] -> IO (Data.Maybe.Maybe a) get = getJson "GET" delete :: Data.Aeson.FromJSON a => [String] -> IO (Data.Maybe.Maybe a) delete = getJson "DELETE" sendJson :: Data.Aeson.ToJSON a => Data.Aeson.FromJSON b => String -> [String] -> a -> IO (Data.Maybe.Maybe b) sendJson method urlFragments object = do let endpoint = Data.List.intercalate "/" urlFragments let requestString = Text.Printf.printf "%s %s%s" method apiRoot endpoint request <- setAuthHeader $ Network.HTTP.Simple.setRequestBodyJSON object $ Network.HTTP.Conduit.parseRequest_ requestString response <- Network.HTTP.Simple.httpJSON request return $ Network.HTTP.Simple.getResponseBody response post :: Data.Aeson.ToJSON a => Data.Aeson.FromJSON b => [String] -> a -> IO (Data.Maybe.Maybe b) post = sendJson "POST" put :: Data.Aeson.ToJSON a => Data.Aeson.FromJSON b => [String] -> a -> IO (Data.Maybe.Maybe b) put = sendJson "PUT" getDatacenters :: IO (Data.Maybe.Maybe Rsp.Datacenters) getDatacenters = get ["/datacenters"] getDatacenter :: String -> IO (Data.Maybe.Maybe Rsp.Datacenter) getDatacenter id = get ["/datacenters", id] getDistributions :: IO (Data.Maybe.Maybe Rsp.Distributions) getDistributions = get ["/distributions"] getDistributionsRecommended :: IO (Data.Maybe.Maybe Rsp.Distributions) getDistributionsRecommended = get ["/distributions/recommended"] getDistribution :: String -> IO (Data.Maybe.Maybe Rsp.Distribution) getDistribution id = get ["/distributions", id] getLinodes :: IO (Data.Maybe.Maybe Rsp.Linodes) getLinodes = get ["/linodes"] getLinode :: String -> IO (Data.Maybe.Maybe Rsp.Linode) getLinode id = get ["/linodes", id] addLinode :: Req.Linode -> IO (Data.Maybe.Maybe Rsp.Linode) addLinode linode = post ["/linodes"] linode editLinode :: Rsp.Linode -> IO (Data.Maybe.Maybe Rsp.Linode) editLinode linode = put ["/linodes", Rsp.id linode] linode getDisks :: String -> IO (Data.Maybe.Maybe Rsp.Disks) getDisks linodeId = get ["/linodes", linodeId, "disks"] getDisk :: String -> String -> IO (Data.Maybe.Maybe Rsp.Disk) getDisk linodeId diskId = get ["/linodes", linodeId, "disks", diskId] addDisk :: String -> Req.Disk -> IO (Data.Maybe.Maybe Rsp.Disk) addDisk linodeId disk = post ["/linodes", linodeId] disk getConfigs :: String -> IO (Data.Maybe.Maybe Rsp.Configs) getConfigs linodeId = get ["/linodes", linodeId, "configs"] getConfig :: String -> String -> IO (Data.Maybe.Maybe Rsp.Config) getConfig linodeId configId = get ["/linodes", linodeId, "configs", configId] addConfig :: String -> Req.Config -> IO (Data.Maybe.Maybe Rsp.Config) addConfig linodeId config = post ["/linodes", linodeId, "configs"] config getServices :: IO (Data.Maybe.Maybe Rsp.Services) getServices = get ["/services"] getService :: String -> IO (Data.Maybe.Maybe Rsp.Service) getService id = get ["/services", id] getDNSZones :: IO (Data.Maybe.Maybe Rsp.DNSZones) getDNSZones = get ["/dnszones"] getDNSZone :: String -> IO (Data.Maybe.Maybe Rsp.DNSZone) getDNSZone id = get ["/dnszones", id] getKernels :: IO (Data.Maybe.Maybe Rsp.Kernels) getKernels = get ["/kernels"] getKernel :: String -> IO (Data.Maybe.Maybe Rsp.Kernel) getKernel id = get ["/kernels", id]