in src/prod/src/managed/ImageBuilderExe/ImageBuilderExe.cs [102:606]
public static int Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("This is for internal use only");
return -1;
}
#if DEBUG
// To add a sleep time while debugging add a "Sleep" key (in milliseconds) to the following registry location: HKLM\\Software\\Microsoft\\Service Fabric
try
{
using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(FabricConstants.FabricRegistryKeyPath, true))
{
var sleepRegVal = registryKey.GetValue("Sleep");
if (sleepRegVal != null)
{
int sleepinms = int.Parse(sleepRegVal.ToString());
ImageBuilderExe.TraceSource.WriteNoise(ImageBuilderExe.TraceType, "ImageBuilderExe: Sleep time requested: {0}", sleepinms.ToString());
Thread.Sleep(sleepinms);
}
}
}
catch (Exception e)
{
ImageBuilderExe.TraceSource.WriteNoise(ImageBuilderExe.TraceType, "ImageBuilderExe: Exception code:{0}, msg:{1} when attempting to read registry value \"Sleep\" in {2}.", e.HResult, e.Message, FabricConstants.FabricRegistryKeyPath);
}
#endif
// Parameters
// /schemaPath:<The xsd schema file of Windows Fabric ServiceModel> - optional. Default: <Current Working Directory>\ServiceFabricServiceModel.xsd
// /workingDir:<The root of working directory of the node> - optional. Default: <Current Working Directory>
// /storeRoot:<The root path of ImageStore> - optional
// /output: <The root folder|file where output will be placed> - required
// /input: <The root folder|file where input will be read from> - required for Delete
// /progress: <The file where operation progress will be read from> - optional. Used by BuildApplicationType and DownloadAndBuildApplicationType.
// /operation:<BuildApplicationTypeInfo | BuildApplicationType | BuildApplication | BuildComposeDeployment | ValidateComposeDeployment | UpgradeApplication | GetFabricVersion | ProvisionFabric | UpgradeFabric | Delete | TestErrorDetails | DownloadAndBuildApplicationType> - required
// /timeout:<ticks> - optional
/* ImageBuilder arguments for DownloadAndBuildApplicationType */
// /downloadPath: <path to .sfpkg file from a store that supports GET method> - required
// /appTypeName:<Application Type Name> - required. Expected application type name in the downloaded package.
// /appTypeVersion:<Application Type Version> - required. Expected application type version in the downloaded package.
// /progress: <The file where operation progress will be read from> - optional.
// /output: <The root folder|file where output will be placed> - required
// /timeout:<ticks> - optional
/* ImageBuilder arguments for BuildComposeDeployment */
// /cf:<Compose File path> - required
// /of:<Overrides File path> - optional
// /appTypeName:<Application Type Name> - required
// /appTypeVersion:<Application Type Version> - required
// /output: <The root folder|file where output application package will be placed> - required
// /ocf:<Output Merged compose file path> - required
// /repoUserName:<Repository User Name> - optional
// /repoPwd:<Repository Password> - optional
// /pwdEncrypted:<Is Repository Password encrypted> - optional
// /cleanup:<Cleanup the compose files> - optional
// /timeout:<ticks> - optional
/* ImageBuilder arguments for ValidateComposeDeployment */
// /cf:<Compose File path> - required
// /of:<Overrides File path> - optional
// /appTypeName:<Application Type Name> - optional
// /appTypeVersion:<Application Type Version> - optional
// /cleanup:<Cleanup the compose files> - optional
// /timeout:<ticks> - optional
/* ImageBuilder arguments for Application */
// /appTypeName:<Application Type Name> - required for BuildApplication and UpgradeApplication operation
// /appTypeVersion:<Application Type Version> - required for BuildApplication and UpgradeApplication operation
// /appId:<Application ID> - required for BuildApplication and UpgradeApplication operation
// /nameUri:<Name URI> - required for BuildApplication operation
// /appParam:<semi-colon separated key-value pair>. Multiple such parameters can be passed. Key cannot have ';'.
// /buildPath: <The root folder of build layout> - required for ApplicationTypeInfo and BuildApplicationType operation
// /currentAppInstanceVersion: <The current app instance of the Application that needs to be upgraded> - required for UpgradeApplication operation
/* ImageBuilder arguments for Fabric Upgrade */
// /codePath: <The path to MSP for FabricUpgrade>
// /configPath: <The path to ClusterManifest for FabricUpgrade>
// /currentFabricVersion: <The current FabricVersion>
// /targetFabricVersion: <The target FabricVersion>
// /im: <Path to InfrastructureManifest.xml file>
//
Dictionary<string, string> commandArgs = null;
Exception exception = null;
string errorDetailsFile = null;
try
{
commandArgs = ParseParameters(args);
// Ensure that required parameters are present
EnsureRequiredCommandLineParameters(commandArgs);
Dictionary<string, string> applicationParameters = ParseAppParameters(commandArgs);
errorDetailsFile = commandArgs.ContainsKey(StringConstants.ErrorDetails)
? commandArgs[StringConstants.ErrorDetails]
: null;
string workingDirectory = commandArgs.ContainsKey(StringConstants.WorkingDir)
? commandArgs[StringConstants.WorkingDir]
: Directory.GetCurrentDirectory();
string imageStoreConnectionString;
if (commandArgs.ContainsKey(StringConstants.StoreRoot))
{
imageStoreConnectionString = commandArgs[StringConstants.StoreRoot];
}
else
{
ImageBuilderExe.TraceSource.WriteInfo(ImageBuilderExe.TraceType, "Loading ImageStoreConnectionString from config.");
bool isEncrypted;
NativeConfigStore configStore = NativeConfigStore.FabricGetConfigStore();
var configValue = configStore.ReadString("Management", "ImageStoreConnectionString", out isEncrypted);
if (isEncrypted)
{
var secureString = NativeConfigStore.DecryptText(configValue);
var secureCharArray = FabricValidatorUtility.SecureStringToCharArray(secureString);
imageStoreConnectionString = new string(secureCharArray);
}
else
{
imageStoreConnectionString = configValue;
}
if (string.IsNullOrEmpty(imageStoreConnectionString))
{
throw new ArgumentException(StringResources.Error_MissingImageStoreConnectionStringInManifest);
}
}
StringBuilder stringToTrace = new StringBuilder();
foreach (var commandArg in commandArgs)
{
// Skipping tracing StoreRoot since it could be a secret value
if (!ImageBuilderUtility.Equals(commandArg.Key, StringConstants.StoreRoot))
{
stringToTrace.AppendFormat("{0}:{1}", commandArg.Key, commandArg.Value);
stringToTrace.AppendLine();
}
}
ImageBuilderExe.TraceSource.WriteInfo(
ImageBuilderExe.TraceType,
"ImageBuilderExe called with - {0}",
stringToTrace.ToString());
string currentExecutingDirectory = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
string schemaPath = commandArgs.ContainsKey(StringConstants.SchemaPath)
? commandArgs[StringConstants.SchemaPath]
: Path.Combine(
currentExecutingDirectory,
StringConstants.DefaultSchemaPath);
TimeSpan timeout = commandArgs.ContainsKey(StringConstants.Timeout)
? TimeSpan.FromTicks(long.Parse(commandArgs[StringConstants.Timeout]))
: TimeSpan.MaxValue;
Timer timer = null;
if (timeout != TimeSpan.MaxValue)
{
ImageBuilderExe.TraceSource.WriteInfo(
ImageBuilderExe.TraceType,
"ImageBuilderExe enabled timeout monitor: {0}",
timeout);
timer = new Timer(OnTimeout, errorDetailsFile, timeout, TimeSpan.FromMilliseconds(-1));
}
IImageStore imageStore = ImageStoreFactoryProxy.CreateImageStore(
imageStoreConnectionString,
null,
workingDirectory,
true /*isInternal*/);
ImageBuilder imageBuilder = new ImageBuilder(imageStore, schemaPath, workingDirectory);
string operationValue = commandArgs[StringConstants.Operation];
bool sfVolumeDiskServiceEnabled = commandArgs.ContainsKey(StringConstants.SFVolumeDiskServiceEnabled)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.SFVolumeDiskServiceEnabled])
: false;
imageBuilder.IsSFVolumeDiskServiceEnabled = sfVolumeDiskServiceEnabled;
if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationDownloadAndBuildApplicationType))
{
string progressFile = commandArgs.ContainsKey(StringConstants.Progress) ? commandArgs[StringConstants.Progress] : null;
bool shouldSkipChecksumValidation = commandArgs.ContainsKey(StringConstants.DisableChecksumValidation) ? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.DisableChecksumValidation]) : false;
imageBuilder.DownloadAndBuildApplicationType(
commandArgs[StringConstants.DownloadPath],
commandArgs[StringConstants.AppTypeName],
commandArgs[StringConstants.AppTypeVersion],
commandArgs[StringConstants.Output],
timeout,
progressFile,
shouldSkipChecksumValidation);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildApplicationTypeInfo))
{
imageBuilder.GetApplicationTypeInfo(commandArgs[StringConstants.BuildPath], timeout, commandArgs[StringConstants.Output]);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildApplicationType))
{
string outputFile = commandArgs.ContainsKey(StringConstants.Output) ? commandArgs[StringConstants.Output] : null;
string progressFile = commandArgs.ContainsKey(StringConstants.Progress) ? commandArgs[StringConstants.Progress] : null;
bool shouldSkipChecksumValidation = commandArgs.ContainsKey(StringConstants.DisableChecksumValidation) ? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.DisableChecksumValidation]) : false;
bool shouldSkipServerSideCopy = commandArgs.ContainsKey(StringConstants.DisableServerSideCopy) ? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.DisableServerSideCopy]) : false;
imageBuilder.BuildApplicationType(commandArgs[StringConstants.BuildPath], timeout, outputFile, progressFile, shouldSkipChecksumValidation, shouldSkipServerSideCopy);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildSingleInstanceApplication))
{
bool generateDnsNames = commandArgs.ContainsKey(StringConstants.GenerateDnsNames)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.GenerateDnsNames])
: false;
bool useOpenNetworkConfig = commandArgs.ContainsKey(StringConstants.UseOpenNetworkConfig)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.UseOpenNetworkConfig])
: false;
bool useLocalNatNetworkConfig = commandArgs.ContainsKey(StringConstants.UseLocalNatNetworkConfig)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.UseLocalNatNetworkConfig])
: false;
Application application = null;
using (StreamReader file = File.OpenText(commandArgs[StringConstants.SingleInstanceApplicationDescription]))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new DiagnosticsSinkJsonConverter());
serializer.Converters.Add(new VolumeMountJsonConverter());
application =
(Application)serializer.Deserialize(file, typeof(Application));
}
GenerationConfig config = null;
if (commandArgs.ContainsKey(StringConstants.GenerationConfig))
{
using (StreamReader file = File.OpenText(commandArgs[StringConstants.GenerationConfig]))
{
JsonSerializer serializer = new JsonSerializer();
config =
(GenerationConfig)serializer.Deserialize(file, typeof(GenerationConfig));
}
}
imageBuilder.BuildSingleInstanceApplication(
application,
commandArgs[StringConstants.AppTypeName],
commandArgs[StringConstants.AppTypeVersion],
commandArgs[StringConstants.AppId],
new Uri(commandArgs[StringConstants.AppName]),
generateDnsNames,
timeout,
commandArgs[StringConstants.BuildPath],
commandArgs[StringConstants.Output],
useOpenNetworkConfig,
useLocalNatNetworkConfig,
commandArgs[StringConstants.MountPointForSettings],
config);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildSingleInstanceApplicationForUpgrade))
{
bool generateDnsNames = commandArgs.ContainsKey(StringConstants.GenerateDnsNames)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.GenerateDnsNames])
: false;
bool useOpenNetworkConfig = commandArgs.ContainsKey(StringConstants.UseOpenNetworkConfig)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.UseOpenNetworkConfig])
: false;
bool useLocalNatNetworkConfig = commandArgs.ContainsKey(StringConstants.UseLocalNatNetworkConfig)
? ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.UseLocalNatNetworkConfig])
: false;
Application application = null;
using (StreamReader file = File.OpenText(commandArgs[StringConstants.SingleInstanceApplicationDescription]))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new VolumeMountJsonConverter());
application =
(Application)serializer.Deserialize(file, typeof(Application));
}
GenerationConfig config = null;
if (commandArgs.ContainsKey(StringConstants.GenerationConfig))
{
using (StreamReader file = File.OpenText(commandArgs[StringConstants.GenerationConfig]))
{
JsonSerializer serializer = new JsonSerializer();
config =
(GenerationConfig)serializer.Deserialize(file, typeof(GenerationConfig));
}
}
imageBuilder.BuildSingleInstanceApplicationForUpgrade(
application,
commandArgs[StringConstants.AppTypeName],
commandArgs[StringConstants.CurrentAppTypeVersion],
commandArgs[StringConstants.TargetAppTypeVersion],
commandArgs[StringConstants.AppId],
int.Parse(commandArgs[StringConstants.CurrentAppInstanceVersion], CultureInfo.InvariantCulture),
new Uri(commandArgs[StringConstants.AppName]),
generateDnsNames,
timeout,
commandArgs[StringConstants.BuildPath],
commandArgs[StringConstants.Output],
useOpenNetworkConfig,
useLocalNatNetworkConfig,
commandArgs[StringConstants.MountPointForSettings],
config);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildApplication))
{
imageBuilder.BuildApplication(
commandArgs[StringConstants.AppTypeName],
commandArgs[StringConstants.AppTypeVersion],
commandArgs[StringConstants.AppId],
new Uri(commandArgs[StringConstants.NameUri]),
applicationParameters,
timeout,
commandArgs[StringConstants.Output]);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationUpgradeApplication))
{
imageBuilder.UpgradeApplication(
commandArgs[StringConstants.AppId],
commandArgs[StringConstants.AppTypeName],
int.Parse(commandArgs[StringConstants.CurrentAppInstanceVersion], CultureInfo.InvariantCulture),
commandArgs[StringConstants.AppTypeVersion],
applicationParameters,
timeout,
commandArgs[StringConstants.Output]);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationDelete))
{
imageBuilder.Delete(commandArgs[StringConstants.Input], timeout);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationCleanupApplicationPackage))
{
imageBuilder.DeleteApplicationPackage(commandArgs[StringConstants.BuildPath], timeout);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationGetFabricVersion))
{
imageBuilder.GetFabricVersionInfo(
commandArgs[StringConstants.CodePath],
commandArgs[StringConstants.ConfigPath],
timeout,
commandArgs[StringConstants.Output]);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationProvisionFabric))
{
string configurationCsvFilePath = Path.Combine(currentExecutingDirectory, StringConstants.ConfigurationsFileName);
imageBuilder.ProvisionFabric(
commandArgs[StringConstants.CodePath],
commandArgs[StringConstants.ConfigPath],
configurationCsvFilePath,
commandArgs[StringConstants.InfrastructureManifestFile],
timeout);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationGetClusterManifest))
{
imageBuilder.GetClusterManifestContents(
commandArgs[StringConstants.ConfigVersion],
commandArgs[StringConstants.Output],
timeout);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationUpgradeFabric))
{
string configurationCsvFilePath = Path.Combine(currentExecutingDirectory, StringConstants.ConfigurationsFileName);
imageBuilder.UpgradeFabric(
commandArgs[StringConstants.CurrentFabricVersion],
commandArgs[StringConstants.TargetFabricVersion],
configurationCsvFilePath,
timeout,
commandArgs[StringConstants.Output]);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationGetManifests))
{
imageBuilder.GetManifests(commandArgs[StringConstants.Input], timeout);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationValidateComposeDeployment))
{
bool cleanupComposeFiles = commandArgs.ContainsKey(StringConstants.CleanupComposeFiles) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.CleanupComposeFiles]);
HashSet<string> ignoredKeys;
imageBuilder.ValidateComposeDeployment(
commandArgs[StringConstants.ComposeFilePath],
commandArgs.ContainsKey(StringConstants.OverrideFilePath) ? commandArgs[StringConstants.OverrideFilePath] : null,
commandArgs.ContainsKey(StringConstants.AppName) ? commandArgs[StringConstants.AppName] : null,
commandArgs.ContainsKey(StringConstants.AppTypeName) ? commandArgs[StringConstants.AppTypeName] : null,
commandArgs.ContainsKey(StringConstants.AppTypeVersion) ? commandArgs[StringConstants.AppTypeVersion] : null,
timeout,
out ignoredKeys,
cleanupComposeFiles);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildComposeDeployment))
{
bool cleanupComposeFiles = commandArgs.ContainsKey(StringConstants.CleanupComposeFiles) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.CleanupComposeFiles]);
bool shouldSkipChecksumValidation = commandArgs.ContainsKey(StringConstants.DisableChecksumValidation) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.DisableChecksumValidation]);
bool isPasswordEncrypted = commandArgs.ContainsKey(StringConstants.IsRepositoryPasswordEncrypted) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.IsRepositoryPasswordEncrypted]);
bool generateDnsNames = commandArgs.ContainsKey(StringConstants.GenerateDnsNames) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.GenerateDnsNames]);
imageBuilder.BuildComposeDeploymentPackage(
commandArgs[StringConstants.ComposeFilePath],
commandArgs.ContainsKey(StringConstants.OverrideFilePath) ? commandArgs[StringConstants.OverrideFilePath] : null,
timeout,
commandArgs.ContainsKey(StringConstants.AppName) ? commandArgs[StringConstants.AppName] : null,
commandArgs[StringConstants.AppTypeName],
commandArgs[StringConstants.AppTypeVersion],
commandArgs.ContainsKey(StringConstants.RepositoryUserName) ? commandArgs[StringConstants.RepositoryUserName] : null,
commandArgs.ContainsKey(StringConstants.RepositoryPassword) ? commandArgs[StringConstants.RepositoryPassword] : null,
isPasswordEncrypted,
generateDnsNames,
commandArgs[StringConstants.OutputComposeFilePath],
commandArgs[StringConstants.Output],
cleanupComposeFiles,
shouldSkipChecksumValidation);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.OperationBuildComposeApplicationForUpgrade))
{
bool cleanupComposeFiles = commandArgs.ContainsKey(StringConstants.CleanupComposeFiles) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.CleanupComposeFiles]);
bool shouldSkipChecksumValidation = commandArgs.ContainsKey(StringConstants.DisableChecksumValidation) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.DisableChecksumValidation]);
bool isPasswordEncrypted = commandArgs.ContainsKey(StringConstants.IsRepositoryPasswordEncrypted) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.IsRepositoryPasswordEncrypted]);
bool generateDnsNames = commandArgs.ContainsKey(StringConstants.GenerateDnsNames) && ImageBuilderUtility.ConvertString<bool>(commandArgs[StringConstants.GenerateDnsNames]);
imageBuilder.BuildComposeDeploymentPackageForUpgrade(
commandArgs[StringConstants.ComposeFilePath],
commandArgs.ContainsKey(StringConstants.OverrideFilePath) ? commandArgs[StringConstants.OverrideFilePath] : null,
timeout,
commandArgs.ContainsKey(StringConstants.AppName) ? commandArgs[StringConstants.AppName] : null,
commandArgs[StringConstants.AppTypeName],
commandArgs[StringConstants.CurrentAppTypeVersion],
commandArgs[StringConstants.TargetAppTypeVersion],
commandArgs.ContainsKey(StringConstants.RepositoryUserName) ? commandArgs[StringConstants.RepositoryUserName] : null,
commandArgs.ContainsKey(StringConstants.RepositoryPassword) ? commandArgs[StringConstants.RepositoryPassword] : null,
isPasswordEncrypted,
generateDnsNames,
commandArgs[StringConstants.OutputComposeFilePath],
commandArgs[StringConstants.Output],
cleanupComposeFiles,
shouldSkipChecksumValidation);
}
else if (ImageBuilderUtility.Equals(operationValue, StringConstants.TestErrorDetails))
{
throw new Exception(StringConstants.TestErrorDetails);
}
else
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
StringResources.Error_ImageBuilderExeCommandLineInvalidOperation,
StringConstants.Operation,
operationValue));
}
}
catch (AggregateException ae)
{
exception = ae.InnerException;
StringBuilder exceptionStringBuilder = new StringBuilder("Aggregate exception has ");
exceptionStringBuilder.Append(ae.InnerExceptions.Count);
exceptionStringBuilder.Append(" exceptions. ");
ae.InnerExceptions.ForEach(innerException => exceptionStringBuilder.AppendLine(innerException.Message));
ImageBuilderExe.TraceSource.WriteWarning(
ImageBuilderExe.TraceType,
"AggregateException: {0}",
exceptionStringBuilder.ToString());
}
catch (Exception e)
{
exception = e;
}
if (exception != null)
{
OnFailure(exception, errorDetailsFile);
return unchecked((int)NativeTypes.FABRIC_ERROR_CODE.FABRIC_E_IMAGEBUILDER_UNEXPECTED_ERROR);
}
else
{
ImageBuilderExe.TraceSource.WriteInfo(
ImageBuilderExe.TraceType,
"ImageBuilderExe operation completed successfully.");
return 0;
}
}