-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
402a932
commit af69fc4
Showing
9 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
129 changes: 129 additions & 0 deletions
129
src/Microsoft.ComponentDetection.Common/ComponentDetectionConfigFileService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
namespace Microsoft.ComponentDetection.Common; | ||
|
||
using System; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using Microsoft.ComponentDetection.Contracts; | ||
using Microsoft.Extensions.Logging; | ||
using YamlDotNet.Serialization; | ||
|
||
/// <inheritdoc /> | ||
public class ComponentDetectionConfigFileService : IComponentDetectionConfigFileService | ||
{ | ||
private const string ComponentDetectionConfigFileEnvVar = "ComponentDetection.ComponentDetectionConfigFile"; | ||
private readonly IFileUtilityService fileUtilityService; | ||
private readonly IEnvironmentVariableService environmentVariableService; | ||
private readonly IPathUtilityService pathUtilityService; | ||
private readonly ComponentDetectionConfigFile componentDetectionConfig; | ||
private readonly ILogger<FastDirectoryWalkerFactory> logger; | ||
private bool serviceInitComplete; | ||
|
||
public ComponentDetectionConfigFileService( | ||
IFileUtilityService fileUtilityService, | ||
IEnvironmentVariableService environmentVariableService, | ||
IPathUtilityService pathUtilityService, | ||
ILogger<FastDirectoryWalkerFactory> logger) | ||
{ | ||
this.fileUtilityService = fileUtilityService; | ||
this.pathUtilityService = pathUtilityService; | ||
this.environmentVariableService = environmentVariableService; | ||
this.logger = logger; | ||
this.componentDetectionConfig = new ComponentDetectionConfigFile(); | ||
this.serviceInitComplete = false; | ||
} | ||
|
||
public ComponentDetectionConfigFile GetComponentDetectionConfig() | ||
{ | ||
this.EnsureInit(); | ||
return this.componentDetectionConfig; | ||
} | ||
|
||
public async Task InitAsync(string explicitConfigPath, string rootDirectoryPath = null) | ||
{ | ||
await this.LoadFromEnvironmentVariableAsync(); | ||
if (!string.IsNullOrEmpty(explicitConfigPath)) | ||
{ | ||
await this.LoadComponentDetectionConfigAsync(explicitConfigPath); | ||
} | ||
|
||
if (!string.IsNullOrEmpty(rootDirectoryPath)) | ||
{ | ||
await this.LoadComponentDetectionConfigFilesFromRootDirectoryAsync(rootDirectoryPath); | ||
} | ||
|
||
this.serviceInitComplete = true; | ||
} | ||
|
||
private async Task LoadComponentDetectionConfigFilesFromRootDirectoryAsync(string rootDirectoryPath) | ||
{ | ||
var workingDir = this.pathUtilityService.NormalizePath(rootDirectoryPath); | ||
|
||
var reportFile = new FileInfo(Path.Combine(workingDir, "ComponentDetection.yml")); | ||
if (this.fileUtilityService.Exists(reportFile.FullName)) | ||
{ | ||
await this.LoadComponentDetectionConfigAsync(reportFile.FullName); | ||
} | ||
} | ||
|
||
private async Task LoadFromEnvironmentVariableAsync() | ||
{ | ||
if (this.environmentVariableService.DoesEnvironmentVariableExist(ComponentDetectionConfigFileEnvVar)) | ||
{ | ||
var possibleConfigFilePath = this.environmentVariableService.GetEnvironmentVariable(ComponentDetectionConfigFileEnvVar); | ||
if (this.fileUtilityService.Exists(possibleConfigFilePath)) | ||
{ | ||
await this.LoadComponentDetectionConfigAsync(possibleConfigFilePath); | ||
} | ||
} | ||
} | ||
|
||
private async Task LoadComponentDetectionConfigAsync(string configFile) | ||
{ | ||
if (!this.fileUtilityService.Exists(configFile)) | ||
{ | ||
throw new InvalidOperationException($"Attempted to load non-existant ComponentDetectionConfig file: {configFile}"); | ||
} | ||
|
||
var configFileInfo = new FileInfo(configFile); | ||
var fileContents = await this.fileUtilityService.ReadAllTextAsync(configFileInfo); | ||
var newConfig = this.ParseComponentDetectionConfig(fileContents); | ||
this.MergeComponentDetectionConfig(newConfig); | ||
this.logger.LogInformation("Loaded component detection config file from {ConfigFile}", configFile); | ||
} | ||
|
||
/// <summary> | ||
/// Merges two component detection configs, giving precedence to values already set in the first file. | ||
/// </summary> | ||
/// <param name="newConfig">The new config file to be merged into the existing config set.</param> | ||
private void MergeComponentDetectionConfig(ComponentDetectionConfigFile newConfig) | ||
{ | ||
foreach ((var name, var value) in newConfig.Variables) | ||
{ | ||
if (!this.componentDetectionConfig.Variables.ContainsKey(name)) | ||
{ | ||
this.componentDetectionConfig.Variables[name] = value; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Reads the component detection config from a file path. | ||
/// </summary> | ||
/// <param name="configFileContent">The string contents of the config yaml file.</param> | ||
/// <returns>The ComponentDetection config file as an object.</returns> | ||
private ComponentDetectionConfigFile ParseComponentDetectionConfig(string configFileContent) | ||
{ | ||
var deserializer = new DeserializerBuilder() | ||
.IgnoreUnmatchedProperties() | ||
.Build(); | ||
return deserializer.Deserialize<ComponentDetectionConfigFile>(new StringReader(configFileContent)); | ||
} | ||
|
||
private void EnsureInit() | ||
{ | ||
if (!this.serviceInitComplete) | ||
{ | ||
throw new InvalidOperationException("ComponentDetection config files have not been loaded yet!"); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/Microsoft.ComponentDetection.Common/IComponentDetectionConfigFileService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
namespace Microsoft.ComponentDetection.Common; | ||
|
||
using System.Threading.Tasks; | ||
using Microsoft.ComponentDetection.Contracts; | ||
|
||
/// <summary> | ||
/// Provides methods for writing files. | ||
/// </summary> | ||
public interface IComponentDetectionConfigFileService | ||
{ | ||
/// <summary> | ||
/// Initializes the Component detection config service. | ||
/// Checks the following for the presence of a config file: | ||
/// 1. The environment variable "ComponentDetection.ConfigFilePath" and the path exists | ||
/// 2. If there is a file present at the root directory named "ComponentDetection.yml". | ||
/// </summary> | ||
/// <returns>A task that represents the asynchronous operation.</returns> | ||
Task InitAsync(string explicitConfigPath, string rootDirectoryPath = null); | ||
|
||
/// <summary> | ||
/// Retrieves the merged config files. | ||
/// </summary> | ||
/// <returns>The ComponentDetection config file as an object.</returns> | ||
ComponentDetectionConfigFile GetComponentDetectionConfig(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/Microsoft.ComponentDetection.Contracts/ComponentDetectionConfigFile.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace Microsoft.ComponentDetection.Contracts; | ||
|
||
using System.Collections.Generic; | ||
using YamlDotNet.Serialization; | ||
|
||
/// <summary> | ||
/// Represents the ComponentDetection.yml config file. | ||
/// </summary> | ||
public class ComponentDetectionConfigFile | ||
{ | ||
/// <summary> | ||
/// Gets or sets a value indicating whether the detection should be stopped. | ||
/// </summary> | ||
[YamlMember(Alias = "variables")] | ||
public Dictionary<string, string> Variables { get; set; } = []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters