module Cloudy.LocalConfFile where import Cloudy.Path (getCloudyConfFilePath) import Control.Exception (throwIO) import Data.Aeson (FromJSON (parseJSON), withObject, (.:?), Value (Null), Object) import Data.Aeson.Types (Parser) import qualified Data.ByteString as BS import Data.Text (Text) import Data.Yaml (decodeEither') import System.IO.Error (tryIOError, isDoesNotExistError) data LocalConfFileScalewayOpts = LocalConfFileScalewayOpts { accessKey :: Maybe Text , secretKey :: Maybe Text , defaultOrganizationId :: Maybe Text , defaultProjectId :: Maybe Text , defaultZone :: Maybe Text , defaultInstanceType :: Maybe Text , defaultImageId :: Maybe Text } deriving Show instance FromJSON LocalConfFileScalewayOpts where parseJSON :: Value -> Parser LocalConfFileScalewayOpts parseJSON = withObject "LocalConfFileScalewayOpts" $ \o -> do accessKey <- o .:? "access_key" secretKey <- o .:? "secret_key" defaultOrganizationId <- o .:? "default_organization_id" defaultProjectId <- o .:? "default_project_id" defaultZone <- o .:? "default_zone" defaultInstanceType <- o .:? "default_instance_type" defaultImageId <- o .:? "default_image_id" pure LocalConfFileScalewayOpts { accessKey , secretKey , defaultOrganizationId , defaultProjectId , defaultZone , defaultInstanceType , defaultImageId } data LocalConfFileOpts = LocalConfFileOpts { scaleway :: Maybe LocalConfFileScalewayOpts } deriving Show instance FromJSON LocalConfFileOpts where parseJSON Null = pure defaultLocalConfFileOpts parseJSON v = withObject "LocalConfFileOpts" parseObj v where parseObj :: Object -> Parser LocalConfFileOpts parseObj o = do LocalConfFileOpts <$> o .:? "scaleway" defaultLocalConfFileOpts :: LocalConfFileOpts defaultLocalConfFileOpts = LocalConfFileOpts { scaleway = Nothing } readLocalConfFile :: IO LocalConfFileOpts readLocalConfFile = do confFilePath <- getCloudyConfFilePath eitherConfFileRaw <- tryIOError (BS.readFile confFilePath) case eitherConfFileRaw of Left ioEx | isDoesNotExistError ioEx -> -- conf file does not exist yet on disk, just return the default options pure defaultLocalConfFileOpts | otherwise -> -- We got an IOException that we weren't expecting. Rethrow it. throwIO ioEx Right confFileRaw -> do let eitherConfFileOpts = decodeEither' confFileRaw case eitherConfFileOpts of Left parseErr -> -- We got an error when trying to parse the config file. This is unexpected. Throw it. throwIO parseErr Right confFile -> pure confFile