-- | 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 Control.Monad.Except
import Control.Monad.Trans.Control
import Data.Aeson (FromJSON, ToJSON, (.!=), (.:), (.:?), (.=))
import Data.Aeson qualified as J
import Data.Has
import Data.Map.Strict qualified as Map
import Data.Monoid
import Data.Text.Extended (ToTxt (..))
import Hasura.Backends.DataConnector.Adapter.Types qualified as DC.Types
import Hasura.Backends.DataConnector.Agent.Client (AgentClientContext (..), runAgentClientT)
import Hasura.Backends.DataConnector.Agent.Client qualified as Client
import Hasura.Base.Error qualified as Error
import Hasura.EncJSON (EncJSON)
import Hasura.EncJSON qualified as EncJSON
import Hasura.Logging qualified as L
import Hasura.Prelude
import Hasura.RQL.DDL.SourceKinds
import Hasura.RQL.Types.BackendType qualified as Backend
import Hasura.RQL.Types.Common qualified as Common
import Hasura.RQL.Types.Metadata qualified as Metadata
import Hasura.RQL.Types.SchemaCache.Build qualified as SC.Build
import Hasura.SQL.BackendMap qualified as BackendMap
import Hasura.Services.Network
import Hasura.Tracing (ignoreTraceT)
import Servant.Client qualified as Servant

--------------------------------------------------------------------------------

data DCAddAgent = DCAddAgent
  { -- | Source kind, ie., the backend type.
    DCAddAgent -> DataConnectorName
_gdcaName :: DC.Types.DataConnectorName,
    -- | The Agent URL.
    DCAddAgent -> BaseUrl
_gdcaUrl :: Servant.BaseUrl,
    -- | Override the display name provided by the Agent.
    DCAddAgent -> Maybe Text
_gdcaDisplayName :: Maybe Text,
    -- | Optionally skip the Agent Validation step.
    DCAddAgent -> SkipCheck
_gdcaSkipCheck :: SkipCheck
  }

newtype SkipCheck = SkipCheck Bool
  deriving newtype (Value -> Parser [SkipCheck]
Value -> Parser SkipCheck
(Value -> Parser SkipCheck)
-> (Value -> Parser [SkipCheck]) -> FromJSON SkipCheck
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser SkipCheck
parseJSON :: Value -> Parser SkipCheck
$cparseJSONList :: Value -> Parser [SkipCheck]
parseJSONList :: Value -> Parser [SkipCheck]
FromJSON, [SkipCheck] -> Value
[SkipCheck] -> Encoding
SkipCheck -> Value
SkipCheck -> Encoding
(SkipCheck -> Value)
-> (SkipCheck -> Encoding)
-> ([SkipCheck] -> Value)
-> ([SkipCheck] -> Encoding)
-> ToJSON SkipCheck
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: SkipCheck -> Value
toJSON :: SkipCheck -> Value
$ctoEncoding :: SkipCheck -> Encoding
toEncoding :: SkipCheck -> Encoding
$ctoJSONList :: [SkipCheck] -> Value
toJSONList :: [SkipCheck] -> Value
$ctoEncodingList :: [SkipCheck] -> Encoding
toEncodingList :: [SkipCheck] -> Encoding
ToJSON, SkipCheck -> SkipCheck -> Bool
(SkipCheck -> SkipCheck -> Bool)
-> (SkipCheck -> SkipCheck -> Bool) -> Eq SkipCheck
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SkipCheck -> SkipCheck -> Bool
== :: SkipCheck -> SkipCheck -> Bool
$c/= :: SkipCheck -> SkipCheck -> Bool
/= :: SkipCheck -> SkipCheck -> Bool
Eq)
  deriving (NonEmpty SkipCheck -> SkipCheck
SkipCheck -> SkipCheck -> SkipCheck
(SkipCheck -> SkipCheck -> SkipCheck)
-> (NonEmpty SkipCheck -> SkipCheck)
-> (forall b. Integral b => b -> SkipCheck -> SkipCheck)
-> Semigroup SkipCheck
forall b. Integral b => b -> SkipCheck -> SkipCheck
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: SkipCheck -> SkipCheck -> SkipCheck
<> :: SkipCheck -> SkipCheck -> SkipCheck
$csconcat :: NonEmpty SkipCheck -> SkipCheck
sconcat :: NonEmpty SkipCheck -> SkipCheck
$cstimes :: forall b. Integral b => b -> SkipCheck -> SkipCheck
stimes :: forall b. Integral b => b -> SkipCheck -> SkipCheck
Semigroup, Semigroup SkipCheck
SkipCheck
Semigroup SkipCheck
-> SkipCheck
-> (SkipCheck -> SkipCheck -> SkipCheck)
-> ([SkipCheck] -> SkipCheck)
-> Monoid SkipCheck
[SkipCheck] -> SkipCheck
SkipCheck -> SkipCheck -> SkipCheck
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: SkipCheck
mempty :: SkipCheck
$cmappend :: SkipCheck -> SkipCheck -> SkipCheck
mappend :: SkipCheck -> SkipCheck -> SkipCheck
$cmconcat :: [SkipCheck] -> SkipCheck
mconcat :: [SkipCheck] -> SkipCheck
Monoid) via Any

instance FromJSON DCAddAgent where
  parseJSON :: Value -> Parser DCAddAgent
parseJSON = String
-> (Object -> Parser DCAddAgent) -> Value -> Parser DCAddAgent
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"DCAddAgent" \Object
o -> do
    DataConnectorName
_gdcaName <- Object
o Object -> Key -> Parser DataConnectorName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
    Maybe BaseUrl
mUri <- Object
o Object -> Key -> Parser (Maybe BaseUrl)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"url"
    Maybe Text
_gdcaDisplayName <- Object
o Object -> Key -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"display_name"
    SkipCheck
_gdcaSkipCheck <- Object
o Object -> Key -> Parser (Maybe SkipCheck)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"skip_check" Parser (Maybe SkipCheck) -> SkipCheck -> Parser SkipCheck
forall a. Parser (Maybe a) -> a -> Parser a
.!= Bool -> SkipCheck
SkipCheck Bool
False
    case Maybe BaseUrl
mUri of
      Just BaseUrl
_gdcaUrl -> DCAddAgent -> Parser DCAddAgent
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure DCAddAgent {Maybe Text
BaseUrl
DataConnectorName
SkipCheck
_gdcaName :: DataConnectorName
_gdcaUrl :: BaseUrl
_gdcaDisplayName :: Maybe Text
_gdcaSkipCheck :: SkipCheck
_gdcaName :: DataConnectorName
_gdcaDisplayName :: Maybe Text
_gdcaSkipCheck :: SkipCheck
_gdcaUrl :: BaseUrl
..}
      Maybe BaseUrl
Nothing -> String -> Parser DCAddAgent
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Failed to parse Agent URL"

instance ToJSON DCAddAgent where
  toJSON :: DCAddAgent -> Value
toJSON DCAddAgent {Maybe Text
BaseUrl
DataConnectorName
SkipCheck
_gdcaName :: DCAddAgent -> DataConnectorName
_gdcaUrl :: DCAddAgent -> BaseUrl
_gdcaDisplayName :: DCAddAgent -> Maybe Text
_gdcaSkipCheck :: DCAddAgent -> SkipCheck
_gdcaName :: DataConnectorName
_gdcaUrl :: BaseUrl
_gdcaDisplayName :: Maybe Text
_gdcaSkipCheck :: SkipCheck
..} =
    [Pair] -> Value
J.object
      ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ [ Key
"name" Key -> DataConnectorName -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= DataConnectorName
_gdcaName,
          Key
"url" Key -> String -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= BaseUrl -> String
forall a. Show a => a -> String
show BaseUrl
_gdcaUrl,
          Key
"skip_check" Key -> SkipCheck -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SkipCheck
_gdcaSkipCheck
        ]
      [Pair] -> [Pair] -> [Pair]
forall a. [a] -> [a] -> [a]
++ [Key
"display_name" Key -> Maybe Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe Text
_gdcaDisplayName | Maybe Text -> Bool
forall a. Maybe a -> Bool
isJust Maybe Text
_gdcaDisplayName]

-- | Insert a new Data Connector Agent into Metadata.
runAddDataConnectorAgent ::
  ( Metadata.MetadataM m,
    ProvidesNetwork m,
    SC.Build.CacheRWM m,
    Has (L.Logger L.Hasura) r,
    MonadReader r m,
    MonadError Error.QErr m,
    MonadIO m,
    MonadBaseControl IO m
  ) =>
  DCAddAgent ->
  m EncJSON
