Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions src/Cli.Tests/ValidateConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ public void TestCleanup()
Environment.SetEnvironmentVariable($"database-type", null);
Environment.SetEnvironmentVariable($"sp_param1_int", null);
Environment.SetEnvironmentVariable($"sp_param2_bool", null);

// Set output back to the default for other tests.
Console.SetOut(new StreamWriter(Console.OpenStandardOutput())
{
AutoFlush = true
});
Console.SetError(new StreamWriter(Console.OpenStandardError())
{
AutoFlush = true
});
}

/// <summary>
Expand Down Expand Up @@ -294,9 +304,6 @@ public void ValidateConfigSchemaWhereConfigReferencesEnvironmentVariables()
Assert.IsFalse(
condition: loggerOutput.Contains("Failed to validate config against schema due to"),
message: "Unexpected errors encountered when validating config schema in RuntimeConfigValidator::ValidateConfigSchema(...).");
Assert.IsTrue(
condition: loggerOutput.Contains("The config satisfies the schema requirements."),
message: "RuntimeConfigValidator::ValidateConfigSchema(...) didn't communicate successful config schema validation.");
}

/// <summary>
Expand Down Expand Up @@ -405,6 +412,37 @@ public void TestValidateNonRootZeroEntitiesWithInvalidConnectionString()
Assert.IsFalse(isValid);
}

/// <summary>
/// Tests that logs related to suppressed messages do not appear.
/// </summary>
[TestMethod]
public async Task TestValidateSuppressedLogsDoNotAppear()
{
// Arrange
StringWriter writer = new();
Console.SetOut(writer);
Comment thread
RubenCerna2079 marked this conversation as resolved.

string config = AddPropertiesToJson(INITIAL_CONFIG, SINGLE_ENTITY);

((MockFileSystem)_fileSystem!).AddFile(
path: TEST_RUNTIME_CONFIG_FILE,
mockFile: config);
ValidateOptions validateOptions = new(TEST_RUNTIME_CONFIG_FILE);

// Act
Utils.LoggerFactoryForCli = Utils.GetLoggerFactoryForCli();
ConfigGenerator.IsConfigValid(validateOptions, _runtimeConfigLoader!, _fileSystem!);

// Assert
string loggerOutput = writer.ToString();
Assert.IsTrue(
condition: !loggerOutput.Contains("REST path:"),
message: "RuntimeConfigValidator should not contain any messages indicating REST path for individual entities");
Assert.IsTrue(
condition: !loggerOutput.Contains("REST calls are disabled for the entity:"),
message: "RuntimeConfigValidator should not contain any messages related to REST calls for individual entities");
}

/// <summary>
/// Validates that a root config (with data-source-files pointing to children)
/// that has no data-source and no entities is considered structurally valid
Expand Down
2 changes: 1 addition & 1 deletion src/Cli/Commands/ValidateOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public int Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSy
}
else
{
logger.LogError("Config is invalid.");
logger.LogInformation("Config is invalid.");
Comment thread
RubenCerna2079 marked this conversation as resolved.
}

return isValidConfig ? CliReturnCode.SUCCESS : CliReturnCode.GENERAL_ERROR;
Expand Down
13 changes: 9 additions & 4 deletions src/Cli/ConfigGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3166,8 +3166,6 @@ public static bool IsConfigValid(ValidateOptions options, FileSystemRuntimeConfi
return false;
}

_logger.LogInformation("Validating config file: {runtimeConfigFile}", runtimeConfigFile);

RuntimeConfigProvider runtimeConfigProvider = new(loader);

