mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 08:02:15 +03:00
feat: Handle logical models in metadata when the feature is disabled
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8443 GitOrigin-RevId: 4df0f62979dc78103b786b6f0f8ffcde6def0739
This commit is contained in:
parent
2fb455b813
commit
926d5ecdb0
@ -3,6 +3,9 @@
|
||||
-- | Tests of the Logical Models feature.
|
||||
module Test.API.Metadata.LogicalModelsSpec (spec) where
|
||||
|
||||
import Control.Lens
|
||||
import Data.Aeson qualified as A
|
||||
import Data.Aeson.Lens
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Harness.Backend.BigQuery qualified as BigQuery
|
||||
import Harness.Backend.Citus qualified as Citus
|
||||
@ -10,13 +13,17 @@ import Harness.Backend.Cockroach qualified as Cockroach
|
||||
import Harness.Backend.Postgres qualified as Postgres
|
||||
import Harness.Backend.Sqlserver qualified as Sqlserver
|
||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||
import Harness.Quoter.Graphql
|
||||
import Harness.Quoter.Yaml (yaml)
|
||||
import Harness.Quoter.Yaml.InterpolateYaml
|
||||
import Harness.Services.GraphqlEngine
|
||||
import Harness.Services.Metadata
|
||||
import Harness.Services.PostgresSource
|
||||
import Harness.Test.BackendType qualified as BackendType
|
||||
import Harness.Test.Fixture qualified as Fixture
|
||||
import Harness.Test.Schema qualified as Schema
|
||||
import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment (options), getBackendTypeConfig, scalarTypeToText)
|
||||
import Harness.Yaml (shouldReturnYaml)
|
||||
import Harness.Yaml (shouldBeYaml, shouldReturnYaml)
|
||||
import Hasura.Prelude
|
||||
import Test.Hspec (SpecWith, describe, it)
|
||||
|
||||
@ -69,6 +76,8 @@ spec = do
|
||||
(Fixture.runClean fixtures)
|
||||
[testImplementation, testPermissions]
|
||||
|
||||
metadataHandlingWhenDisabledSpec
|
||||
|
||||
-- ** Setup and teardown
|
||||
|
||||
schema :: [Schema.Table]
|
||||
@ -611,3 +620,109 @@ testPermissionFailures = do
|
||||
error: *expectedError
|
||||
path: "$.args"
|
||||
|]
|
||||
|
||||
metadataHandlingWhenDisabledSpec :: SpecWith GlobalTestEnvironment
|
||||
metadataHandlingWhenDisabledSpec = do
|
||||
describe "When logical models are enabled" do
|
||||
withHge
|
||||
( emptyHgeConfig
|
||||
{ hgeConfigEnvironmentVars =
|
||||
[ (featureFlagForLogicalModels, "True")
|
||||
]
|
||||
}
|
||||
)
|
||||
$ withPostgresSource "default"
|
||||
$ do
|
||||
it "`replace_metadata` does not report any inconsistent objects" $ \env -> do
|
||||
currentMetadata <- export_metadata env
|
||||
actual <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
|
||||
actual
|
||||
`shouldBeYaml` [yaml|
|
||||
inconsistent_objects: []
|
||||
is_consistent: true
|
||||
|]
|
||||
|
||||
it "They do appear in the schema" $ \env -> do
|
||||
currentMetadata <- export_metadata env
|
||||
_res <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
data:
|
||||
__type:
|
||||
name: divided_stuff
|
||||
|]
|
||||
|
||||
actual <- hgePostGraphql env queryTypesIntrospection
|
||||
actual `shouldBeYaml` expected
|
||||
|
||||
describe "When logical models are disabled" do
|
||||
withHge emptyHgeConfig $ do
|
||||
withPostgresSource "default" $ do
|
||||
it "`replace_metadata` preserves logical models" $ \env -> do
|
||||
currentMetadata <- export_metadata env
|
||||
_ <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
actual <- export_metadata env
|
||||
actual `shouldBeYaml` (metadataWithLogicalModel currentMetadata)
|
||||
|
||||
it "`replace_metadata` reports inconsistent objects" $ \env -> do
|
||||
currentMetadata <- export_metadata env
|
||||
actual <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
|
||||
actual
|
||||
`shouldBeYaml` [yaml|
|
||||
inconsistent_objects:
|
||||
- definition: *logicalModelsMetadata
|
||||
name: logical_model divided_stuff in source default
|
||||
reason: 'Inconsistent object: The Logical Models feature is disabled'
|
||||
type: logical_model
|
||||
is_consistent: false
|
||||
|]
|
||||
|
||||
it "They do not appear in the schema" $ \env -> do
|
||||
currentMetadata <- export_metadata env
|
||||
_res <- replace_metadata env (metadataWithLogicalModel currentMetadata)
|
||||
|
||||
let expected =
|
||||
[yaml|
|
||||
data:
|
||||
__type: null
|
||||
|]
|
||||
|
||||
actual <- hgePostGraphql env queryTypesIntrospection
|
||||
actual `shouldBeYaml` expected
|
||||
where
|
||||
logicalModelsMetadata =
|
||||
[yaml|
|
||||
arguments:
|
||||
divided:
|
||||
nullable: false
|
||||
type: int
|
||||
code: SELECT {{divided}} as divided
|
||||
returns:
|
||||
columns:
|
||||
- name: divided
|
||||
description: a divided thing
|
||||
nullable: false
|
||||
type: integer
|
||||
root_field_name: divided_stuff
|
||||
|]
|
||||
|
||||
metadataWithLogicalModel :: A.Value -> A.Value
|
||||
metadataWithLogicalModel currentMetadata =
|
||||
currentMetadata
|
||||
& key "sources"
|
||||
. nth 0
|
||||
. atKey "logical_models"
|
||||
.~ Just [yaml| - *logicalModelsMetadata |]
|
||||
|
||||
queryTypesIntrospection :: A.Value
|
||||
queryTypesIntrospection =
|
||||
[graphql|
|
||||
query {
|
||||
__type(name: "divided_stuff") {
|
||||
name
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
@ -9,6 +9,7 @@ module Harness.Services.GraphqlEngine
|
||||
spawnServer,
|
||||
emptyHgeConfig,
|
||||
hgePost,
|
||||
hgePostGraphql,
|
||||
)
|
||||
where
|
||||
|
||||
@ -280,10 +281,10 @@ hgeLogRelayThread logger hgeOutput = do
|
||||
logParser = json' <* (option () (void (string "\n")) <|> endOfInput)
|
||||
|
||||
hgePost ::
|
||||
( Has HgeServerInstance a,
|
||||
Has Logger a
|
||||
( Has HgeServerInstance env,
|
||||
Has Logger env
|
||||
) =>
|
||||
a ->
|
||||
env ->
|
||||
Int ->
|
||||
Text ->
|
||||
Http.RequestHeaders ->
|
||||
@ -296,3 +297,13 @@ hgePost env statusCode path headers requestBody = do
|
||||
responseBody <- withFrozenCallStack $ Http.postValueWithStatus statusCode fullUrl headers requestBody
|
||||
testLogMessage env $ LogHGEResponse path responseBody
|
||||
return responseBody
|
||||
|
||||
hgePostGraphql ::
|
||||
( Has HgeServerInstance env,
|
||||
Has Logger env
|
||||
) =>
|
||||
env ->
|
||||
Value ->
|
||||
IO Value
|
||||
hgePostGraphql env query = do
|
||||
hgePost env 200 "/v1/graphql" [] (object ["query" .= query])
|
||||
|
@ -23,11 +23,13 @@ withPostgresSource ::
|
||||
SpecWith (PostgresSource, a) ->
|
||||
SpecWith a
|
||||
withPostgresSource sourceName specs =
|
||||
flip aroundWith specs \action env -> do
|
||||
pg_add_source env sourceName
|
||||
-- TODO assert that res is a success result
|
||||
-- TODO: use 'managed'?
|
||||
action (PostgresSource sourceName, env)
|
||||
-- We mark "Postgres" to interoperate with HASURA_TEST_BACKEND_TYPE.
|
||||
describe "Postgres" $
|
||||
flip aroundWith specs \action env -> do
|
||||
pg_add_source env sourceName
|
||||
-- TODO assert that res is a success result
|
||||
-- TODO: use 'managed'?
|
||||
action (PostgresSource sourceName, env)
|
||||
|
||||
pg_add_source ::
|
||||
( Has Logger env,
|
||||
|
@ -92,6 +92,7 @@ import Hasura.SQL.Backend
|
||||
import Hasura.SQL.BackendMap (BackendMap)
|
||||
import Hasura.SQL.BackendMap qualified as BackendMap
|
||||
import Hasura.SQL.Tag
|
||||
import Hasura.Server.Init.FeatureFlag qualified as FF
|
||||
import Hasura.Server.Migrate.Version
|
||||
import Hasura.Server.Types
|
||||
import Hasura.Services
|
||||
@ -624,6 +625,7 @@ buildSchemaCacheRule logger env = proc (metadataNoDefaults, serverConfigCtx, inv
|
||||
ArrowKleisli m arr,
|
||||
ArrowWriter (Seq (Either InconsistentMetadata MetadataDependency)) arr,
|
||||
MonadError QErr m,
|
||||
MonadIO m,
|
||||
BackendMetadata b,
|
||||
GetAggregationPredicatesDeps b
|
||||
) =>
|
||||
@ -722,30 +724,50 @@ buildSchemaCacheRule logger env = proc (metadataNoDefaults, serverConfigCtx, inv
|
||||
|
||||
let functionCache = mapFromL _fiSQLName $ catMaybes functionCacheMaybes
|
||||
|
||||
areLogicalModelsEnabled <-
|
||||
bindA
|
||||
-< do
|
||||
let CheckFeatureFlag checkFeatureFlag = _sccCheckFeatureFlag serverConfigCtx
|
||||
liftIO @m $ checkFeatureFlag FF.logicalModelInterface
|
||||
|
||||
let mkLogicalModelMetadataObject :: LogicalModelMetadata b -> MetadataObject
|
||||
mkLogicalModelMetadataObject lmm =
|
||||
( MetadataObject
|
||||
( MOSourceObjId sourceName $
|
||||
AB.mkAnyBackend $
|
||||
SMOLogicalModel @b (_lmmRootFieldName lmm)
|
||||
)
|
||||
(toJSON lmm)
|
||||
)
|
||||
|
||||
logicalModelCacheMaybes <-
|
||||
interpretWriter
|
||||
-< for
|
||||
(OMap.elems logicalModels)
|
||||
\LogicalModelMetadata {..} -> runExceptT do
|
||||
fieldInfoMap <- case toFieldInfo _lmmReturns of
|
||||
Nothing -> pure mempty
|
||||
Just fields -> pure (mapFromL fieldInfoName fields)
|
||||
\lmm@LogicalModelMetadata {..} ->
|
||||
withRecordInconsistencyM (mkLogicalModelMetadataObject lmm) $ do
|
||||
unless areLogicalModelsEnabled $
|
||||
throw400 InvalidConfiguration "The Logical Models feature is disabled"
|
||||
|
||||
logicalModelPermissions <-
|
||||
buildLogicalModelPermissions sourceName tableCoreInfos _lmmRootFieldName fieldInfoMap _lmmSelectPermissions orderedRoles
|
||||
fieldInfoMap <- case toFieldInfo _lmmReturns of
|
||||
Nothing -> pure mempty
|
||||
Just fields -> pure (mapFromL fieldInfoName fields)
|
||||
|
||||
pure
|
||||
LogicalModelInfo
|
||||
{ _lmiRootFieldName = _lmmRootFieldName,
|
||||
_lmiCode = _lmmCode,
|
||||
_lmiReturns = _lmmReturns,
|
||||
_lmiArguments = _lmmArguments,
|
||||
_lmiPermissions = logicalModelPermissions,
|
||||
_lmiDescription = _lmmDescription
|
||||
}
|
||||
logicalModelPermissions <-
|
||||
buildLogicalModelPermissions sourceName tableCoreInfos _lmmRootFieldName fieldInfoMap _lmmSelectPermissions orderedRoles
|
||||
|
||||
pure
|
||||
LogicalModelInfo
|
||||
{ _lmiRootFieldName = _lmmRootFieldName,
|
||||
_lmiCode = _lmmCode,
|
||||
_lmiReturns = _lmmReturns,
|
||||
_lmiArguments = _lmmArguments,
|
||||
_lmiPermissions = logicalModelPermissions,
|
||||
_lmiDescription = _lmmDescription
|
||||
}
|
||||
|
||||
let logicalModelCache :: LogicalModelCache b
|
||||
logicalModelCache = mapFromL _lmiRootFieldName (mapMaybe eitherToMaybe logicalModelCacheMaybes)
|
||||
logicalModelCache = mapFromL _lmiRootFieldName (catMaybes logicalModelCacheMaybes)
|
||||
|
||||
returnA -< SourceInfo sourceName tableCache functionCache logicalModelCache sourceConfig queryTagsConfig resolvedCustomization
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user