runAddDataConnectorAgent :: forall (m :: * -> *) r.
(MetadataM m, ProvidesNetwork m, CacheRWM m, Has (Logger Hasura) r,
 MonadReader r m, MonadError QErr m, MonadIO m,
 MonadBaseControl IO m) =>
DCAddAgent -> m EncJSON
runAddDataConnectorAgent DCAddAgent {Maybe Text
BaseUrl
DataConnectorName
SkipCheck
_gdcaName :: DCAddAgent -> DataConnectorName
_gdcaUrl :: DCAddAgent -> BaseUrl
_gdcaDisplayName :: DCAddAgent -> Maybe Text
_gdcaSkipCheck :: DCAddAgent -> SkipCheck
_gdcaName :: DataConnectorName
_gdcaUrl :: BaseUrl
_gdcaDisplayName :: Maybe Text
_gdcaSkipCheck :: SkipCheck
..} = do
  let agent :: DC.Types.DataConnectorOptions
      agent :: DataConnectorOptions
agent = BaseUrl -> Maybe Text -> DataConnectorOptions
DC.Types.DataConnectorOptions BaseUrl
_gdcaUrl Maybe Text
_gdcaDisplayName
  [Text]
sourceKinds <- (:) Text
"postgres" ([Text] -> [Text])
-> (SourceKinds -> [Text]) -> SourceKinds -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceKindInfo -> Text) -> [SourceKindInfo] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SourceKindInfo -> Text
_skiSourceKind ([SourceKindInfo] -> [Text])
-> (SourceKinds -> [SourceKindInfo]) -> SourceKinds -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SourceKinds -> [SourceKindInfo]
unSourceKinds (SourceKinds -> [Text]) -> m SourceKinds -> m [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SourceKinds
forall (m :: * -> *). MetadataM m => m SourceKinds
agentSourceKinds
  if
    | DataConnectorName -> Text
forall a. ToTxt a => a -> Text
toTxt DataConnectorName
_gdcaName Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
sourceKinds -> Code -> Text -> m EncJSON
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
Error.throw400 Code
Error.AlreadyExists (Text -> m EncJSON) -> Text -> m EncJSON
forall a b. (a -> b) -> a -> b
$ Text
"SourceKind '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DataConnectorName -> Text
forall a. ToTxt a => a -> Text
toTxt DataConnectorName
_gdcaName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"' already exists."
    | SkipCheck
_gdcaSkipCheck SkipCheck -> SkipCheck -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> SkipCheck
SkipCheck Bool
True -> DataConnectorName -> DataConnectorOptions -> m EncJSON
forall (m :: * -> *).
(MonadError QErr m, MetadataM m, CacheRWM m) =>
DataConnectorName -> DataConnectorOptions -> m EncJSON
addAgent DataConnectorName
_gdcaName DataConnectorOptions
agent
    | Bool
otherwise ->
        BaseUrl -> m Availability
forall (m :: * -> *) r.
(ProvidesNetwork m, Has (Logger Hasura) r, MonadReader r m,
 MonadIO m, MonadBaseControl IO m) =>
BaseUrl -> m Availability
checkAgentAvailability BaseUrl
_gdcaUrl m Availability -> (Availability -> m EncJSON) -> m EncJSON
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          NotAvailable QErr
err ->
            EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
              (EncJSON -> m EncJSON) -> EncJSON -> m EncJSON
forall a b. (a -> b) -> a -> b
$ Value -> EncJSON
forall a. ToJSON a => a -> EncJSON
EncJSON.encJFromJValue
              (Value -> EncJSON) -> Value -> EncJSON
forall a b. (a -> b) -> a -> b
$ [Pair] -> Value
J.object
                [ (Key
"message" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text -> Value
J.String Text
"Agent is not available"),
                  (Key
"details" Key -> QErr -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= QErr
err)
                ]
          Availability
_ -> DataConnectorName -> DataConnectorOptions -> m EncJSON
forall (m :: * -> *).
(MonadError QErr m, MetadataM m, CacheRWM m) =>
DataConnectorName -> DataConnectorOptions -> m EncJSON
addAgent DataConnectorName
_gdcaName DataConnectorOptions
agent

addAgent :: (MonadError Error.QErr m, SC.Build.MetadataM m, SC.Build.CacheRWM m) => DC.Types.DataConnectorName -> DC.Types.DataConnectorOptions -> m EncJSON
addAgent :: forall (m :: * -> *).
(MonadError QErr m, MetadataM m, CacheRWM m) =>
DataConnectorName -> DataConnectorOptions -> m EncJSON
addAgent DataConnectorName
agentName DataConnectorOptions
agent = do
  let modifier' :: MetadataModifier
modifier' =
        (Metadata -> Metadata) -> MetadataModifier
Metadata.MetadataModifier
          ((Metadata -> Metadata) -> MetadataModifier)
-> (Metadata -> Metadata) -> MetadataModifier
forall a b. (a -> b) -> a -> b
$ (BackendMap BackendConfigWrapper
 -> Identity (BackendMap BackendConfigWrapper))
-> Metadata -> Identity Metadata
Lens' Metadata (BackendMap BackendConfigWrapper)
Metadata.metaBackendConfigs
          ((BackendMap BackendConfigWrapper
  -> Identity (BackendMap BackendConfigWrapper))
 -> Metadata -> Identity Metadata)
-> (BackendMap BackendConfigWrapper
    -> BackendMap BackendConfigWrapper)
-> Metadata
-> Metadata
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ forall (b :: BackendType) (i :: BackendType -> *).
(HasTag b, Monoid (i b)) =>
(i b -> i b) -> BackendMap i -> BackendMap i
BackendMap.modify @'Backend.DataConnector \BackendConfigWrapper 'DataConnector
oldMap ->
            BackendConfig 'DataConnector -> BackendConfigWrapper 'DataConnector
forall (b :: BackendType).
BackendConfig b -> BackendConfigWrapper b
Metadata.BackendConfigWrapper (BackendConfig 'DataConnector
 -> BackendConfigWrapper 'DataConnector)
-> BackendConfig 'DataConnector
-> BackendConfigWrapper 'DataConnector
forall a b. (a -> b) -> a -> b
$ DataConnectorName
-> DataConnectorOptions
-> Map DataConnectorName DataConnectorOptions
-> Map DataConnectorName DataConnectorOptions
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert DataConnectorName
agentName DataConnectorOptions
agent (BackendConfigWrapper 'DataConnector
-> Map DataConnectorName DataConnectorOptions
forall a b. Coercible a b => a -> b
coerce BackendConfigWrapper 'DataConnector
oldMap)
  m () -> m ()
forall (m :: * -> *) a. (QErrM m, CacheRM m) => m a -> m a
SC.Build.withNewInconsistentObjsCheck (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ MetadataModifier -> m ()
forall (m :: * -> *).
(MetadataM m, CacheRWM m) =>
MetadataModifier -> m ()
SC.Build.buildSchemaCache MetadataModifier
modifier'

  EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure EncJSON
Common.successMsg

data Availability = Available | NotAvailable Error.QErr

-- | Check DC Agent availability by checking its Capabilities endpoint.
checkAgentAvailability ::
  ( ProvidesNetwork m,
    Has (L.Logger L.Hasura) r,
    MonadReader r m,
    MonadIO m,
    MonadBaseControl IO m
  ) =>
  Servant.BaseUrl ->
  m Availability
checkAgentAvailability :: forall (m :: * -> *) r.
(ProvidesNetwork m, Has (Logger Hasura) r, MonadReader r m,
 MonadIO m, MonadBaseControl IO m) =>
BaseUrl -> m Availability
checkAgentAvailability BaseUrl
url = do
  Manager
manager <- m Manager
forall (m :: * -> *). ProvidesNetwork m => m Manager
askHTTPManager
  Logger Hasura
logger <- (r -> Logger Hasura) -> m (Logger Hasura)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks r -> Logger Hasura
forall a t. Has a t => t -> a
getter
  Either QErr CapabilitiesResponse
res <- ExceptT QErr m CapabilitiesResponse
-> m (Either QErr CapabilitiesResponse)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT QErr m CapabilitiesResponse
 -> m (Either QErr CapabilitiesResponse))
-> (AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
    -> ExceptT QErr m CapabilitiesResponse)
-> AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
-> m (Either QErr CapabilitiesResponse)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TraceT (ExceptT QErr m) CapabilitiesResponse
-> ExceptT QErr m CapabilitiesResponse
forall (m :: * -> *) a. TraceT m a -> m a
ignoreTraceT (TraceT (ExceptT QErr m) CapabilitiesResponse
 -> ExceptT QErr m CapabilitiesResponse)
-> (AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
    -> TraceT (ExceptT QErr m) CapabilitiesResponse)
-> AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
-> ExceptT QErr m CapabilitiesResponse
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
 -> AgentClientContext
 -> TraceT (ExceptT QErr m) CapabilitiesResponse)
-> AgentClientContext
-> AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
-> TraceT (ExceptT QErr m) CapabilitiesResponse
forall a b c. (a -> b -> c) -> b -> a -> c
flip AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
-> AgentClientContext
-> TraceT (ExceptT QErr m) CapabilitiesResponse
forall (m :: * -> *) a.
AgentClientT m a -> AgentClientContext -> m a
runAgentClientT (Logger Hasura
-> BaseUrl
-> Manager
-> Maybe Int
-> Maybe AgentLicenseKey
-> AgentClientContext
AgentClientContext Logger Hasura
logger BaseUrl
url Manager
manager Maybe Int
forall a. Maybe a
Nothing Maybe AgentLicenseKey
forall a. Maybe a
Nothing) (AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
 -> m (Either QErr CapabilitiesResponse))
-> AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
-> m (Either QErr CapabilitiesResponse)
forall a b. (a -> b) -> a -> b
$ AgentClientT (TraceT (ExceptT QErr m)) CapabilitiesResponse
forall (m :: * -> *).
(MonadIO m, MonadTrace m, MonadError QErr m) =>
AgentClientT m CapabilitiesResponse
Client.capabilities
  -- NOTE: 'capabilitiesCase' does not handle the 'no connection to host' scenario so we must handle it explicitly here:
  Availability -> m Availability
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((QErr -> Availability)
-> (CapabilitiesResponse -> Availability)
-> Either QErr CapabilitiesResponse
-> Availability
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either QErr -> Availability
NotAvailable (Availability -> CapabilitiesResponse -> Availability
forall a b. a -> b -> a
const Availability
Available) Either QErr CapabilitiesResponse
res)

--------------------------------------------------------------------------------

newtype DCDeleteAgent = DCDeleteAgent {DCDeleteAgent -> DataConnectorName
_dcdaName :: DC.Types.DataConnectorName}

instance FromJSON DCDeleteAgent where
  parseJSON :: Value -> Parser DCDeleteAgent
parseJSON = String
-> (Object -> Parser DCDeleteAgent)
-> Value
-> Parser DCDeleteAgent
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"DCDeleteAgent" \Object
o -> do
    DataConnectorName
_dcdaName <- Object
o Object -> Key -> Parser DataConnectorName
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
    DCDeleteAgent -> Parser DCDeleteAgent
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DCDeleteAgent -> Parser DCDeleteAgent)
-> DCDeleteAgent -> Parser DCDeleteAgent
forall a b. (a -> b) -> a -> b
$ DCDeleteAgent {DataConnectorName
_dcdaName :: DataConnectorName
_dcdaName :: DataConnectorName
..}

