Skip to content

Commit

Permalink
API BREAKING CHANGE: Remove back-compat interface shims (#952)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveTryon authored Mar 3, 2025
1 parent c695cca commit 1dce65e
Showing 13 changed files with 44 additions and 136 deletions.
44 changes: 20 additions & 24 deletions src/Microsoft.Sbom.Api/Config/ConfigSanitizer.cs
Original file line number Diff line number Diff line change
@@ -78,32 +78,28 @@ public IConfiguration SanitizeConfig(IConfiguration configuration)
// Set default package supplier if not provided in configuration.
configuration.PackageSupplier = GetPackageSupplierFromAssembly(configuration, logger);

var configuration2 = configuration as IConfiguration2;
if (configuration2 is not null)
// Prevent null value for LicenseInformationTimeoutInSeconds.
// Values of (0, Constants.MaxLicenseFetchTimeoutInSeconds] are allowed. Negative values are replaced with the default, and
// the higher values are truncated to the maximum of Common.Constants.MaxLicenseFetchTimeoutInSeconds
if (configuration.LicenseInformationTimeoutInSeconds is null)
{
// Prevent null value for LicenseInformationTimeoutInSeconds.
// Values of (0, Constants.MaxLicenseFetchTimeoutInSeconds] are allowed. Negative values are replaced with the default, and
// the higher values are truncated to the maximum of Common.Constants.MaxLicenseFetchTimeoutInSeconds
if (configuration2.LicenseInformationTimeoutInSeconds is null)
{
configuration2.LicenseInformationTimeoutInSeconds = new(Common.Constants.DefaultLicenseFetchTimeoutInSeconds, SettingSource.Default);
}
else if (configuration2.LicenseInformationTimeoutInSeconds.Value <= 0)
{
logger.Warning($"Negative and Zero Values not allowed for timeout. Using the default {Common.Constants.DefaultLicenseFetchTimeoutInSeconds} seconds instead.");
configuration2.LicenseInformationTimeoutInSeconds.Value = Common.Constants.DefaultLicenseFetchTimeoutInSeconds;
}
else if (configuration2.LicenseInformationTimeoutInSeconds.Value > Common.Constants.MaxLicenseFetchTimeoutInSeconds)
{
logger.Warning($"Specified timeout exceeds maximum allowed. Truncating the timeout to {Common.Constants.MaxLicenseFetchTimeoutInSeconds} seconds.");
configuration2.LicenseInformationTimeoutInSeconds.Value = Common.Constants.MaxLicenseFetchTimeoutInSeconds;
}
configuration.LicenseInformationTimeoutInSeconds = new(Common.Constants.DefaultLicenseFetchTimeoutInSeconds, SettingSource.Default);
}
else if (configuration.LicenseInformationTimeoutInSeconds.Value <= 0)
{
logger.Warning($"Negative and Zero Values not allowed for timeout. Using the default {Common.Constants.DefaultLicenseFetchTimeoutInSeconds} seconds instead.");
configuration.LicenseInformationTimeoutInSeconds.Value = Common.Constants.DefaultLicenseFetchTimeoutInSeconds;
}
else if (configuration.LicenseInformationTimeoutInSeconds.Value > Common.Constants.MaxLicenseFetchTimeoutInSeconds)
{
logger.Warning($"Specified timeout exceeds maximum allowed. Truncating the timeout to {Common.Constants.MaxLicenseFetchTimeoutInSeconds} seconds.");
configuration.LicenseInformationTimeoutInSeconds.Value = Common.Constants.MaxLicenseFetchTimeoutInSeconds;
}

// Check if arg -lto is specified but -li is not
if (configuration.FetchLicenseInformation?.Value != true && !configuration2.LicenseInformationTimeoutInSeconds.IsDefaultSource)
{
logger.Warning("A license fetching timeout is specified (argument -lto), but this has no effect when FetchLicenseInfo is unspecified or false (argument -li)");
}
// Check if arg -lto is specified but -li is not
if (configuration.FetchLicenseInformation?.Value != true && !configuration.LicenseInformationTimeoutInSeconds.IsDefaultSource)
{
logger.Warning("A license fetching timeout is specified (argument -lto), but this has no effect when FetchLicenseInfo is unspecified or false (argument -li)");
}

// Replace backslashes in directory paths with the OS-sepcific directory separator character.
27 changes: 1 addition & 26 deletions src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs
Original file line number Diff line number Diff line change
@@ -144,22 +144,8 @@ async Task Scan(string path)
licenseInformationRetrieved = true;

List<string> apiResponses;
var licenseInformationFetcher2 = licenseInformationFetcher as ILicenseInformationFetcher2;
var licenseInformationTimeoutInSecondsConfigSetting = GetLicenseInformationTimeoutInSecondsSetting(configuration);

if (licenseInformationFetcher2 is null && (bool)!licenseInformationTimeoutInSecondsConfigSetting?.IsDefaultSource)
{
log.Warning("Timeout value is specified, but ILicenseInformationFetcher2 is not implemented for the licenseInformationFetcher");
}

if (licenseInformationFetcher2 is null || licenseInformationTimeoutInSecondsConfigSetting is null)
{
apiResponses = await licenseInformationFetcher.FetchLicenseInformationAsync(listOfComponentsForApi);
}
else
{
apiResponses = await licenseInformationFetcher2.FetchLicenseInformationAsync(listOfComponentsForApi, licenseInformationTimeoutInSecondsConfigSetting.Value);
}
apiResponses = await licenseInformationFetcher.FetchLicenseInformationAsync(listOfComponentsForApi, configuration.LicenseInformationTimeoutInSeconds.Value);

foreach (var response in apiResponses)
{
@@ -233,15 +219,4 @@ async Task Scan(string path)
}

protected abstract IEnumerable<ScannedComponent> FilterScannedComponents(ScanResult result);

private ConfigurationSetting<int>? GetLicenseInformationTimeoutInSecondsSetting(IConfiguration configuration)
{
var configuration2 = configuration as IConfiguration2;
if (configuration2 is not null)
{
return configuration2.LicenseInformationTimeoutInSeconds;
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -18,11 +18,12 @@ public interface ILicenseInformationFetcher
List<string> ConvertComponentsToListForApi(IEnumerable<ScannedComponent> scannedComponents);

/// <summary>
/// Calls the ClearlyDefined API to get the license information for the list of components. Uses a default timeout specified in implementation
/// Calls the ClearlyDefined API to get the license information for the list of components.
/// </summary>
/// <param name="listOfComponentsForApi"> A list of strings formatted into a list of strings that can be used to call the batch ClearlyDefined API.</param>
/// <param name="timeoutInSeconds">Timeout in seconds to use when making web requests. Caller owns sanitizing this value</param>
/// <returns></returns>
Task<List<string>> FetchLicenseInformationAsync(List<string> listOfComponentsForApi);
Task<List<string>> FetchLicenseInformationAsync(List<string> listOfComponentsForApi, int timeoutInSeconds);

/// <summary>
/// Gets the dictionary of licenses that were fetched from the ClearlyDefined API.
18 changes: 0 additions & 18 deletions src/Microsoft.Sbom.Api/Executors/ILicenseInformationFetcher2.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -8,5 +8,5 @@ namespace Microsoft.Sbom.Api.Executors;

public interface ILicenseInformationService
{
public Task<List<string>> FetchLicenseInformationFromAPI(List<string> listOfComponentsForApi);
public Task<List<string>> FetchLicenseInformationFromAPI(List<string> listOfComponentsForApi, int timeoutInSeconds);
}
12 changes: 0 additions & 12 deletions src/Microsoft.Sbom.Api/Executors/ILicenseInformationService2.cs

This file was deleted.

18 changes: 2 additions & 16 deletions src/Microsoft.Sbom.Api/Executors/LicenseInformationFetcher.cs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@

namespace Microsoft.Sbom.Api.Executors;

public class LicenseInformationFetcher : ILicenseInformationFetcher2
public class LicenseInformationFetcher : ILicenseInformationFetcher
{
private readonly ILogger log;
private readonly IRecorder recorder;
@@ -82,23 +82,9 @@ public List<string> ConvertComponentsToListForApi(IEnumerable<ScannedComponent>
return listOfComponentsForApi;
}

public async Task<List<string>> FetchLicenseInformationAsync(List<string> listOfComponentsForApi)
{
return await licenseInformationService.FetchLicenseInformationFromAPI(listOfComponentsForApi);
}

public async Task<List<string>> FetchLicenseInformationAsync(List<string> listOfComponentsForApi, int timeoutInSeconds)
{
var licenseInformationService2 = licenseInformationService as ILicenseInformationService2;
if (licenseInformationService2 is null)
{
log.Warning("Timeout is specified in License Fetcher, but licenseInformationService does not implement ILicenseInformationService2");
return await licenseInformationService.FetchLicenseInformationFromAPI(listOfComponentsForApi);
}
else
{
return await licenseInformationService2.FetchLicenseInformationFromAPI(listOfComponentsForApi, timeoutInSeconds);
}
return await licenseInformationService.FetchLicenseInformationFromAPI(listOfComponentsForApi, timeoutInSeconds);
}

// Will attempt to extract license information from a clearlyDefined batch API response. Will always return a dictionary which may be empty depending on the response.
12 changes: 2 additions & 10 deletions src/Microsoft.Sbom.Api/Executors/LicenseInformationService.cs
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@

namespace Microsoft.Sbom.Api.Executors;

public class LicenseInformationService : ILicenseInformationService2
public class LicenseInformationService : ILicenseInformationService
{
private readonly ILogger log;
private readonly IRecorder recorder;
@@ -28,11 +28,6 @@ public LicenseInformationService(ILogger log, IRecorder recorder, HttpClient htt
this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}

public async Task<List<string>> FetchLicenseInformationFromAPI(List<string> listOfComponentsForApi)
{
return await FetchLicenseInformationFromAPI(listOfComponentsForApi, Common.Constants.MaxLicenseFetchTimeoutInSeconds);
}

public async Task<List<string>> FetchLicenseInformationFromAPI(List<string> listOfComponentsForApi, int timeoutInSeconds)
{
var batchSize = 500;
@@ -42,10 +37,7 @@ public async Task<List<string>> FetchLicenseInformationFromAPI(List<string> list
var uri = new Uri("https://api.clearlydefined.io/definitions?expand=-files");

httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (timeoutInSeconds > 0)
{
httpClient.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
} // The else cases should be sanitized in Config Sanitizer, and even if not, it'll just use httpClient's default timeout
httpClient.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);

for (var i = 0; i < listOfComponentsForApi.Count; i += batchSize)
{
6 changes: 3 additions & 3 deletions src/Microsoft.Sbom.Common/Config/Configuration.cs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ namespace Microsoft.Sbom.Common.Config;

[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1311:Static readonly fields should begin with upper-case letter", Justification = "Private fields with the same name as public properties.")]
[SuppressMessage("Naming", "CA1724:Type names should not match namespaces", Justification = "This is the configuration class")]
public class Configuration : IConfiguration2
public class Configuration : IConfiguration
{
private static readonly AsyncLocal<ConfigurationSetting<string>> buildDropPath = new();
private static readonly AsyncLocal<ConfigurationSetting<string>> buildComponentPath = new();
@@ -47,7 +47,7 @@ public class Configuration : IConfiguration2
private static readonly AsyncLocal<ConfigurationSetting<string>> generationTimestamp = new();
private static readonly AsyncLocal<ConfigurationSetting<bool>> followSymlinks = new();
private static readonly AsyncLocal<ConfigurationSetting<bool>> fetchLicenseInformation = new();
private static readonly AsyncLocal<ConfigurationSetting<int>> licenseInformationTimeout = new(); // IConfiguration2
private static readonly AsyncLocal<ConfigurationSetting<int>> licenseInformationTimeout = new();
private static readonly AsyncLocal<ConfigurationSetting<bool>> enablePackageMetadataParsing = new();
private static readonly AsyncLocal<ConfigurationSetting<bool>> deleteManifestDirIfPresent = new();
private static readonly AsyncLocal<ConfigurationSetting<bool>> failIfNoPackages = new();
@@ -311,7 +311,7 @@ public ConfigurationSetting<bool> FetchLicenseInformation
set => fetchLicenseInformation.Value = value;
}

/// <inheritdoc cref="IConfiguration2.LicenseInformationTimeoutInSeconds" />
/// <inheritdoc cref="IConfiguration.LicenseInformationTimeoutInSeconds" />
[DefaultValue(Constants.DefaultLicenseFetchTimeoutInSeconds)]
public ConfigurationSetting<int> LicenseInformationTimeoutInSeconds
{
6 changes: 6 additions & 0 deletions src/Microsoft.Sbom.Common/Config/IConfiguration.cs
Original file line number Diff line number Diff line change
@@ -212,4 +212,10 @@ public interface IConfiguration
/// The compliance standard to validate against.
/// </summary>
ConfigurationSetting<string> ComplianceStandard { get; set; }

/// Specifies the timeout in seconds for fetching the license information. Defaults to <see cref="Constants.DefaultLicenseFetchTimeoutInSeconds"/>.
/// Has no effect if FetchLicenseInformation (li) argument is false or not provided. Negative values are set to the default and values exceeding the
/// maximum are truncated to <see cref="Constants.MaxLicenseFetchTimeoutInSeconds"/>
/// </summary>
ConfigurationSetting<int> LicenseInformationTimeoutInSeconds { get; set; }
}
19 changes: 0 additions & 19 deletions src/Microsoft.Sbom.Common/Config/IConfiguration2.cs

This file was deleted.

4 changes: 2 additions & 2 deletions src/Microsoft.Sbom.Common/Config/InputConfiguration.cs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
namespace Microsoft.Sbom.Common.Config;

[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1311:Static readonly fields should begin with upper-case letter", Justification = "Private fields with the same name as public properties.")]
public class InputConfiguration : IConfiguration2
public class InputConfiguration : IConfiguration
{
/// <inheritdoc cref="IConfiguration.BuildDropPath" />
[DirectoryExists]
@@ -141,7 +141,7 @@ public class InputConfiguration : IConfiguration2
[DefaultValue(false)]
public ConfigurationSetting<bool> FetchLicenseInformation { get; set; }

/// <inheritdoc cref="IConfiguration2.LicenseInformationTimeoutInSeconds" />
/// <inheritdoc cref="IConfiguration.LicenseInformationTimeoutInSeconds" />
[DefaultValue(Constants.DefaultLicenseFetchTimeoutInSeconds)]
public ConfigurationSetting<int> LicenseInformationTimeoutInSeconds { get; set; }

Original file line number Diff line number Diff line change
@@ -75,14 +75,14 @@ private class PinnedILicenseInformationFetcher : ILicenseInformationFetcher
public void AppendLicensesToDictionary(Dictionary<string, string> partialLicenseDictionary) => throw new NotImplementedException();
public Dictionary<string, string> ConvertClearlyDefinedApiResponseToList(string httpResponseContent) => throw new NotImplementedException();
public List<string> ConvertComponentsToListForApi(IEnumerable<ScannedComponent> scannedComponents) => throw new NotImplementedException();
public Task<List<string>> FetchLicenseInformationAsync(List<string> listOfComponentsForApi) => throw new NotImplementedException();
public Task<List<string>> FetchLicenseInformationAsync(List<string> listOfComponentsForApi, int timeoutInSeconds) => throw new NotImplementedException();
public string GetFromLicenseDictionary(string key) => throw new NotImplementedException();
public ConcurrentDictionary<string, string> GetLicenseDictionary() => throw new NotImplementedException();
}

private class PinnedILicenstInformationSErvice : ILicenseInformationService
private class PinnedILicenstInformationService : ILicenseInformationService
{
public Task<List<string>> FetchLicenseInformationFromAPI(List<string> listOfComponentsForApi) => throw new NotImplementedException();
public Task<List<string>> FetchLicenseInformationFromAPI(List<string> listOfComponentsForApi, int timeoutInSeconds) => throw new NotImplementedException();
}

private class Pinned_SBOMReaderForExternalDocumentReference : ISbomReaderForExternalDocumentReference
@@ -330,6 +330,7 @@ private class PinnedIConfiguration : IConfiguration
public ConfigurationSetting<string> SbomPath { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public ConfigurationSetting<string> SbomDir { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public ConfigurationSetting<string> ComplianceStandard { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public ConfigurationSetting<int> LicenseInformationTimeoutInSeconds { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}

private class PinnedISettingSourceable : ISettingSourceable

0 comments on commit 1dce65e

Please sign in to comment.