diff --git a/docs/Reference/Generated/MigrationTools.xml b/docs/Reference/Generated/MigrationTools.xml
index 52872266d..d507badcf 100644
--- a/docs/Reference/Generated/MigrationTools.xml
+++ b/docs/Reference/Generated/MigrationTools.xml
@@ -263,27 +263,27 @@
- => @"b2f20d07"
+ => @"cd3dc28e"
- => @"b2f20d070b957515450ac797a47507c6f35126fa"
+ => @"cd3dc28e52a31c168b7b951d34456f95caf338f6"
- => @"2024-08-28T14:24:26+01:00"
+ => @"2024-08-28T17:45:31+01:00"
- => @"220"
+ => @"221"
- => @"v15.2.1-220-gb2f20d07"
+ => @"v15.2.1-221-gcd3dc28e"
@@ -318,7 +318,7 @@
- => @"221"
+ => @"222"
diff --git a/src/MigrationTools.ConsoleFull/Properties/launchSettings.json b/src/MigrationTools.ConsoleFull/Properties/launchSettings.json
index 5def193ce..38d095386 100644
--- a/src/MigrationTools.ConsoleFull/Properties/launchSettings.json
+++ b/src/MigrationTools.ConsoleFull/Properties/launchSettings.json
@@ -25,7 +25,7 @@
},
"init Options-Reference": {
"commandName": "Project",
- "commandLineArgs": "init --options Reference -c configuration-ref.json"
+ "commandLineArgs": "init --options Reference -c configuration-ref.json --overwrite"
},
"Upgrade": {
"commandName": "Project",
diff --git a/src/MigrationTools.Host/Commands/InitMigrationCommand.cs b/src/MigrationTools.Host/Commands/InitMigrationCommand.cs
index 776ec20f1..e5e49b4a5 100644
--- a/src/MigrationTools.Host/Commands/InitMigrationCommand.cs
+++ b/src/MigrationTools.Host/Commands/InitMigrationCommand.cs
@@ -7,6 +7,7 @@
using Elmah.Io.Client;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -21,15 +22,19 @@ namespace MigrationTools.Host.Commands
{
internal class InitMigrationCommand : AsyncCommand
{
+ public IServiceProvider Services { get; }
+
private readonly ILogger _logger;
private readonly ITelemetryLogger Telemetery;
private readonly IHostApplicationLifetime _appLifetime;
public InitMigrationCommand(
+ IServiceProvider services,
ILogger logger,
ITelemetryLogger telemetryLogger,
IHostApplicationLifetime appLifetime)
{
+ Services = services;
_logger = logger;
Telemetery = telemetryLogger;
_appLifetime = appLifetime;
@@ -66,72 +71,45 @@ public override async Task ExecuteAsync(CommandContext context, InitMigrati
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
- // get source IOptions bits
- List allMigrationTypes = AppDomain.CurrentDomain.GetMigrationToolsTypes().ToList();
- var allOptions = allMigrationTypes.WithInterface();
- JObject configJson = new JObject();
_logger.LogInformation("Populating config with {Options}", settings.Options.ToString());
- List optionsToInclude = null;
- Dictionary endpointsToInclude = null;
+
+ OptionsConfigurationBuilder optionsBuilder = Services.GetService();
+
switch (settings.Options)
{
case OptionsMode.Reference:
-
+ optionsBuilder.AddAllOptions();
break;
case OptionsMode.Basic:
- optionsToInclude = new List() { "TfsWorkItemMigrationProcessor", "FieldMappingTool", "FieldLiteralMap" };
- endpointsToInclude = new Dictionary () { { "Source", "TfsTeamProjectEndpoint" }, { "Target", "TfsTeamProjectEndpoint" } };
+ optionsBuilder.AddOption("TfsWorkItemMigrationProcessor");
+ optionsBuilder.AddOption("FieldMappingTool");
+ optionsBuilder.AddOption("FieldLiteralMap");
+ optionsBuilder.AddOption("TfsTeamProjectEndpoint", "Source");
+ optionsBuilder.AddOption("TfsTeamProjectEndpoint", "Target");
break;
case OptionsMode.WorkItemTracking:
- optionsToInclude = new List() { "TfsWorkItemMigrationProcessor", "FieldMappingTool", "FieldLiteralMap" };
- endpointsToInclude = new Dictionary() { { "Source", "TfsTeamProjectEndpoint" }, { "Target", "TfsTeamProjectEndpoint" } };
+ optionsBuilder.AddOption("TfsWorkItemMigrationProcessor");
+ optionsBuilder.AddOption("FieldMappingTool");
+ optionsBuilder.AddOption("FieldLiteralMap");
+ optionsBuilder.AddOption("TfsTeamProjectEndpoint", "Source");
+ optionsBuilder.AddOption("TfsTeamProjectEndpoint", "Target");
+ break;
+ case OptionsMode.PipelineProcessor:
+ optionsBuilder.AddOption("AzureDevOpsPipelineProcessor");
+ optionsBuilder.AddOption("AzureDevOpsEndpoint", "Source");
+ optionsBuilder.AddOption("AzureDevOpsEndpoint", "Target");
break;
- case OptionsMode.PipelineProcessor:
default:
- optionsToInclude = new List() { "AzureDevOpsPipelineProcessor"};
- endpointsToInclude = new Dictionary() { { "Source", "AzureDevOpsEndpoint" }, { "Target", "AzureDevOpsEndpoint" } };
+ optionsBuilder.AddAllOptions();
break;
}
- if (endpointsToInclude !=null)
- {
- foreach (var item in endpointsToInclude)
- {
- var item2 = allOptions.WithInterface().FirstOrDefault(x => x.Name.StartsWith(item.Value));
- configJson = AddEndpointOptionToConfig(configuration, configJson, item.Key, item2);
- }
- } else
- {
- _logger.LogWarning($"You are adding all of the EndPoints, there may be some that cant be added and will cause an error...");
- int epNo = 1;
- foreach (var item in allOptions.WithInterface())
- {
- configJson = AddEndpointOptionToConfig(configuration, configJson, $"Endpoint{epNo}", item);
- epNo++;
- }
- }
+ string json = optionsBuilder.Build();
- if (optionsToInclude != null)
- {
- foreach (var item in optionsToInclude)
- {
- var item2 = allOptions.FirstOrDefault(x => x.Name.StartsWith(item));
- configJson = AddOptionToConfig(configuration, configJson, item2);
- }
- } else
- {
- _logger.LogWarning($"You are adding all of the Options, there may be some that cant be added and will cause an error...");
- foreach (var item in allOptions)
- {
- configJson = AddOptionToConfig(configuration, configJson, item);
- }
- }
-
-
- File.WriteAllText(configFile, configJson.ToString(Formatting.Indented));
+ File.WriteAllText(configFile, json);
_logger.LogInformation("New {configFile} file has been created", configFile);
- _logger.LogInformation(configJson.ToString(Formatting.Indented));
+ _logger.LogInformation(json);
}
_exitCode = 0;
@@ -149,45 +127,5 @@ public override async Task ExecuteAsync(CommandContext context, InitMigrati
}
return _exitCode;
}
-
- private JObject AddEndpointOptionToConfig(IConfigurationRoot configuration, JObject configJson, string key, Type endpointType)
- {
- IOptions instanceOfOption = (IOptions)Activator.CreateInstance(endpointType);
- var section = configuration.GetSection(instanceOfOption.ConfigurationMetadata.PathToInstance);
- section.Bind(instanceOfOption);
- try
- {
- //instanceOfOption.ConfigurationMetadata.Path = $"MigrationTools:Endpoints:{key}";
- var hardPath = $"MigrationTools:Endpoints:{key}";
- configJson = Options.OptionsManager.AddOptionsToConfiguration(configJson, instanceOfOption, hardPath, true);
- _logger.LogInformation("Adding Option: {item}", endpointType.Name);
- }
- catch (Exception)
- {
-
- _logger.LogInformation("FAILED!! Adding Option: {item}", endpointType.FullName);
- }
-
- return configJson;
- }
-
- private JObject AddOptionToConfig(IConfigurationRoot configuration, JObject configJson, Type item)
- {
- IOptions instanceOfOption = (IOptions)Activator.CreateInstance(item);
- var section = configuration.GetSection(instanceOfOption.ConfigurationMetadata.PathToInstance);
- section.Bind(instanceOfOption);
- try
- {
- configJson = Options.OptionsManager.AddOptionsToConfiguration(configJson, instanceOfOption, false);
- _logger.LogInformation("Adding Option: {item}", item.Name);
- }
- catch (Exception)
- {
-
- _logger.LogInformation("FAILED!! Adding Option: {item}", item.FullName);
- }
-
- return configJson;
- }
}
}
diff --git a/src/MigrationTools.Host/ServiceCollectionExtensions.cs b/src/MigrationTools.Host/ServiceCollectionExtensions.cs
index 33c0da323..f169f7874 100644
--- a/src/MigrationTools.Host/ServiceCollectionExtensions.cs
+++ b/src/MigrationTools.Host/ServiceCollectionExtensions.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using MigrationTools.Options;
namespace MigrationTools
{
@@ -12,6 +13,7 @@ public static IServiceCollection AddConfiguredService(this IServiceCollection co
//collection.Configure
//collection.Configure(config);
//return collection.AddTransient();
+
return collection;
}
}
diff --git a/src/MigrationTools/Options/OptionsBuilder.cs b/src/MigrationTools/Options/OptionsBuilder.cs
deleted file mode 100644
index b79144a36..000000000
--- a/src/MigrationTools/Options/OptionsBuilder.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Linq;
-using System.Text;
-using Elmah.Io.Client;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Logging;
-using Microsoft.VisualStudio.Services.Audit;
-using Microsoft.VisualStudio.Services.Common.CommandLine;
-using Newtonsoft.Json.Linq;
-
-namespace MigrationTools.Options
-{
- public class OptionsBuilder
- {
- readonly ILogger logger;
- readonly IConfiguration configuration;
-
- private List OptionsToInclude { get; }
- private Dictionary NamedOptionsToInclude { get; }
-
- private List catalogue;
-
- public OptionsBuilder(
- IConfigurationRoot configuration,
- ILogger logger,
- ITelemetryLogger telemetryLogger)
- {
- this.configuration = configuration;
- this.logger = logger;
- OptionsToInclude = new List();
- NamedOptionsToInclude = new Dictionary();
- catalogue = AppDomain.CurrentDomain.GetMigrationToolsTypes().WithInterface().ToList();
- }
-
- public void AddOption(IOptions option)
- {
- OptionsToInclude.Add(option);
- }
-
- public void AddOption(string optionName)
- {
- optionName = optionName.Replace("Options", "").Replace("Config", "");
- var optionType = catalogue.FirstOrDefault(x => x.Name.StartsWith(optionName));
- OptionsToInclude.Add(CreateOptionFromType(optionType));
- }
-
- private IOptions CreateOptionFromType(Type optionType)
- {
- IOptions instanceOfOption = (IOptions)Activator.CreateInstance(optionType);
- var section = configuration.GetSection(instanceOfOption.ConfigurationMetadata.PathToInstance);
- section.Bind(instanceOfOption);
- return instanceOfOption;
- }
-
- public void AddOption(IOptions option, string key)
- {
- NamedOptionsToInclude.Add(key, option);
- }
-
- public void AddOption(string optionName, string key)
- {
- optionName = optionName.Replace("Options", "").Replace("Config", "");
- var optionType = catalogue.FirstOrDefault(x => x.Name.StartsWith(optionName));
- NamedOptionsToInclude.Add(key, CreateOptionFromType(optionType));
- }
-
- public string Build()
- {
- JObject configJson = new JObject();
- foreach (var item in OptionsToInclude)
- {
- configJson = AddOptionToConfig(configuration, configJson, item);
- }
- foreach (var item in NamedOptionsToInclude)
- {
- configJson = AddNamedOptionToConfig(configuration, configJson, item.Key, item.Value);
- }
- return configJson.ToString(Newtonsoft.Json.Formatting.Indented);
- }
-
- private JObject AddNamedOptionToConfig(IConfiguration configuration, JObject configJson, string key, IOptions option)
- {
- try
- {
- var hardPath = $"MigrationTools:Endpoints:{key}";
- configJson = Options.OptionsManager.AddOptionsToConfiguration(configJson, option, hardPath, true);
- logger.LogInformation("Adding Option: {item}", option.GetType().Name);
- }
- catch (Exception)
- {
-
- logger.LogInformation("FAILED!! Adding Option: {item}", option.GetType().FullName);
- }
-
- return configJson;
- }
-
- private JObject AddOptionToConfig(IConfiguration configuration, JObject configJson, IOptions option)
- {
- try
- {
- configJson = Options.OptionsManager.AddOptionsToConfiguration(configJson, option, false);
- logger.LogInformation("Adding Option: {item}", option.GetType().Name);
- }
- catch (Exception)
- {
-
- logger.LogInformation("FAILED!! Adding Option: {item}", option.GetType().FullName);
- }
-
- return configJson;
- }
- }
-}
diff --git a/src/MigrationTools/Options/OptionsConfigurationBuilder.cs b/src/MigrationTools/Options/OptionsConfigurationBuilder.cs
new file mode 100644
index 000000000..ea393dbce
--- /dev/null
+++ b/src/MigrationTools/Options/OptionsConfigurationBuilder.cs
@@ -0,0 +1,206 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Elmah.Io.Client;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using Microsoft.VisualStudio.Services.Audit;
+using Microsoft.VisualStudio.Services.Common.CommandLine;
+using MigrationTools.EndpointEnrichers;
+using MigrationTools.Endpoints.Infrastructure;
+using MigrationTools.Enrichers;
+using Newtonsoft.Json.Linq;
+using Serilog.Core;
+
+namespace MigrationTools.Options
+{
+ public class OptionsConfigurationBuilder
+ {
+ readonly ILogger logger;
+ readonly IConfiguration configuration;
+
+ private List OptionsToInclude { get; }
+ private Dictionary NamedOptionsToInclude { get; }
+
+ private List catalogue;
+
+ public OptionsConfigurationBuilder(
+ IConfiguration configuration,
+ ILogger logger,
+ ITelemetryLogger telemetryLogger)
+ {
+ this.configuration = configuration;
+ this.logger = logger;
+ OptionsToInclude = new List();
+ NamedOptionsToInclude = new Dictionary();
+ catalogue = AppDomain.CurrentDomain.GetMigrationToolsTypes().WithInterface().ToList();
+ }
+
+ public void AddAllOptions()
+ {
+ var keyGen = new KeyGenerator();
+
+ foreach (var optionType in catalogue)
+ {
+ switch (optionType)
+ {
+ case Type t when typeof(IEndpointOptions).IsAssignableFrom(t):
+ AddOption(optionType.Name, keyGen.GetNextKey());
+ break;
+ case Type t when typeof(IProcessorEnricherOptions).IsAssignableFrom(t):
+ logger.LogInformation("Skipping ProcessorEnricherOptions: {optionType}", optionType.Name);
+ break;
+ case Type t when typeof(IEndpointEnricherOptions).IsAssignableFrom(t):
+ logger.LogInformation("Skipping ProcessorEnricherOptions: {optionType}", optionType.Name);
+ break;
+ default:
+ AddOption(optionType.Name);
+ break;
+ }
+ }
+ }
+
+ public void AddOption(IOptions option)
+ {
+ OptionsToInclude.Add(option);
+ }
+
+ public void AddOption(string optionName)
+ {
+ optionName = optionName.Replace("Options", "");
+ var optionType = catalogue.FirstOrDefault(x => x.Name.StartsWith(optionName));
+ if (optionType == null)
+ {
+ logger.LogWarning("Could not find option type for {optionName}", optionName);
+ } else
+ {
+ logger.LogInformation("Adding {optionName}", optionName);
+ OptionsToInclude.Add(CreateOptionFromType(optionType));
+ }
+
+ }
+
+ private IOptions CreateOptionFromType(Type optionType)
+ {
+ IOptions instanceOfOption = (IOptions)Activator.CreateInstance(optionType);
+ var section = configuration.GetSection(instanceOfOption.ConfigurationMetadata.PathToSample);
+ section.Bind(instanceOfOption);
+ return instanceOfOption;
+ }
+
+ public void AddOption(IOptions option, string key)
+ {
+ NamedOptionsToInclude.Add(key, option);
+ }
+
+ public void AddOption(string optionName, string key)
+ {
+ optionName = optionName.Replace("Options", "");
+ var optionType = catalogue.FirstOrDefault(x => x.Name.StartsWith(optionName));
+ if (optionType == null)
+ {
+ logger.LogWarning("Could not find option type for {optionName}", optionName);
+ }
+ else
+ {
+ logger.LogInformation("Adding {optionName} as {key}", optionName, key);
+ NamedOptionsToInclude.Add(key, CreateOptionFromType(optionType));
+ }
+ }
+
+ public string Build()
+ {
+ logger.LogInformation("Building Configuration");
+ JObject configJson = new JObject();
+ configJson["MigrationTools"] = new JObject();
+ configJson["MigrationTools"]["Endpoints"] = new JObject();
+ configJson["MigrationTools"]["Processors"] = new JArray();
+ configJson["MigrationTools"]["CommonTools"] = new JObject();
+ // Add the version element
+ AddSerilog(configJson);
+ AddVersionInfo(configJson);
+ foreach (var item in OptionsToInclude)
+ {
+ configJson = AddOptionToConfig(configuration, configJson, item);
+ }
+ foreach (var item in NamedOptionsToInclude)
+ {
+ configJson = AddNamedOptionToConfig(configuration, configJson, item.Key, item.Value);
+ }
+ return configJson.ToString(Newtonsoft.Json.Formatting.Indented);
+ }
+
+ private static void AddSerilog(JObject configJson)
+ {
+ configJson["Serilog"] = new JObject();
+ configJson["Serilog"]["MinimumLevel"] = $"Information";
+ }
+
+ private static void AddVersionInfo(JObject configJson)
+ {
+ var version = Assembly.GetExecutingAssembly().GetName().Version;
+ configJson["MigrationTools"]["Version"] = $"{version.Major}.{version.Minor}";
+ }
+
+ private JObject AddNamedOptionToConfig(IConfiguration configuration, JObject configJson, string key, IOptions option)
+ {
+ if (option.ConfigurationMetadata.PathToInstance == null)
+ {
+ logger.LogWarning("Skipping Option: {item} with {key} as it has no PathToInstance", option.GetType().Name, key);
+ return configJson;
+ }
+ try
+ {
+ var hardPath = $"MigrationTools:Endpoints:{key}";
+ logger.LogInformation("Building Option: {item} to {hardPath}", option.GetType().Name, hardPath);
+ configJson = Options.OptionsManager.AddOptionsToConfiguration(configJson, option, hardPath, true);
+
+ }
+ catch (Exception)
+ {
+
+ logger.LogWarning("FAILED!! Adding Option: {item}", option.GetType().FullName);
+ }
+
+ return configJson;
+ }
+
+ private JObject AddOptionToConfig(IConfiguration configuration, JObject configJson, IOptions option)
+ {
+ if (option.ConfigurationMetadata.PathToInstance == null)
+ {
+ logger.LogWarning("Skipping Option: {item} as it has no PathToInstance", option.GetType().Name);
+ return configJson;
+ }
+ try
+ {
+ logger.LogInformation("Building Option: {item} to {path}", option.GetType().Name, option.ConfigurationMetadata.PathToInstance);
+ configJson = Options.OptionsManager.AddOptionsToConfiguration(configJson, option, false);
+
+ }
+ catch (Exception)
+ {
+
+ logger.LogWarning("FAILED!! Adding Option: {item}", option.GetType().FullName);
+ }
+
+ return configJson;
+ }
+
+
+ }
+
+ public class KeyGenerator
+ {
+ private int _counter = 1;
+
+ public string GetNextKey()
+ {
+ _counter++;
+ return $"Key{_counter}";
+ }
+ }
+}
diff --git a/src/MigrationTools/ServiceCollectionExtensions.cs b/src/MigrationTools/ServiceCollectionExtensions.cs
index b2bde4857..47e16bb0a 100644
--- a/src/MigrationTools/ServiceCollectionExtensions.cs
+++ b/src/MigrationTools/ServiceCollectionExtensions.cs
@@ -28,6 +28,7 @@ public static OptionsBuilder AddMigrationToolsOptions(this I
public static void AddMigrationToolServices(this IServiceCollection context, IConfiguration configuration, string configFile = "configuration.json")
{
+ context.AddSingleton();
context.AddConfiguredEndpoints(configuration);
//Containers
context.AddTransient();