diff --git a/Directory.Packages.props b/Directory.Packages.props index 49496d5fa..08c640aff 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,8 +10,6 @@ 6.3.0 - - diff --git a/src/Microsoft.Sbom.Api/Config/ConfigPostProcessor.cs b/src/Microsoft.Sbom.Api/Config/ConfigPostProcessor.cs index 9b085b52f..bb8a8b416 100644 --- a/src/Microsoft.Sbom.Api/Config/ConfigPostProcessor.cs +++ b/src/Microsoft.Sbom.Api/Config/ConfigPostProcessor.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using AutoMapper; using Microsoft.Sbom.Api.Output.Telemetry; using Microsoft.Sbom.Common; using Microsoft.Sbom.Common.Config; @@ -17,7 +16,7 @@ namespace Microsoft.Sbom.Api.Config; /// /// Runs finalizing operations on the configuration once it has been successfully parsed. /// -public class ConfigPostProcessor : IMappingAction +public class ConfigPostProcessor { private readonly IEnumerable configValidators; private readonly ConfigSanitizer configSanitizer; @@ -30,7 +29,7 @@ public ConfigPostProcessor(IEnumerable configValidators, Config this.fileSystemUtils = fileSystemUtils ?? throw new ArgumentNullException(nameof(fileSystemUtils)); } - public void Process(IConfiguration source, IConfiguration destination, ResolutionContext context) + public void Process(IConfiguration source, IConfiguration destination) { // Replace backslashes in directory paths with the OS-sepcific directory separator character. PathUtils.ConvertToOSSpecificPathSeparators(destination); diff --git a/src/Microsoft.Sbom.Api/Config/ConfigurationBuilder.cs b/src/Microsoft.Sbom.Api/Config/ConfigurationBuilder.cs index 6b95596f1..2a37a3e25 100644 --- a/src/Microsoft.Sbom.Api/Config/ConfigurationBuilder.cs +++ b/src/Microsoft.Sbom.Api/Config/ConfigurationBuilder.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Threading.Tasks; -using AutoMapper; using Microsoft.Sbom.Api.Config.Args; using Microsoft.Sbom.Common.Config; using PowerArgs; @@ -13,12 +12,12 @@ namespace Microsoft.Sbom.Api.Config; /// Throws an error if the same parameters are defined in both the config file and command line. public class ConfigurationBuilder : IConfigurationBuilder { - private readonly IMapper mapper; + private readonly ConfigPostProcessor configPostProcessor; private readonly ConfigFileParser configFileParser; - public ConfigurationBuilder(IMapper mapper, ConfigFileParser configFileParser) + public ConfigurationBuilder(ConfigPostProcessor configPostProcessor, ConfigFileParser configFileParser) { - this.mapper = mapper; + this.configPostProcessor = configPostProcessor; this.configFileParser = configFileParser; } @@ -31,23 +30,23 @@ public async Task GetConfiguration(T args) { case ValidationArgs validationArgs: validationArgs.ManifestToolAction = ManifestToolActions.Validate; - commandLineArgs = mapper.Map(validationArgs); + commandLineArgs = ConfigurationMapper.MapFrom(validationArgs); break; case GenerationArgs generationArgs: generationArgs.ManifestToolAction = ManifestToolActions.Generate; - commandLineArgs = mapper.Map(generationArgs); + commandLineArgs = ConfigurationMapper.MapFrom(generationArgs); break; case RedactArgs redactArgs: redactArgs.ManifestToolAction = ManifestToolActions.Redact; - commandLineArgs = mapper.Map(redactArgs); + commandLineArgs = ConfigurationMapper.MapFrom(redactArgs); break; case FormatValidationArgs formatValidationArgs: formatValidationArgs.ManifestToolAction = ManifestToolActions.ValidateFormat; - commandLineArgs = mapper.Map(formatValidationArgs); + commandLineArgs = ConfigurationMapper.MapFrom(formatValidationArgs); break; case AggregationArgs aggregationArgs: aggregationArgs.ManifestToolAction = ManifestToolActions.Aggregate; - commandLineArgs = mapper.Map(aggregationArgs); + commandLineArgs = ConfigurationMapper.MapFrom(aggregationArgs); break; default: throw new ValidationArgException($"Unsupported configuration type found {typeof(T)}"); @@ -59,10 +58,10 @@ await configFileParser.ParseFromJsonFile(commandLineArgs.ConfigFilePath.Value) : new ConfigFile(); // Convert config file arguments to configuration. - var configFileArgs = mapper.Map(configFromFile); + var configFileArgs = ConfigurationMapper.MapFrom(configFromFile); // Combine both configs, include defaults. - return mapper.Map(commandLineArgs, configFileArgs); + return ConfigurationMapper.Merge(commandLineArgs, configFileArgs, configPostProcessor); } } diff --git a/src/Microsoft.Sbom.Api/Config/ConfigurationMapper.cs b/src/Microsoft.Sbom.Api/Config/ConfigurationMapper.cs new file mode 100644 index 000000000..63f1c51a5 --- /dev/null +++ b/src/Microsoft.Sbom.Api/Config/ConfigurationMapper.cs @@ -0,0 +1,412 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.Sbom.Api.Config.Args; +using Microsoft.Sbom.Common.Config; +using Microsoft.Sbom.Contracts.Enums; +using Microsoft.Sbom.Extensions.Entities; +using PowerArgs; +using Serilog.Events; +using Constants = Microsoft.Sbom.Common.Constants; + +namespace Microsoft.Sbom.Api.Config; + +/// +/// Provides explicit property-by-property mapping methods to convert CLI argument objects +/// and config file objects into instances. +/// +public static class ConfigurationMapper +{ + public static InputConfiguration MapFrom(GenerationArgs args) + { + var s = SettingSource.CommandLine; + var dest = new InputConfiguration(); + MapCommonArgs(args, dest, s); + MapGenValAggCommonArgs(args, dest, s); + MapGenValCommonArgs(args, dest, s); + + dest.BuildDropPath = WrapString(args.BuildDropPath, s); + dest.BuildComponentPath = WrapString(args.BuildComponentPath, s); + dest.BuildListFile = WrapString(args.BuildListFile, s); + dest.ManifestDirPath = WrapString(args.ManifestDirPath, s); + dest.PackageName = WrapString(args.PackageName, s); + dest.PackageVersion = WrapString(args.PackageVersion, s); + dest.PackageSupplier = WrapString(args.PackageSupplier, s); + dest.DockerImagesToScan = WrapString(args.DockerImagesToScan, s); + dest.AdditionalComponentDetectorArgs = WrapString(args.AdditionalComponentDetectorArgs, s); + dest.ExternalDocumentReferenceListFile = WrapString(args.ExternalDocumentReferenceListFile, s); + dest.NamespaceUriUniquePart = WrapString(args.NamespaceUriUniquePart, s); + dest.NamespaceUriBase = WrapString(args.NamespaceUriBase, s); + dest.GenerationTimestamp = WrapString(args.GenerationTimestamp, s); + dest.DeleteManifestDirIfPresent = WrapNullableBool(args.DeleteManifestDirIfPresent, s); + dest.FetchLicenseInformation = WrapNullableBool(args.FetchLicenseInformation, s); + dest.LicenseInformationTimeoutInSeconds = WrapNullableInt(args.LicenseInformationTimeoutInSeconds, s); + dest.EnablePackageMetadataParsing = WrapNullableBool(args.EnablePackageMetadataParsing, s); + + return dest; + } + + public static InputConfiguration MapFrom(ValidationArgs args) + { + var s = SettingSource.CommandLine; + var dest = new InputConfiguration(); + MapCommonArgs(args, dest, s); + MapGenValAggCommonArgs(args, dest, s); + MapGenValCommonArgs(args, dest, s); + + dest.BuildDropPath = WrapString(args.BuildDropPath, s); + dest.ManifestDirPath = WrapString(args.ManifestDirPath, s); + dest.OutputPath = WrapString(args.OutputPath, s); + dest.ValidateSignature = WrapBool(args.ValidateSignature, s); + dest.IgnoreMissing = WrapBool(args.IgnoreMissing, s); + dest.FailIfNoPackages = WrapBool(args.FailIfNoPackages, s); + dest.RootPathFilter = WrapString(args.RootPathFilter, s); + dest.HashAlgorithm = WrapAlgorithmName(args.HashAlgorithm, s); + dest.Conformance = WrapConformance(args.Conformance, s); + +#pragma warning disable CS0612 // Type or member is obsolete + dest.CatalogFilePath = WrapString(args.CatalogFilePath, s); +#pragma warning restore CS0612 + + return dest; + } + + public static InputConfiguration MapFrom(RedactArgs args) + { + var s = SettingSource.CommandLine; + var dest = new InputConfiguration(); + MapCommonArgs(args, dest, s); + + dest.SbomPath = WrapString(args.SbomPath, s); + dest.SbomDir = WrapString(args.SbomDir, s); + dest.OutputPath = WrapString(args.OutputPath, s); + + return dest; + } + + public static InputConfiguration MapFrom(FormatValidationArgs args) + { + var s = SettingSource.CommandLine; + var dest = new InputConfiguration(); + MapCommonArgs(args, dest, s); + + dest.SbomPath = WrapString(args.SbomPath, s); + + return dest; + } + + public static InputConfiguration MapFrom(AggregationArgs args) + { + var s = SettingSource.CommandLine; + var dest = new InputConfiguration(); + MapCommonArgs(args, dest, s); + MapGenValAggCommonArgs(args, dest, s); + + return dest; + } + + public static InputConfiguration MapFrom(ConfigFile config) + { + var s = SettingSource.JsonConfig; + +#pragma warning disable IDE0017 // Simplify object initialization + var dest = new InputConfiguration(); + + dest.BuildDropPath = WrapString(config.BuildDropPath, s); + dest.BuildComponentPath = WrapString(config.BuildComponentPath, s); + dest.BuildListFile = WrapString(config.BuildListFile, s); + dest.ManifestDirPath = WrapString(config.ManifestDirPath, s); + dest.OutputPath = WrapString(config.OutputPath, s); + dest.CatalogFilePath = WrapString(config.CatalogFilePath, s); + dest.ValidateSignature = WrapNullableBool(config.ValidateSignature, s); + dest.IgnoreMissing = WrapNullableBool(config.IgnoreMissing, s); + dest.RootPathFilter = WrapString(config.RootPathFilter, s); + dest.Verbosity = WrapLogEventLevel(config.Verbosity, s); + dest.Parallelism = WrapNullableInt(config.Parallelism, s); + dest.ManifestInfo = WrapManifestInfo(config.ManifestInfo, s); + dest.HashAlgorithm = WrapAlgorithmName(config.HashAlgorithm, s); + dest.PackageName = WrapString(config.PackageName, s); + dest.PackageVersion = WrapString(config.PackageVersion, s); + dest.PackageSupplier = WrapString(config.PackageSupplier, s); + dest.ConfigFilePath = WrapString(config.ConfigFilePath, s); + dest.ManifestToolAction = config.ManifestToolAction; + dest.TelemetryFilePath = WrapString(config.TelemetryFilePath, s); + dest.DockerImagesToScan = WrapString(config.DockerImagesToScan, s); + dest.ExternalDocumentReferenceListFile = WrapString(config.ExternalDocumentReferenceListFile, s); + dest.AdditionalComponentDetectorArgs = WrapString(config.AdditionalComponentDetectorArgs, s); + dest.NamespaceUriUniquePart = WrapString(config.NamespaceUriUniquePart, s); + dest.NamespaceUriBase = WrapString(config.NamespaceUriBase, s); + dest.GenerationTimestamp = WrapString(config.GenerationTimestamp, s); + dest.FollowSymlinks = WrapNullableBool(config.FollowSymlinks, s); + dest.DeleteManifestDirIfPresent = WrapNullableBool(config.DeleteManifestDirIfPresent, s); + dest.FailIfNoPackages = WrapNullableBool(config.FailIfNoPackages, s); + dest.FetchLicenseInformation = WrapNullableBool(config.FetchLicenseInformation, s); + dest.EnablePackageMetadataParsing = WrapNullableBool(config.EnablePackageMetadataParsing, s); + dest.Conformance = WrapConformance(config.Conformance, s); + dest.ArtifactInfoMap = WrapArtifactInfoMap(config.ArtifactInfoMap, s); + +#pragma warning disable CS0618 // Type or member is obsolete + dest.ManifestPath = WrapString(config.ManifestPath, s); +#pragma warning restore CS0618 +#pragma warning restore IDE0017 + + return dest; + } + + /// + /// Merges command-line configuration into config-file configuration. + /// If the same setting is specified in both with non-default sources, throws. + /// Then runs post-processing (validation, sanitization, defaults). + /// + public static InputConfiguration Merge(InputConfiguration commandLine, InputConfiguration configFile, ConfigPostProcessor postProcessor) + { + configFile.BuildDropPath = MergeSetting(commandLine.BuildDropPath, configFile.BuildDropPath); + configFile.BuildComponentPath = MergeSetting(commandLine.BuildComponentPath, configFile.BuildComponentPath); + configFile.BuildListFile = MergeSetting(commandLine.BuildListFile, configFile.BuildListFile); + configFile.ManifestDirPath = MergeSetting(commandLine.ManifestDirPath, configFile.ManifestDirPath); + configFile.OutputPath = MergeSetting(commandLine.OutputPath, configFile.OutputPath); + configFile.Parallelism = MergeSetting(commandLine.Parallelism, configFile.Parallelism); + configFile.Verbosity = MergeSetting(commandLine.Verbosity, configFile.Verbosity); + configFile.ConfigFilePath = MergeSetting(commandLine.ConfigFilePath, configFile.ConfigFilePath); + configFile.ManifestInfo = MergeSetting(commandLine.ManifestInfo, configFile.ManifestInfo); + configFile.HashAlgorithm = MergeSetting(commandLine.HashAlgorithm, configFile.HashAlgorithm); + configFile.RootPathFilter = MergeSetting(commandLine.RootPathFilter, configFile.RootPathFilter); + configFile.CatalogFilePath = MergeSetting(commandLine.CatalogFilePath, configFile.CatalogFilePath); + configFile.ValidateSignature = MergeSetting(commandLine.ValidateSignature, configFile.ValidateSignature); + configFile.IgnoreMissing = MergeSetting(commandLine.IgnoreMissing, configFile.IgnoreMissing); + configFile.PackageName = MergeSetting(commandLine.PackageName, configFile.PackageName); + configFile.PackageVersion = MergeSetting(commandLine.PackageVersion, configFile.PackageVersion); + configFile.PackageSupplier = MergeSetting(commandLine.PackageSupplier, configFile.PackageSupplier); + configFile.FilesList = MergeSetting(commandLine.FilesList, configFile.FilesList); + configFile.PackagesList = MergeSetting(commandLine.PackagesList, configFile.PackagesList); + configFile.TelemetryFilePath = MergeSetting(commandLine.TelemetryFilePath, configFile.TelemetryFilePath); + configFile.DockerImagesToScan = MergeSetting(commandLine.DockerImagesToScan, configFile.DockerImagesToScan); + configFile.ExternalDocumentReferenceListFile = MergeSetting(commandLine.ExternalDocumentReferenceListFile, configFile.ExternalDocumentReferenceListFile); + configFile.AdditionalComponentDetectorArgs = MergeSetting(commandLine.AdditionalComponentDetectorArgs, configFile.AdditionalComponentDetectorArgs); + configFile.NamespaceUriUniquePart = MergeSetting(commandLine.NamespaceUriUniquePart, configFile.NamespaceUriUniquePart); + configFile.NamespaceUriBase = MergeSetting(commandLine.NamespaceUriBase, configFile.NamespaceUriBase); + configFile.GenerationTimestamp = MergeSetting(commandLine.GenerationTimestamp, configFile.GenerationTimestamp); + configFile.FollowSymlinks = MergeSetting(commandLine.FollowSymlinks, configFile.FollowSymlinks); + configFile.DeleteManifestDirIfPresent = MergeSetting(commandLine.DeleteManifestDirIfPresent, configFile.DeleteManifestDirIfPresent); + configFile.FailIfNoPackages = MergeSetting(commandLine.FailIfNoPackages, configFile.FailIfNoPackages); + configFile.FetchLicenseInformation = MergeSetting(commandLine.FetchLicenseInformation, configFile.FetchLicenseInformation); + configFile.LicenseInformationTimeoutInSeconds = MergeSetting(commandLine.LicenseInformationTimeoutInSeconds, configFile.LicenseInformationTimeoutInSeconds); + configFile.EnablePackageMetadataParsing = MergeSetting(commandLine.EnablePackageMetadataParsing, configFile.EnablePackageMetadataParsing); + configFile.SbomPath = MergeSetting(commandLine.SbomPath, configFile.SbomPath); + configFile.SbomDir = MergeSetting(commandLine.SbomDir, configFile.SbomDir); + configFile.Conformance = MergeSetting(commandLine.Conformance, configFile.Conformance); + configFile.ArtifactInfoMap = MergeSetting(commandLine.ArtifactInfoMap, configFile.ArtifactInfoMap); + + // ManifestToolAction is not a ConfigurationSetting — take command-line value if set. + if (commandLine.ManifestToolAction != default) + { + configFile.ManifestToolAction = commandLine.ManifestToolAction; + } + +#pragma warning disable CS0618 // Type or member is obsolete + configFile.ManifestPath = MergeSetting(commandLine.ManifestPath, configFile.ManifestPath); +#pragma warning restore CS0618 + + postProcessor.Process(commandLine, configFile); + return configFile; + } + + /// + /// Converts a validated to a thread-safe . + /// + public static Configuration ToConfiguration(InputConfiguration src) + { +#pragma warning disable IDE0017 // Simplify object initialization + var dest = new Configuration(); + + dest.BuildDropPath = src.BuildDropPath; + dest.BuildComponentPath = src.BuildComponentPath; + dest.BuildListFile = src.BuildListFile; + dest.ManifestDirPath = src.ManifestDirPath; + dest.OutputPath = src.OutputPath; + dest.Parallelism = src.Parallelism; + dest.Verbosity = src.Verbosity; + dest.ConfigFilePath = src.ConfigFilePath; + dest.ManifestInfo = src.ManifestInfo; + dest.HashAlgorithm = src.HashAlgorithm; + dest.RootPathFilter = src.RootPathFilter; + dest.CatalogFilePath = src.CatalogFilePath; + dest.ValidateSignature = src.ValidateSignature; + dest.IgnoreMissing = src.IgnoreMissing; + dest.ManifestToolAction = src.ManifestToolAction; + dest.PackageName = src.PackageName; + dest.PackageVersion = src.PackageVersion; + dest.PackageSupplier = src.PackageSupplier; + dest.FilesList = src.FilesList; + dest.PackagesList = src.PackagesList; + dest.TelemetryFilePath = src.TelemetryFilePath; + dest.DockerImagesToScan = src.DockerImagesToScan; + dest.ExternalDocumentReferenceListFile = src.ExternalDocumentReferenceListFile; + dest.AdditionalComponentDetectorArgs = src.AdditionalComponentDetectorArgs; + dest.NamespaceUriUniquePart = src.NamespaceUriUniquePart; + dest.NamespaceUriBase = src.NamespaceUriBase; + dest.GenerationTimestamp = src.GenerationTimestamp; + dest.FollowSymlinks = src.FollowSymlinks; + dest.DeleteManifestDirIfPresent = src.DeleteManifestDirIfPresent; + dest.FailIfNoPackages = src.FailIfNoPackages; + dest.FetchLicenseInformation = src.FetchLicenseInformation; + dest.LicenseInformationTimeoutInSeconds = src.LicenseInformationTimeoutInSeconds; + dest.EnablePackageMetadataParsing = src.EnablePackageMetadataParsing; + dest.SbomPath = src.SbomPath; + dest.SbomDir = src.SbomDir; + dest.Conformance = src.Conformance; + dest.ArtifactInfoMap = src.ArtifactInfoMap; + +#pragma warning disable CS0618 // Type or member is obsolete + dest.ManifestPath = src.ManifestPath; +#pragma warning restore CS0618 +#pragma warning restore IDE0017 + + return dest; + } + + // ── Base class mapping helpers ─────────────────────────────────────── + + private static void MapCommonArgs(CommonArgs args, InputConfiguration dest, SettingSource s) + { + dest.ManifestToolAction = args.ManifestToolAction; + dest.Verbosity = WrapLogEventLevel(args.Verbosity, s); + } + + private static void MapGenValAggCommonArgs(GenerationAndValidationAndAggregationCommonArgs args, InputConfiguration dest, SettingSource s) + { + dest.ConfigFilePath = WrapString(args.ConfigFilePath, s); + dest.TelemetryFilePath = WrapString(args.TelemetryFilePath, s); + } + + private static void MapGenValCommonArgs(GenerationAndValidationCommonArgs args, InputConfiguration dest, SettingSource s) + { + dest.Parallelism = WrapNullableInt(args.Parallelism, s); + dest.FollowSymlinks = WrapNullableBool(args.FollowSymlinks, s); + dest.ManifestInfo = WrapManifestInfo(args.ManifestInfo, s); + } + + // ── Merge helper ──────────────────────────────────────────────────── + + private static ConfigurationSetting MergeSetting(ConfigurationSetting src, ConfigurationSetting dst) + { + if (src != null && dst != null) + { + if (src.Source != SettingSource.Default && dst.Source != SettingSource.Default) + { + throw new ValidationArgException("Duplicate keys found in config file and command line parameters."); + } + + return dst.Source == SettingSource.Default ? src : dst; + } + + return src ?? dst; + } + + // ── Value wrapping helpers ────────────────────────────────────────── + + private static ConfigurationSetting WrapString(string value, SettingSource source) + { + if (string.IsNullOrEmpty(value)) + { + return null; + } + + return new ConfigurationSetting { Source = source, Value = value }; + } + + private static ConfigurationSetting WrapBool(bool value, SettingSource source) => + new ConfigurationSetting { Source = source, Value = value }; + + private static ConfigurationSetting WrapNullableBool(bool? value, SettingSource source) + { + if (value == null) + { + return null; + } + + return new ConfigurationSetting { Source = source, Value = value.Value }; + } + + private static ConfigurationSetting WrapNullableInt(int? value, SettingSource source) + { + if (value == null) + { + return null; + } + + return new ConfigurationSetting { Source = source, Value = value.Value }; + } + + private static ConfigurationSetting WrapLogEventLevel(LogEventLevel? value, SettingSource source) + { + if (value == null) + { + source = SettingSource.Default; + } + + return new ConfigurationSetting + { + Source = source, + Value = value ?? Constants.DefaultLogLevel + }; + } + + private static ConfigurationSetting> WrapManifestInfo(IList value, SettingSource source) + { + if (value == null) + { + source = SettingSource.Default; + } + + return new ConfigurationSetting> + { + Source = source, + Value = value + }; + } + + private static ConfigurationSetting WrapAlgorithmName(AlgorithmName value, SettingSource source) + { + if (value == null) + { + source = SettingSource.Default; + } + + return new ConfigurationSetting + { + Source = source, + Value = value ?? Api.Utils.Constants.DefaultHashAlgorithmName + }; + } + + private static ConfigurationSetting WrapConformance(ConformanceType value, SettingSource source) + { + if (value == null) + { + source = SettingSource.Default; + } + + return new ConfigurationSetting + { + Source = source, + Value = value ?? ConformanceType.None + }; + } + + private static ConfigurationSetting> WrapArtifactInfoMap(Dictionary value, SettingSource source) + { + if (value == null || !value.Any()) + { + return null; + } + + return new ConfigurationSetting> + { + Source = source, + Value = value + }; + } +} diff --git a/src/Microsoft.Sbom.Api/Config/Extensions/ConfigurationExtensions.cs b/src/Microsoft.Sbom.Api/Config/Extensions/ConfigurationExtensions.cs index 9bf9fa989..2ca94724f 100644 --- a/src/Microsoft.Sbom.Api/Config/Extensions/ConfigurationExtensions.cs +++ b/src/Microsoft.Sbom.Api/Config/Extensions/ConfigurationExtensions.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using AutoMapper; using Microsoft.Sbom.Api.Utils; using Microsoft.Sbom.Common.Config; using Microsoft.Sbom.Common.Config.Attributes; @@ -51,7 +50,5 @@ public static string[] ToComponentDetectorCommandLineParams(this IConfiguration // Map the validated InputConfiguration to a Configuration, which will persist the mapping statically and globally public static Configuration ToConfiguration(this InputConfiguration inputConfig) => - new MapperConfiguration(cfg => cfg.CreateMap()) - .CreateMapper() - .Map(inputConfig); + ConfigurationMapper.ToConfiguration(inputConfig); } diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/ArtifactInfoMapSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/ArtifactInfoMapSettingAddingConverter.cs deleted file mode 100644 index afb63f174..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/ArtifactInfoMapSettingAddingConverter.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Generic; -using System.Linq; -using AutoMapper; -using Microsoft.Sbom.Common.Config; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -internal class ArtifactInfoMapSettingAddingConverter : IValueConverter, ConfigurationSetting>> -{ - private readonly SettingSource settingSource; - - public ArtifactInfoMapSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting> Convert(Dictionary sourceMember, ResolutionContext context) - { - if (sourceMember == null || !sourceMember.Any()) - { - return null; - } - - return new ConfigurationSetting> - { - Source = settingSource, - Value = sourceMember - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/BoolConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/BoolConfigurationSettingAddingConverter.cs deleted file mode 100644 index 4d76a2d95..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/BoolConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Common.Config; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts a nullable bool member to a ConfigurationSetting decorated string member. -/// -internal class BoolConfigurationSettingAddingConverter : IValueConverter> -{ - private readonly SettingSource settingSource; - - public BoolConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(bool sourceMember, ResolutionContext context) - { - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/ConformanceConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/ConformanceConfigurationSettingAddingConverter.cs deleted file mode 100644 index 6ad0ab942..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/ConformanceConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Common.Config; -using Microsoft.Sbom.Contracts.Enums; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts a Conformance member to a ConfigurationSetting decorated string member. -/// -internal class ConformanceConfigurationSettingAddingConverter : IValueConverter> -{ - private SettingSource settingSource; - - public ConformanceConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(ConformanceType? sourceMember, ResolutionContext context) - { - if (sourceMember == null) - { - settingSource = SettingSource.Default; - } - - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember ?? ConformanceType.None - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/HashAlgorithmNameConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/HashAlgorithmNameConfigurationSettingAddingConverter.cs deleted file mode 100644 index 33a2bda29..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/HashAlgorithmNameConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Api.Utils; -using Microsoft.Sbom.Common.Config; -using Microsoft.Sbom.Contracts.Enums; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts an LogEventLevel member to a ConfigurationSetting decorated string member. -/// -internal class HashAlgorithmNameConfigurationSettingAddingConverter : IValueConverter> -{ - private SettingSource settingSource; - - public HashAlgorithmNameConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(AlgorithmName sourceMember, ResolutionContext context) - { - if (sourceMember == null) - { - settingSource = SettingSource.Default; - } - - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember ?? Constants.DefaultHashAlgorithmName - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/IntConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/IntConfigurationSettingAddingConverter.cs deleted file mode 100644 index 273cefb9a..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/IntConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Common.Config; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts the int property to a ConfigurationSetting decorated member -/// Int.MinValue is considered invalid. -/// -internal class IntConfigurationSettingAddingConverter : IValueConverter>, IValueConverter> -{ - private readonly SettingSource settingSource; - - public IntConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(int? sourceMember, ResolutionContext context) - { - if (sourceMember == null) - { - return null; - } - - return Convert(sourceMember.Value, context); - } - - public ConfigurationSetting Convert(int sourceMember, ResolutionContext context) - { - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/LogEventLevelConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/LogEventLevelConfigurationSettingAddingConverter.cs deleted file mode 100644 index 4e1a1552c..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/LogEventLevelConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Common.Config; -using Serilog.Events; -using Constants = Microsoft.Sbom.Common.Constants; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts an LogEventLevel member to a ConfigurationSetting decorated string member. -/// -internal class LogEventLevelConfigurationSettingAddingConverter : IValueConverter> -{ - private SettingSource settingSource; - - public LogEventLevelConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(LogEventLevel? sourceMember, ResolutionContext context) - { - if (sourceMember == null) - { - settingSource = SettingSource.Default; - } - - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember ?? Constants.DefaultLogLevel - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/ManifestInfoConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/ManifestInfoConfigurationSettingAddingConverter.cs deleted file mode 100644 index c93e6f800..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/ManifestInfoConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Generic; -using AutoMapper; -using Microsoft.Sbom.Common.Config; -using Microsoft.Sbom.Extensions.Entities; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts an ManifestInfo member to a ConfigurationSetting decorated string member. -/// -internal class ManifestInfoConfigurationSettingAddingConverter : IValueConverter, ConfigurationSetting>> -{ - private SettingSource settingSource; - - public ManifestInfoConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting> Convert(IList sourceMember, ResolutionContext context) - { - if (sourceMember == null) - { - settingSource = SettingSource.Default; - sourceMember = null; - } - - return new ConfigurationSetting> - { - Source = settingSource, - Value = sourceMember - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/NullableBoolConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/NullableBoolConfigurationSettingAddingConverter.cs deleted file mode 100644 index 00de0d1ae..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/NullableBoolConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Common.Config; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts a nullable bool member to a ConfigurationSetting decorated string member. -/// -internal class NullableBoolConfigurationSettingAddingConverter : IValueConverter> -{ - private readonly SettingSource settingSource; - - public NullableBoolConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(bool? sourceMember, ResolutionContext context) - { - if (sourceMember == null) - { - return null; - } - - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember.Value - }; - } -} diff --git a/src/Microsoft.Sbom.Api/Config/ValueConverters/StringConfigurationSettingAddingConverter.cs b/src/Microsoft.Sbom.Api/Config/ValueConverters/StringConfigurationSettingAddingConverter.cs deleted file mode 100644 index c47054983..000000000 --- a/src/Microsoft.Sbom.Api/Config/ValueConverters/StringConfigurationSettingAddingConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using AutoMapper; -using Microsoft.Sbom.Common.Config; - -namespace Microsoft.Sbom.Api.Config.ValueConverters; - -/// -/// Converts a string member to a ConfigurationSetting decorated string member. -/// -internal class StringConfigurationSettingAddingConverter : IValueConverter> -{ - private readonly SettingSource settingSource; - - public StringConfigurationSettingAddingConverter(SettingSource settingSource) - { - this.settingSource = settingSource; - } - - public ConfigurationSetting Convert(string sourceMember, ResolutionContext context) - { - if (string.IsNullOrEmpty(sourceMember)) - { - return null; - } - - return new ConfigurationSetting - { - Source = settingSource, - Value = sourceMember - }; - } -} diff --git a/src/Microsoft.Sbom.Api/ConfigurationProfile.cs b/src/Microsoft.Sbom.Api/ConfigurationProfile.cs deleted file mode 100644 index b402a2294..000000000 --- a/src/Microsoft.Sbom.Api/ConfigurationProfile.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Collections.Generic; -using AutoMapper; -using Microsoft.Sbom.Api.Config; -using Microsoft.Sbom.Api.Config.Args; -using Microsoft.Sbom.Api.Config.ValueConverters; -using Microsoft.Sbom.Common.Config; -using Microsoft.Sbom.Contracts.Enums; -using Microsoft.Sbom.Extensions.Entities; -using Serilog.Events; - -namespace Microsoft.Sbom.Api; - -/// -/// Provides a named profile for the automapper that -/// generates a mapping for all the classes that map to a configuration object. -/// -public class ConfigurationProfile : Profile -{ - public ConfigurationProfile() - { - // Create config for the validation args, ignoring other action members - CreateMap() -#pragma warning disable CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.ManifestPath, o => o.Ignore()) -#pragma warning restore CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.PackageName, o => o.Ignore()) - .ForMember(c => c.PackageVersion, o => o.Ignore()) - .ForMember(c => c.BuildListFile, o => o.Ignore()) - .ForMember(c => c.ExternalDocumentReferenceListFile, o => o.Ignore()) - .ForMember(c => c.BuildComponentPath, o => o.Ignore()) - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()) - .ForMember(c => c.DockerImagesToScan, o => o.Ignore()) - .ForMember(c => c.AdditionalComponentDetectorArgs, o => o.Ignore()) - .ForMember(c => c.GenerationTimestamp, o => o.Ignore()) - .ForMember(c => c.NamespaceUriUniquePart, o => o.Ignore()) - .ForMember(c => c.NamespaceUriBase, o => o.Ignore()) - .ForMember(c => c.DeleteManifestDirIfPresent, o => o.Ignore()) - .ForMember(c => c.PackageSupplier, o => o.Ignore()); - - CreateMap() -#pragma warning disable CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.ManifestPath, o => o.Ignore()) -#pragma warning restore CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.HashAlgorithm, o => o.Ignore()) - .ForMember(c => c.RootPathFilter, o => o.Ignore()) - .ForMember(c => c.CatalogFilePath, o => o.Ignore()) - .ForMember(c => c.ValidateSignature, o => o.Ignore()) - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()) - .ForMember(c => c.IgnoreMissing, o => o.Ignore()) - .ForMember(c => c.FailIfNoPackages, o => o.Ignore()) - .ForMember(c => c.PackageName, o => o.Ignore()) - .ForMember(c => c.PackageVersion, o => o.Ignore()) - .ForMember(c => c.BuildListFile, o => o.Ignore()) - .ForMember(c => c.ExternalDocumentReferenceListFile, o => o.Ignore()) - .ForMember(c => c.BuildComponentPath, o => o.Ignore()) - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()) - .ForMember(c => c.DockerImagesToScan, o => o.Ignore()) - .ForMember(c => c.AdditionalComponentDetectorArgs, o => o.Ignore()) - .ForMember(c => c.GenerationTimestamp, o => o.Ignore()) - .ForMember(c => c.NamespaceUriUniquePart, o => o.Ignore()) - .ForMember(c => c.NamespaceUriBase, o => o.Ignore()) - .ForMember(c => c.DeleteManifestDirIfPresent, o => o.Ignore()) - .ForMember(c => c.PackageSupplier, o => o.Ignore()); - - // Create config for the generation args, ignoring other action members - CreateMap() -#pragma warning disable CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.ManifestPath, o => o.Ignore()) -#pragma warning restore CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.OutputPath, o => o.Ignore()) - .ForMember(c => c.HashAlgorithm, o => o.Ignore()) - .ForMember(c => c.RootPathFilter, o => o.Ignore()) - .ForMember(c => c.CatalogFilePath, o => o.Ignore()) - .ForMember(c => c.ValidateSignature, o => o.Ignore()) - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()) - .ForMember(c => c.IgnoreMissing, o => o.Ignore()) - .ForMember(c => c.FailIfNoPackages, o => o.Ignore()); - - // Create config for the redact args, ignoring other action members - CreateMap() -#pragma warning disable CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.ManifestPath, o => o.Ignore()) -#pragma warning restore CS0618 // 'Configuration.ManifestPath' is obsolete: 'This field is not provided by the user or configFile, set by system' - .ForMember(c => c.HashAlgorithm, o => o.Ignore()) - .ForMember(c => c.RootPathFilter, o => o.Ignore()) - .ForMember(c => c.CatalogFilePath, o => o.Ignore()) - .ForMember(c => c.ValidateSignature, o => o.Ignore()) - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()) - .ForMember(c => c.IgnoreMissing, o => o.Ignore()) - .ForMember(c => c.FailIfNoPackages, o => o.Ignore()) - .ForMember(c => c.PackageName, o => o.Ignore()) - .ForMember(c => c.PackageVersion, o => o.Ignore()) - .ForMember(c => c.BuildListFile, o => o.Ignore()) - .ForMember(c => c.ExternalDocumentReferenceListFile, o => o.Ignore()) - .ForMember(c => c.BuildComponentPath, o => o.Ignore()) - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()) - .ForMember(c => c.DockerImagesToScan, o => o.Ignore()) - .ForMember(c => c.AdditionalComponentDetectorArgs, o => o.Ignore()) - .ForMember(c => c.GenerationTimestamp, o => o.Ignore()) - .ForMember(c => c.NamespaceUriUniquePart, o => o.Ignore()) - .ForMember(c => c.NamespaceUriBase, o => o.Ignore()) - .ForMember(c => c.DeleteManifestDirIfPresent, o => o.Ignore()) - .ForMember(c => c.PackageSupplier, o => o.Ignore()); - - // See Issue #1107 for details on why this map doesn't have a bunch of .ForMember calls to ignore properties. - CreateMap(); - - // Create config for the config json file to configuration. - CreateMap() - .ForMember(c => c.PackagesList, o => o.Ignore()) - .ForMember(c => c.FilesList, o => o.Ignore()); - - // Add maps to combine both config json and argument args, - // validate each settings using the config validator. - CreateMap() - .AfterMap() - .ForAllMembers(dest => dest.Condition((src, dest, srcObj, dstObj) => - { - // If the property is set in both source and destination (config and cmdline, - // this is a failure case, unless one of the property is a default value, in which - // case the non default value wins. - if (srcObj != null && dstObj != null - && srcObj is ISettingSourceable srcWithSource - && dstObj is ISettingSourceable dstWithSource) - { - if (srcWithSource.Source != SettingSource.Default && dstWithSource.Source != SettingSource.Default) - { - throw new Exception("Duplicate keys found in config file and command line parameters."); - } - - return dstWithSource.Source == SettingSource.Default; - } - - // If source property is not null, use source, or else use destination value. - return srcObj != null; - })); - - // Set value converters for each type of object. - ForAllPropertyMaps( - p => p.SourceType == typeof(string), - (c, memberOptions) => memberOptions.ConvertUsing(new StringConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(bool?), - (c, memberOptions) => memberOptions.ConvertUsing(new NullableBoolConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(bool), - (c, memberOptions) => memberOptions.ConvertUsing(new BoolConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(int), - (c, memberOptions) => memberOptions.ConvertUsing(new IntConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(int?), - (c, memberOptions) => memberOptions.ConvertUsing(new IntConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(LogEventLevel?), - (c, memberOptions) => memberOptions.ConvertUsing(new LogEventLevelConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(IList), - (c, memberOptions) => memberOptions.ConvertUsing(new ManifestInfoConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(AlgorithmName), - (c, memberOptions) => memberOptions.ConvertUsing(new HashAlgorithmNameConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(ConformanceType), - (c, memberOptions) => memberOptions.ConvertUsing(new ConformanceConfigurationSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - ForAllPropertyMaps( - p => p.SourceType == typeof(Dictionary), - (c, memberOptions) => memberOptions.ConvertUsing(new ArtifactInfoMapSettingAddingConverter(GetSettingSourceFor(c.SourceMember.ReflectedType)))); - } - - // Based on the type of source, return the settings type. - private SettingSource GetSettingSourceFor(Type sourceType) - { - switch (sourceType) - { - case Type _ when sourceType.IsSubclassOf(typeof(CommonArgs)): - case Type _ when sourceType == typeof(CommonArgs): - return SettingSource.CommandLine; - case Type _ when sourceType == typeof(ConfigFile): - return SettingSource.JsonConfig; - default: return SettingSource.Default; - } - } -} diff --git a/src/Microsoft.Sbom.Api/Microsoft.Sbom.Api.csproj b/src/Microsoft.Sbom.Api/Microsoft.Sbom.Api.csproj index 36b944da8..7ca1d4f30 100644 --- a/src/Microsoft.Sbom.Api/Microsoft.Sbom.Api.csproj +++ b/src/Microsoft.Sbom.Api/Microsoft.Sbom.Api.csproj @@ -8,7 +8,6 @@ - diff --git a/src/Microsoft.Sbom.DotNetTool/Microsoft.Sbom.DotNetTool.csproj b/src/Microsoft.Sbom.DotNetTool/Microsoft.Sbom.DotNetTool.csproj index 6b542ad3d..24da2783e 100644 --- a/src/Microsoft.Sbom.DotNetTool/Microsoft.Sbom.DotNetTool.csproj +++ b/src/Microsoft.Sbom.DotNetTool/Microsoft.Sbom.DotNetTool.csproj @@ -18,7 +18,6 @@ - diff --git a/src/Microsoft.Sbom.Extensions.DependencyInjection/Microsoft.Sbom.Extensions.DependencyInjection.csproj b/src/Microsoft.Sbom.Extensions.DependencyInjection/Microsoft.Sbom.Extensions.DependencyInjection.csproj index db8733da8..008827d80 100644 --- a/src/Microsoft.Sbom.Extensions.DependencyInjection/Microsoft.Sbom.Extensions.DependencyInjection.csproj +++ b/src/Microsoft.Sbom.Extensions.DependencyInjection/Microsoft.Sbom.Extensions.DependencyInjection.csproj @@ -17,7 +17,6 @@ - diff --git a/src/Microsoft.Sbom.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/src/Microsoft.Sbom.Extensions.DependencyInjection/ServiceCollectionExtensions.cs index 2371d6544..167a10f14 100644 --- a/src/Microsoft.Sbom.Extensions.DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Microsoft.Sbom.Extensions.DependencyInjection/ServiceCollectionExtensions.cs @@ -144,7 +144,7 @@ public static IServiceCollection AddSbomTool(this IServiceCollection services, L .AddSingleton() .AddSingleton() .AddSingleton() - .AddAutoMapper(x => x.AddProfile(new ConfigurationProfile()), typeof(ConfigValidator), typeof(ConfigSanitizer)) + .AddTransient() .Scan(scan => scan.FromApplicationDependencies() .AddClasses(classes => classes.AssignableTo()) .As() diff --git a/src/Microsoft.Sbom.Tool/Microsoft.Sbom.Tool.csproj b/src/Microsoft.Sbom.Tool/Microsoft.Sbom.Tool.csproj index c8acf6ca2..60afe39bd 100644 --- a/src/Microsoft.Sbom.Tool/Microsoft.Sbom.Tool.csproj +++ b/src/Microsoft.Sbom.Tool/Microsoft.Sbom.Tool.csproj @@ -20,7 +20,6 @@ - diff --git a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsBase.cs b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsBase.cs index 46eacde13..100d6c0d7 100644 --- a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsBase.cs +++ b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsBase.cs @@ -1,9 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; -using AutoMapper; using Microsoft.Sbom.Api.Config.Validators; using Microsoft.Sbom.Api.Hashing; using Microsoft.Sbom.Api.Utils; @@ -20,7 +18,7 @@ namespace Microsoft.Sbom.Api.Config.Tests; public class ConfigurationBuilderTestsBase { protected Mock fileSystemUtilsMock; - private protected IMapper mapper; + private protected ConfigPostProcessor configPostProcessor; protected ConfigValidator[] configValidators; protected Mock mockAssemblyConfig; @@ -47,23 +45,8 @@ protected void Init() hashAlgorithmProvider.Init(); var configSanitizer = new ConfigSanitizer(hashAlgorithmProvider, fileSystemUtilsMock.Object, mockAssemblyConfig.Object); - object Ctor(Type type) - { - if (type == typeof(ConfigPostProcessor)) - { - return new ConfigPostProcessor(configValidators, configSanitizer, fileSystemUtilsMock.Object); - } - - return Activator.CreateInstance(type); - } - - var mapperConfiguration = new MapperConfiguration(cfg => - { - cfg.ConstructServicesUsing(Ctor); - cfg.AddProfile(); - }); - mapper = mapperConfiguration.CreateMapper(); + configPostProcessor = new ConfigPostProcessor(configValidators, configSanitizer, fileSystemUtilsMock.Object); } protected const string JSONConfigWithManifestPath = "{ \"ManifestDirPath\": \"manifestDirPath\"}"; diff --git a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForGeneration.cs b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForGeneration.cs index 31c72cd33..06d83ec18 100644 --- a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForGeneration.cs +++ b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForGeneration.cs @@ -28,7 +28,7 @@ public void Setup() public async Task ConfigurationBuilderTest_ForGenerator_CombinesConfigs() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigGoodWithManifestInfo); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); @@ -57,7 +57,7 @@ public async Task ConfigurationBuilderTest_ForGenerator_CombinesConfigs() public async Task ConfigurationBuilderTest_ForGenerator_CombinesConfigs_CmdLineSucceeds() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigGoodWithManifestInfo); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); @@ -86,7 +86,7 @@ public async Task ConfigurationBuilderTest_ForGenerator_CombinesConfigs_CmdLineS public async Task ConfigurationBuilderTest_Generation_BuildDropPathDoNotExist_Throws() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(false); @@ -104,7 +104,7 @@ public async Task ConfigurationBuilderTest_Generation_BuildDropPathDoNotExist_Th public async Task ConfigurationBuilderTest_Generation_BuildDropPathNotWriteAccess_Throws() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); @@ -124,7 +124,7 @@ public async Task ConfigurationBuilderTest_Generation_BuildDropPathNotWriteAcces public async Task ConfigurationBuilderTest_Generation_DefaultManifestDirPath_AddsManifestDir() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); @@ -153,7 +153,7 @@ public async Task ConfigurationBuilderTest_Generation_DefaultManifestDirPath_Add public async Task ConfigurationBuilderTest_Generation_UserManifestDirPath_AddsManifestDir() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); @@ -183,7 +183,7 @@ public async Task ConfigurationBuilderTest_Generation_UserManifestDirPath_AddsMa public async Task ConfigurationBuilderTest_Generation_NSBaseUri_Validated() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); @@ -213,7 +213,7 @@ public async Task ConfigurationBuilderTest_Generation_NSBaseUri_Validated() public async Task ConfigurationBuilderTest_Generation_BadNSBaseUriWithDefaultValue_Succeds() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); mockAssemblyConfig.SetupGet(a => a.DefaultSbomNamespaceBaseUri).Returns("https://uri"); @@ -246,7 +246,7 @@ public async Task ConfigurationBuilderTest_Generation_BadNSBaseUriWithDefaultVal public async Task ConfigurationBuilderTest_Generation_NullNSBaseUriChangesToDefault() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); @@ -279,7 +279,7 @@ public async Task ConfigurationBuilderTest_Generation_NullNSBaseUriChangesToDefa public async Task ConfigurationBuilderTest_Generation_BadNSBaseUri_Fails(string badNsUri) { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); @@ -304,7 +304,7 @@ public async Task ConfigurationBuilderTest_Generation_BadNSBaseUri_Fails(string public async Task ConfigurationBuilderTest_Generation_BadManifestInfo_Fails(string manifestInfo) { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); diff --git a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForRedact.cs b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForRedact.cs index 3eb8f91ce..d15482712 100644 --- a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForRedact.cs +++ b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForRedact.cs @@ -24,7 +24,7 @@ public void Setup() public async Task ConfigurationBuilderTest_ForRedact_CombinesConfigs() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true).Verifiable(); @@ -49,7 +49,7 @@ public async Task ConfigurationBuilderTest_ForRedact_CombinesConfigs() public async Task ConfigurationBuilderTest_Redact_OuputPathNotWriteAccess_Throws() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true); diff --git a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForValidation.cs b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForValidation.cs index 5c94cfbec..284002832 100644 --- a/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForValidation.cs +++ b/test/Microsoft.Sbom.Api.Tests/Config/ConfigurationBuilderTestsForValidation.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using AutoMapper; using Microsoft.Sbom.Api.Config.Args; using Microsoft.Sbom.Common.Config; using Microsoft.Sbom.Contracts.Enums; @@ -29,7 +28,7 @@ public void Setup() public async Task ConfigurationBuilderTest_CombinesConfigs() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigWithManifestPath).Verifiable(); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); @@ -62,7 +61,7 @@ public async Task ConfigurationBuilderTest_CombinesConfigs() public async Task ConfigurationBuilderTest_CombinesConfigs_DuplicateConfig_DefaultLoses() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigWithManifestPath).Verifiable(); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); @@ -95,7 +94,7 @@ public async Task ConfigurationBuilderTest_CombinesConfigs_DuplicateConfig_Defau public async Task ConfigurationBuilderTest_CombinesConfigs_DuplicateConfig_Throws() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigWithManifestPath); @@ -107,14 +106,14 @@ public async Task ConfigurationBuilderTest_CombinesConfigs_DuplicateConfig_Throw ManifestDirPath = "ManifestPath" }; - await Assert.ThrowsExceptionAsync(() => cb.GetConfiguration(args)); + await Assert.ThrowsExceptionAsync(() => cb.GetConfiguration(args)); } [TestMethod] public async Task ConfigurationBuilderTest_CombinesConfigs_NegativeParallism_Throws() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigWithManifestPath); @@ -133,7 +132,7 @@ public async Task ConfigurationBuilderTest_CombinesConfigs_NegativeParallism_Thr public async Task ConfigurationBuilderTest_Validation_DefaultManifestDirPath_AddsManifestDir() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true).Verifiable(); @@ -159,7 +158,7 @@ public async Task ConfigurationBuilderTest_Validation_DefaultManifestDirPath_Add public async Task ConfigurationBuilderTest_Validation_UserManifestDirPath_DoesntManifestDir() { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable(); fileSystemUtilsMock.Setup(f => f.DirectoryHasReadPermissions(It.IsAny())).Returns(true).Verifiable(); @@ -188,7 +187,7 @@ public async Task ConfigurationBuilderTest_Validation_UserManifestDirPath_Doesnt public async Task ConfigurationBuilderTest_Validation_BadManifestInfo_Fails(string manifestInfo) { var configFileParser = new ConfigFileParser(fileSystemUtilsMock.Object); - var cb = new ConfigurationBuilder(mapper, configFileParser); + var cb = new ConfigurationBuilder(configPostProcessor, configFileParser); fileSystemUtilsMock.Setup(f => f.ReadAllTextAsync(It.IsAny())).ReturnsAsync(JSONConfigWithManifestPath).Verifiable(); fileSystemUtilsMock.Setup(f => f.DirectoryExists(It.IsAny())).Returns(true).Verifiable();