Guard Checkmk service renames during updates
This commit is contained in:
@@ -27,7 +27,13 @@ namespace BizTalkCheckmkPulse.Setup
|
||||
checkmkLocalDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "checkmk", "agent", "local");
|
||||
}
|
||||
|
||||
public void Install(string account, string password, bool isGmsa, string environmentName, Action<string> report)
|
||||
public void Install(
|
||||
string account,
|
||||
string password,
|
||||
bool isGmsa,
|
||||
string environmentName,
|
||||
bool allowServiceNameChange,
|
||||
Action<string> report)
|
||||
{
|
||||
Validate(account, password, isGmsa, environmentName);
|
||||
report = report ?? delegate { };
|
||||
@@ -72,9 +78,21 @@ namespace BizTalkCheckmkPulse.Setup
|
||||
stagedConfig,
|
||||
File.Exists(targetConfig) ? targetConfig : null,
|
||||
environmentName);
|
||||
RunSelfTest(stagedExe);
|
||||
var stagedServiceNames = RunSelfTest(stagedExe);
|
||||
report("Update-Staging validiert. Umgebung=" + (effectiveEnvironment.Length == 0 ? "(keine)" : effectiveEnvironment) + ".");
|
||||
|
||||
if (File.Exists(targetExe))
|
||||
{
|
||||
var installedServiceNames = RunSelfTest(targetExe);
|
||||
var serviceNameChange = EnsureServiceNameCompatibility(
|
||||
installedServiceNames,
|
||||
stagedServiceNames,
|
||||
allowServiceNameChange);
|
||||
report(serviceNameChange.Length == 0
|
||||
? "Checkmk-Servicevertrag unveraendert: keine Service Discovery erforderlich."
|
||||
: "Checkmk-Service-Rename ausdruecklich bestaetigt; Service Discovery erforderlich. " + serviceNameChange);
|
||||
}
|
||||
|
||||
// Erst nach vollstaendiger Staging-Pruefung wird der laufende Provider angehalten.
|
||||
scheduler.DeleteIfExists(TaskName);
|
||||
taskRemoved = true;
|
||||
@@ -397,7 +415,7 @@ namespace BizTalkCheckmkPulse.Setup
|
||||
new DirectoryInfo(path).SetAccessControl(security);
|
||||
}
|
||||
|
||||
private static void RunSelfTest(string executable)
|
||||
private static IReadOnlyList<string> RunSelfTest(string executable)
|
||||
{
|
||||
var start = new ProcessStartInfo(executable, "--self-test")
|
||||
{
|
||||
@@ -419,7 +437,45 @@ namespace BizTalkCheckmkPulse.Setup
|
||||
var lines = output.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (process.ExitCode != 0 || lines.Length != 9 || lines.Any(x => !x.StartsWith("0 ", StringComparison.Ordinal)))
|
||||
throw new InvalidOperationException("Self-Test fehlgeschlagen. Exitcode=" + process.ExitCode + ", Zeilen=" + lines.Length + ". " + error);
|
||||
|
||||
var serviceNames = lines.Select(ExtractServiceName).ToArray();
|
||||
if (serviceNames.Distinct(StringComparer.Ordinal).Count() != serviceNames.Length)
|
||||
throw new InvalidOperationException("Self-Test fehlgeschlagen: Checkmk-Servicenamen sind nicht eindeutig.");
|
||||
return serviceNames;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ExtractServiceName(string line)
|
||||
{
|
||||
var firstQuote = line.IndexOf('"');
|
||||
var secondQuote = firstQuote < 0 ? -1 : line.IndexOf('"', firstQuote + 1);
|
||||
if (firstQuote < 0 || secondQuote <= firstQuote + 1)
|
||||
throw new InvalidOperationException("Self-Test fehlgeschlagen: Checkmk-Servicename kann nicht gelesen werden: " + line);
|
||||
return line.Substring(firstQuote + 1, secondQuote - firstQuote - 1);
|
||||
}
|
||||
|
||||
internal static string EnsureServiceNameCompatibility(
|
||||
IEnumerable<string> installedServiceNames,
|
||||
IEnumerable<string> stagedServiceNames,
|
||||
bool allowServiceNameChange)
|
||||
{
|
||||
var installed = new HashSet<string>(installedServiceNames ?? Enumerable.Empty<string>(), StringComparer.Ordinal);
|
||||
var staged = new HashSet<string>(stagedServiceNames ?? Enumerable.Empty<string>(), StringComparer.Ordinal);
|
||||
if (installed.SetEquals(staged)) return string.Empty;
|
||||
|
||||
var removed = installed.Except(staged, StringComparer.Ordinal).OrderBy(x => x, StringComparer.Ordinal).ToArray();
|
||||
var added = staged.Except(installed, StringComparer.Ordinal).OrderBy(x => x, StringComparer.Ordinal).ToArray();
|
||||
var description = "Entfernt=[" + string.Join(", ", removed) + "]; Neu=[" + string.Join(", ", added) + "].";
|
||||
if (!allowServiceNameChange)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Sicherheitsstopp: Das Update wuerde Checkmk-Servicenamen aendern. "
|
||||
+ description
|
||||
+ " Ohne Service Discovery entstehen verwaiste bzw. fehlende Services. "
|
||||
+ "Nur wenn die Aenderung beabsichtigt ist, im Setup 'Service Discovery ist eingeplant' bestaetigen und anschliessend die Discovery ausfuehren.");
|
||||
}
|
||||
|
||||
return description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user