instance ToJSON DCDeleteAgent where
  toJSON :: DCDeleteAgent -> Value
toJSON DCDeleteAgent {DataConnectorName
_dcdaName :: DCDeleteAgent -> DataConnectorName
_dcdaName :: DataConnectorName
..} = [Pair] -> Value
J.object [Key
"name" Key -> DataConnectorName -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= DataConnectorName
_dcdaName]

-- | Delete a Data Connector Agent from the Metadata.
runDeleteDataConnectorAgent ::
  ( SC.Build.CacheRWM m,
    Metadata.MetadataM m,
    MonadError Error.QErr m
  ) =>
  DCDeleteAgent ->
  m EncJSON
runDeleteDataConnectorAgent :: forall (m :: * -> *).
(CacheRWM m, MetadataM m, MonadError QErr m) =>
DCDeleteAgent -> m EncJSON
runDeleteDataConnectorAgent DCDeleteAgent {DataConnectorName
_dcdaName :: DCDeleteAgent -> DataConnectorName
_dcdaName :: DataConnectorName
..} = do
  Metadata
oldMetadata <- m Metadata
forall (m :: * -> *). MetadataM m => m Metadata
Metadata.getMetadata

  let kindExists :: Maybe DataConnectorOptions
kindExists = do
        BackendConfigWrapper 'DataConnector
