graphql-engine/server/src-lib/Hasura/RQL/DDL/DataConnector.hs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

114 lines
3.9 KiB
Haskell
Raw Normal View History

-- | This module provides operations to load and modify metadata
-- relating to GraphQL Data Connectors.
module Hasura.RQL.DDL.DataConnector
( -- * DC Add Agent
DCAddAgent (..),
runAddDataConnectorAgent,
-- * DC Delete Agent
DCDeleteAgent (..),
runDeleteDataConnectorAgent,
)
where
--------------------------------------------------------------------------------
import Data.Aeson (FromJSON, ToJSON, (.:), (.=))
import Data.Aeson qualified as Aeson
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
import Data.Text.NonEmpty (NonEmptyText)
import Data.Text.NonEmpty qualified as Text.NE
import Hasura.Backends.DataConnector.Adapter.Types qualified as DC.Types
import Hasura.Base.Error qualified as Error
import Hasura.EncJSON (EncJSON)
import Hasura.Prelude
import Hasura.RQL.Types.Common qualified as Common
import Hasura.RQL.Types.Metadata qualified as Metadata
import Hasura.RQL.Types.SchemaCache qualified as SchemaCache
import Hasura.RQL.Types.SchemaCache.Build qualified as SC.Build
import Hasura.SQL.Backend qualified as Backend
import Hasura.SQL.BackendMap qualified as BackendMap
import Servant.Client qualified as Servant
--------------------------------------------------------------------------------
data DCAddAgent = DCAddAgent
{ _gdcaName :: NonEmptyText,
_gdcaUrl :: Servant.BaseUrl
}
instance FromJSON DCAddAgent where
parseJSON = Aeson.withObject "DCAddAgent" \o -> do
_gdcaName <- o .: "name"
mUri <- o .: "url"
case mUri of
Just _gdcaUrl -> pure DCAddAgent {..}
Nothing -> fail "Failed to parse Agent URL"
instance ToJSON DCAddAgent where
toJSON DCAddAgent {..} = Aeson.object ["name" .= _gdcaName, "url" .= show _gdcaUrl]
-- | Insert a new Data Connector Agent into Metadata.
runAddDataConnectorAgent ::
( Metadata.MetadataM m,
SC.Build.CacheRWM m,
MonadError Error.QErr m
) =>
DCAddAgent ->
m EncJSON
runAddDataConnectorAgent DCAddAgent {..} = do
let kind = DC.Types.DataConnectorName _gdcaName
agent = DC.Types.DataConnectorOptions _gdcaUrl
oldMetadata <- Metadata.getMetadata
let modifiedMetadata =
oldMetadata & Metadata.metaBackendConfigs %~ BackendMap.modify @'Backend.DataConnector \oldMap ->
Metadata.BackendConfigWrapper $ InsOrdHashMap.insert kind agent (coerce oldMap)
SC.Build.withNewInconsistentObjsCheck $
SC.Build.buildSchemaCache $ Metadata.MetadataModifier $ const modifiedMetadata
pure Common.successMsg
--------------------------------------------------------------------------------
newtype DCDeleteAgent = DCDeleteAgent {_dcdaName :: NonEmptyText}
instance FromJSON DCDeleteAgent where
parseJSON = Aeson.withObject "DCDeleteAgent" \o -> do
_dcdaName <- o .: "name"
pure $ DCDeleteAgent {..}
instance ToJSON DCDeleteAgent where
toJSON DCDeleteAgent {..} = Aeson.object ["name" .= _dcdaName]
-- | Delete a Data Connector Agent from the Metadata.
runDeleteDataConnectorAgent ::
( SchemaCache.CacheRM m,
SC.Build.CacheRWM m,
Metadata.MetadataM m,
MonadError Error.QErr m
) =>
DCDeleteAgent ->
m EncJSON
runDeleteDataConnectorAgent DCDeleteAgent {..} = do
let kind = DC.Types.DataConnectorName _dcdaName
oldMetadata <- Metadata.getMetadata
let kindExists = do
agentMap <- BackendMap.lookup @'Backend.DataConnector $ Metadata._metaBackendConfigs oldMetadata
InsOrdHashMap.lookup kind $ Metadata.unBackendConfigWrapper agentMap
case kindExists of
Nothing -> Error.throw400 Error.NotFound $ "DC Agent '" <> Text.NE.unNonEmptyText _dcdaName <> "' not found"
Just _ -> do
let modifiedMetadata =
oldMetadata & Metadata.metaBackendConfigs
%~ BackendMap.alter @'Backend.DataConnector
(fmap (coerce . InsOrdHashMap.delete kind . Metadata.unBackendConfigWrapper))
SC.Build.withNewInconsistentObjsCheck $
SC.Build.buildSchemaCache $ Metadata.MetadataModifier $ const modifiedMetadata
pure Common.successMsg