if (!runtimeConfigProvider.TryGetConfig(out RuntimeConfig? _))
Expand Down Expand Up @@ -3196,14 +3194,21 @@ public static bool IsConfigValid(ValidateOptions options, FileSystemRuntimeConfi
bool mcpEnabled = config.IsMcpEnabled;
if (mcpEnabled)
{
bool missingFields = false;
foreach (KeyValuePair<string, Entity> entity in config.Entities)
{
if (entity.Value.Fields == null || !entity.Value.Fields.Any())
{
_logger.LogWarning($"Entity '{entity.Key}' is missing 'fields' definition while MCP is enabled. " +
"It's recommended to define fields explicitly to ensure optimal performance with MCP.");
missingFields = true;
_logger.LogDebug($"Entity '{entity.Key}' is missing 'fields' definition while MCP is enabled.");
}
}

if (missingFields)
{
_logger.LogWarning("One or more entities are missing `fields` definition while MCP is enabled. " +
"It's recommended to define fields explicitly to ensure optimal performance with MCP.");
}
}

// Warn if Unauthenticated provider is used with authenticated or custom roles
Expand Down
1 change: 0 additions & 1 deletion src/Core/Configurations/JsonConfigSchemaValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public JsonSchemaValidationResult ValidateJsonConfigWithSchema(string jsonSchema

if (isValid)
{
_logger!.LogInformation("The config satisfies the schema requirements.");
return new(isValid: true, errors: null);
}
else
Expand Down
1 change: 0 additions & 1 deletion src/Core/Configurations/RuntimeConfigValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ public async Task<bool> TryValidateConfig(
ValidateConfigProperties();
ValidatePermissionsInConfig(runtimeConfig);

_logger.LogInformation("Validating entity relationships.");
ValidateRelationshipConfigCorrectness(runtimeConfig);

// This function initializes the metadata providers which in turn validates the connectivity to the
Expand Down
20 changes: 9 additions & 11 deletions src/Core/Services/MetadataProviders/MsSqlMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,19 @@ public override async Task PopulateTriggerMetadataForTable(string entityName, st
if ("UPDATE".Equals(type_desc))
{
sourceDefinition.IsUpdateDMLTriggerEnabled = true;
_logger.LogInformation($"An update trigger is enabled for the entity: {entityName}");
if (!_isValidateOnly)
{
_logger.LogInformation($"An update trigger is enabled for the entity: {entityName}");
}
}

if ("INSERT".Equals(type_desc))
{
sourceDefinition.IsInsertDMLTriggerEnabled = true;
_logger.LogInformation($"An insert trigger is enabled for the entity: {entityName}");
if (!_isValidateOnly)
{
_logger.LogInformation($"An insert trigger is enabled for the entity: {entityName}");
}
}
}
}
Expand Down Expand Up @@ -362,15 +368,6 @@ protected override async Task GenerateAutoentitiesIntoEntities(IReadOnlyDictiona
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization);
}

if (runtimeConfig.IsRestEnabled)
{
_logger.LogInformation("[{entity}] REST path: {globalRestPath}/{entityRestPath}", entityName, runtimeConfig.RestPath, entityName);
}
else
{
_logger.LogInformation(message: "REST calls are disabled for the entity: {entity}", entityName);
}

addedEntities++;
}

Expand All @@ -383,6 +380,7 @@ protected override async Task GenerateAutoentitiesIntoEntities(IReadOnlyDictiona
runtimeConfig.AutoentityResolutionCounts[autoentityName] = addedEntities;
}

LogRestPathsForEntities(runtimeConfig, entities);
_runtimeConfigProvider.AddMergedEntitiesToConfig(entities);
}

Expand Down
37 changes: 25 additions & 12 deletions src/Core/Services/MetadataProviders/SqlMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,7 @@ public SqlMetadataProvider(
_databaseType = runtimeConfig.GetDataSourceFromDataSourceName(dataSourceName).DatabaseType;
_logger = logger;
_isValidateOnly = isValidateOnly;
foreach ((string entityName, Entity entityMetatdata) in Entities)
{
if (runtimeConfig.IsRestEnabled)
{
string restPath = entityMetatdata.Rest?.Path ?? entityName;
_logger.LogInformation("[{entity}] REST path: {globalRestPath}/{entityRestPath}", entityName, runtimeConfig.RestPath, restPath);
}
else
{
_logger.LogInformation(message: "REST calls are disabled for the entity: {entity}", entityName);
}
}
LogRestPathsForEntities(runtimeConfig, Entities);

ConnectionString = runtimeConfig.GetDataSourceFromDataSourceName(dataSourceName).ConnectionString;
EntitiesDataSet = new();
Expand Down Expand Up @@ -1019,6 +1008,30 @@ protected virtual void PopulateMetadataForLinkingObject(
return;
}

/// <summary>
/// Helper method that logs the REST paths for all entities and shows if the REST calls are enabled/disabled for any entity.
/// </summary>
/// <param name="runtimeConfig"></param>
/// <param name="entities"></param>
protected void LogRestPathsForEntities(RuntimeConfig runtimeConfig, IReadOnlyDictionary<string, Entity> entities)
{
if (!_isValidateOnly)
Comment thread
RubenCerna2079 marked this conversation as resolved.
{
foreach ((string entityName, Entity entityMetatdata) in entities)
{
if (runtimeConfig.IsRestEnabled)
{
string restPath = entityMetatdata.Rest?.Path ?? entityName;
_logger.LogInformation("[{entity}] REST path: {globalRestPath}/{entityRestPath}", entityName, runtimeConfig.RestPath, restPath);
}
else
{
_logger.LogInformation(message: "REST calls are disabled for the entity: {entity}", entityName);
}
}
}
}

/// <summary>
/// Adds a new foreign key definition for the target entity in the relationship metadata.
/// The last argument "relationshipData" is modified (hydrated with the new foreign key definition)
Expand Down
26 changes: 0 additions & 26 deletions src/Service.Tests/Configuration/ConfigurationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,6 @@ public async Task TestSqlMetadataValidationForEntitiesWithInvalidSource()
/// <summary>
/// This test method validates a sample DAB runtime config file against DAB's JSON schema definition.
/// It asserts that the validation is successful and there are no validation failures.
/// It also verifies that the expected log message is logged.
/// </summary>
[TestMethod("Validates the config file schema."), TestCategory(TestCategory.MSSQL)]
public void TestConfigSchemaIsValid()
Expand All @@ -1874,20 +1873,11 @@ public void TestConfigSchemaIsValid()
JsonSchemaValidationResult result = jsonSchemaValidator.ValidateJsonConfigWithSchema(jsonSchema, jsonData);
Assert.IsTrue(result.IsValid);
Assert.IsTrue(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors));
schemaValidatorLogger.Verify(
x => x.Log(
LogLevel.Information,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((o, t) => o.ToString()!.Contains($"The config satisfies the schema requirements.")),
It.IsAny<Exception>(),
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
Times.Once);
}

/// <summary>
/// This test method validates a sample DAB runtime config file against DAB's JSON schema definition.
/// It asserts that the validation is successful and there are no validation failures when no optional fields are used.
/// It also verifies that the expected log message is logged.
/// </summary>
[DataTestMethod]
[DataRow(CONFIG_FILE_WITH_NO_OPTIONAL_FIELD, DisplayName = "Validates schema of the config file with no optional fields.")]
Expand All @@ -1906,14 +1896,6 @@ public void TestBasicConfigSchemaWithNoOptionalFieldsIsValid(string jsonData)
Assert.IsTrue(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors));

Assert.IsTrue(result.IsValid);
schemaValidatorLogger.Verify(
x => x.Log(
LogLevel.Information,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((o, t) => o.ToString()!.Contains($"The config satisfies the schema requirements.")),
It.IsAny<Exception>(),
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
Times.Once);
}

[DataTestMethod]
Expand All @@ -1940,14 +1922,6 @@ public void TestBasicConfigSchemaWithFlexibleBoolean(string Value)
Assert.IsTrue(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors), "Validation Erros null of empty");

Assert.IsTrue(result.IsValid, "Result should be valid");
schemaValidatorLogger.Verify(
x => x.Log(
LogLevel.Information,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((o, t) => o.ToString()!.Contains($"The config satisfies the schema requirements.")),
It.IsAny<Exception>(),
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
Times.Once);
}

/// <summary>
Expand Down