agentMap <- forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
BackendMap i -> Maybe (i b)
BackendMap.lookup @'Backend.DataConnector (BackendMap BackendConfigWrapper
 -> Maybe (BackendConfigWrapper 'DataConnector))
-> BackendMap BackendConfigWrapper
-> Maybe (BackendConfigWrapper 'DataConnector)
forall a b. (a -> b) -> a -> b
$ Metadata -> BackendMap BackendConfigWrapper
Metadata._metaBackendConfigs Metadata
oldMetadata
        DataConnectorName
-> Map DataConnectorName DataConnectorOptions
-> Maybe DataConnectorOptions
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup DataConnectorName
_dcdaName (Map DataConnectorName DataConnectorOptions
 -> Maybe DataConnectorOptions)
-> Map DataConnectorName DataConnectorOptions
-> Maybe DataConnectorOptions
forall a b. (a -> b) -> a -> b
$ BackendConfigWrapper 'DataConnector -> BackendConfig 'DataConnector
forall (b :: BackendType).
BackendConfigWrapper b -> BackendConfig b
Metadata.unBackendConfigWrapper BackendConfigWrapper 'DataConnector
agentMap
  case Maybe DataConnectorOptions
kindExists of
    Maybe DataConnectorOptions
Nothing -> Code -> Text -> m EncJSON
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
Error.throw400 Code
Error.NotFound (Text -> m EncJSON) -> Text -> m EncJSON
forall a b. (a -> b) -> a -> b
$ Text
"DC Agent '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DataConnectorName -> Text
forall a. ToTxt a => a -> Text
toTxt DataConnectorName
_dcdaName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"' not found"
    Just DataConnectorOptions
_ -> do
      let modifier' :: MetadataModifier
modifier' =
            (Metadata -> Metadata) -> MetadataModifier
Metadata.MetadataModifier
              ((Metadata -> Metadata) -> MetadataModifier)
-> (Metadata -> Metadata) -> MetadataModifier
forall a b. (a -> b) -> a -> b
$ (BackendMap BackendConfigWrapper
 -> Identity (BackendMap BackendConfigWrapper))
-> Metadata -> Identity Metadata
Lens' Metadata (BackendMap BackendConfigWrapper)
Metadata.metaBackendConfigs
              ((BackendMap BackendConfigWrapper
  -> Identity (BackendMap BackendConfigWrapper))
 -> Metadata -> Identity Metadata)
-> (BackendMap BackendConfigWrapper
    -> BackendMap BackendConfigWrapper)
-> Metadata
-> Metadata
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
(Maybe (i b) -> Maybe (i b)) -> BackendMap i -> BackendMap i
BackendMap.alter @'Backend.DataConnector
                ((BackendConfigWrapper 'DataConnector
 -> BackendConfigWrapper 'DataConnector)
-> Maybe (BackendConfigWrapper 'DataConnector)
-> Maybe (BackendConfigWrapper 'DataConnector)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Map DataConnectorName DataConnectorOptions
-> BackendConfigWrapper 'DataConnector
forall a b. Coercible a b => a -> b
coerce (Map DataConnectorName DataConnectorOptions
 -> BackendConfigWrapper 'DataConnector)
-> (BackendConfigWrapper 'DataConnector
    -> Map DataConnectorName DataConnectorOptions)
-> BackendConfigWrapper 'DataConnector
-> BackendConfigWrapper 'DataConnector
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DataConnectorName
-> Map DataConnectorName DataConnectorOptions
-> Map DataConnectorName DataConnectorOptions
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete DataConnectorName
_dcdaName (Map DataConnectorName DataConnectorOptions
 -> Map DataConnectorName DataConnectorOptions)
-> (BackendConfigWrapper 'DataConnector
    -> Map DataConnectorName DataConnectorOptions)
-> BackendConfigWrapper 'DataConnector
-> Map DataConnectorName DataConnectorOptions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BackendConfigWrapper 'DataConnector
-> Map DataConnectorName DataConnectorOptions
BackendConfigWrapper 'DataConnector -> BackendConfig 'DataConnector
forall (b :: BackendType).
BackendConfigWrapper b -> BackendConfig b
Metadata.unBackendConfigWrapper))

      m () -> m ()
forall (m :: * -> *) a. (QErrM m, CacheRM m) => m a -> m a
SC.Build.withNewInconsistentObjsCheck (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ MetadataModifier -> m ()
forall (m :: * -> *).
(MetadataM m, CacheRWM m) =>
MetadataModifier -> m ()
SC.Build.buildSchemaCache MetadataModifier
modifier'
      EncJSON -> m EncJSON
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure EncJSON
Common.successMsg