236 lines
12 KiB
C#
236 lines
12 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace File_Folder_Helper.ADO2025.PI5;
|
|
|
|
internal static partial class Helper20250404 {
|
|
|
|
internal record KafkaProducerSaslOptions(
|
|
[property: JsonPropertyName("mechanism")] string Mechanism
|
|
);
|
|
|
|
internal record MonitorList(
|
|
[property: JsonPropertyName("id")] int Id,
|
|
[property: JsonPropertyName("name")] string Name,
|
|
[property: JsonPropertyName("description")] string Description,
|
|
[property: JsonPropertyName("pathName")] string PathName,
|
|
[property: JsonPropertyName("parent")] int? Parent,
|
|
[property: JsonPropertyName("childrenIDs")] IReadOnlyList<int> ChildrenIDs,
|
|
[property: JsonPropertyName("url")] string Url,
|
|
[property: JsonPropertyName("method")] string Method,
|
|
[property: JsonPropertyName("hostname")] object Hostname,
|
|
[property: JsonPropertyName("port")] object Port,
|
|
[property: JsonPropertyName("maxretries")] int MaxRetries,
|
|
[property: JsonPropertyName("weight")] int Weight,
|
|
[property: JsonPropertyName("active")] bool Active,
|
|
[property: JsonPropertyName("forceInactive")] bool ForceInactive,
|
|
[property: JsonPropertyName("type")] string Type,
|
|
[property: JsonPropertyName("timeout")] int Timeout,
|
|
[property: JsonPropertyName("interval")] int Interval,
|
|
[property: JsonPropertyName("retryInterval")] int RetryInterval,
|
|
[property: JsonPropertyName("resendInterval")] int ResendInterval,
|
|
[property: JsonPropertyName("keyword")] object Keyword,
|
|
[property: JsonPropertyName("invertKeyword")] bool InvertKeyword,
|
|
[property: JsonPropertyName("expiryNotification")] bool ExpiryNotification,
|
|
[property: JsonPropertyName("ignoreTls")] bool IgnoreTls,
|
|
[property: JsonPropertyName("upsideDown")] bool UpsideDown,
|
|
[property: JsonPropertyName("packetSize")] int PacketSize,
|
|
[property: JsonPropertyName("maxredirects")] int MaxRedirects,
|
|
[property: JsonPropertyName("accepted_statuscodes")] IReadOnlyList<string> AcceptedStatusCodes,
|
|
[property: JsonPropertyName("dns_resolve_type")] string DnsResolveType,
|
|
[property: JsonPropertyName("dns_resolve_server")] string DnsResolveServer,
|
|
[property: JsonPropertyName("dns_last_result")] object DnsLastResult,
|
|
[property: JsonPropertyName("docker_container")] string DockerContainer,
|
|
[property: JsonPropertyName("docker_host")] object DockerHost,
|
|
[property: JsonPropertyName("proxyId")] object ProxyId,
|
|
[property: JsonPropertyName("notificationIDList")] NotificationIDList NotificationIDList,
|
|
[property: JsonPropertyName("tags")] IReadOnlyList<object> Tags,
|
|
[property: JsonPropertyName("maintenance")] bool Maintenance,
|
|
[property: JsonPropertyName("mqttTopic")] string MqttTopic,
|
|
[property: JsonPropertyName("mqttSuccessMessage")] string MqttSuccessMessage,
|
|
[property: JsonPropertyName("databaseQuery")] object DatabaseQuery,
|
|
[property: JsonPropertyName("authMethod")] string AuthMethod,
|
|
[property: JsonPropertyName("grpcUrl")] object GrpcUrl,
|
|
[property: JsonPropertyName("grpcProtobuf")] object GrpcProtobuf,
|
|
[property: JsonPropertyName("grpcMethod")] object GrpcMethod,
|
|
[property: JsonPropertyName("grpcServiceName")] object GrpcServiceName,
|
|
[property: JsonPropertyName("grpcEnableTls")] bool GrpcEnableTls,
|
|
[property: JsonPropertyName("radiusCalledStationId")] object RadiusCalledStationId,
|
|
[property: JsonPropertyName("radiusCallingStationId")] object RadiusCallingStationId,
|
|
[property: JsonPropertyName("game")] object Game,
|
|
[property: JsonPropertyName("gamedigGivenPortOnly")] bool GameDigGivenPortOnly,
|
|
[property: JsonPropertyName("httpBodyEncoding")] string HttpBodyEncoding,
|
|
[property: JsonPropertyName("jsonPath")] object JsonPath,
|
|
[property: JsonPropertyName("expectedValue")] object ExpectedValue,
|
|
[property: JsonPropertyName("kafkaProducerTopic")] object KafkaProducerTopic,
|
|
[property: JsonPropertyName("kafkaProducerBrokers")] IReadOnlyList<object> KafkaProducerBrokers,
|
|
[property: JsonPropertyName("kafkaProducerSsl")] bool KafkaProducerSsl,
|
|
[property: JsonPropertyName("kafkaProducerAllowAutoTopicCreation")] bool KafkaProducerAllowAutoTopicCreation,
|
|
[property: JsonPropertyName("kafkaProducerMessage")] object KafkaProducerMessage,
|
|
[property: JsonPropertyName("screenshot")] object Screenshot,
|
|
[property: JsonPropertyName("headers")] object Headers,
|
|
[property: JsonPropertyName("body")] object Body,
|
|
[property: JsonPropertyName("grpcBody")] object GrpcBody,
|
|
[property: JsonPropertyName("grpcMetadata")] object GrpcMetadata,
|
|
[property: JsonPropertyName("basic_auth_user")] string BasicAuthUser,
|
|
[property: JsonPropertyName("basic_auth_pass")] string BasicAuthPass,
|
|
[property: JsonPropertyName("oauth_client_id")] object OauthClientId,
|
|
[property: JsonPropertyName("oauth_client_secret")] object OauthClientSecret,
|
|
[property: JsonPropertyName("oauth_token_url")] object OauthTokenUrl,
|
|
[property: JsonPropertyName("oauth_scopes")] object OauthScopes,
|
|
[property: JsonPropertyName("oauth_auth_method")] string OauthAuthMethod,
|
|
[property: JsonPropertyName("pushToken")] string PushToken,
|
|
[property: JsonPropertyName("databaseConnectionString")] string DatabaseConnectionString,
|
|
[property: JsonPropertyName("radiusUsername")] object RadiusUsername,
|
|
[property: JsonPropertyName("radiusPassword")] object RadiusPassword,
|
|
[property: JsonPropertyName("radiusSecret")] object RadiusSecret,
|
|
[property: JsonPropertyName("mqttUsername")] string MqttUsername,
|
|
[property: JsonPropertyName("mqttPassword")] string MqttPassword,
|
|
[property: JsonPropertyName("authWorkstation")] object AuthWorkstation,
|
|
[property: JsonPropertyName("authDomain")] object AuthDomain,
|
|
[property: JsonPropertyName("tlsCa")] object TlsCa,
|
|
[property: JsonPropertyName("tlsCert")] object TlsCert,
|
|
[property: JsonPropertyName("tlsKey")] object TlsKey,
|
|
[property: JsonPropertyName("kafkaProducerSaslOptions")] KafkaProducerSaslOptions KafkaProducerSaslOptions,
|
|
[property: JsonPropertyName("includeSensitiveData")] bool IncludeSensitiveData
|
|
);
|
|
|
|
internal record NotificationIDList(
|
|
[property: JsonPropertyName("4")] bool _4
|
|
);
|
|
|
|
internal record NotificationList(
|
|
[property: JsonPropertyName("id")] int Id,
|
|
[property: JsonPropertyName("name")] string Name,
|
|
[property: JsonPropertyName("active")] bool Active,
|
|
[property: JsonPropertyName("userId")] int UserId,
|
|
[property: JsonPropertyName("isDefault")] bool IsDefault,
|
|
[property: JsonPropertyName("config")] string Config
|
|
);
|
|
|
|
internal record Kuma(
|
|
[property: JsonPropertyName("version")] string Version,
|
|
[property: JsonPropertyName("notificationList")] IReadOnlyList<NotificationList> NotificationList,
|
|
[property: JsonPropertyName("monitorList")] IReadOnlyList<MonitorList> MonitorList
|
|
);
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
|
[JsonSerializable(typeof(Kuma))]
|
|
private partial class KumaCommonSourceGenerationContext : JsonSerializerContext {
|
|
}
|
|
|
|
internal static void KumaToGatus(ILogger<Worker> logger, List<string> args) {
|
|
string url = args[4];
|
|
string fileName = args[3];
|
|
string searchPattern = args[2];
|
|
ParseMetrics(logger, fileName, url);
|
|
string sourceDirectory = Path.GetFullPath(args[0]);
|
|
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
|
|
if (files.Length == 0)
|
|
logger.LogWarning("<{files}>(s)", files.Length);
|
|
else
|
|
KumaToGatus(files);
|
|
}
|
|
|
|
private static void ParseMetrics(ILogger<Worker> logger, string fileName, string url) {
|
|
FileStream fileStream = new(fileName, FileMode.Truncate);
|
|
HttpClient httpClient = new();
|
|
Task<Stream> streamTask = httpClient.GetStreamAsync(url);
|
|
streamTask.Wait();
|
|
Task task = streamTask.Result.CopyToAsync(fileStream);
|
|
task.Wait();
|
|
ParseMetrics(logger, fileStream);
|
|
fileStream.Dispose();
|
|
streamTask.Dispose();
|
|
httpClient.Dispose();
|
|
}
|
|
|
|
private static void ParseMetrics(ILogger<Worker> _, FileStream __) {
|
|
// Task<List<IMetric>> metrics = PrometheusMetricsParser.ParseAsync(fileStream);
|
|
// metrics.Wait();
|
|
// foreach (IMetric metric in metrics.Result) {
|
|
// if (metric is not Gauge gauge)
|
|
// continue;
|
|
// foreach (GaugeMeasurement gaugeMeasurement in gauge.Measurements) {
|
|
// if (string.IsNullOrEmpty(metric.Name))
|
|
// continue;
|
|
// foreach (KeyValuePair<string, string> keyValuePair in gaugeMeasurement.Labels) {
|
|
// logger.LogInformation("name:{name}; timestamp:{timestamp}; value:{value}; key-name:{key-name}; key-value:{key-value}",
|
|
// metric.Name,
|
|
// gaugeMeasurement.Timestamp,
|
|
// gaugeMeasurement.Value,
|
|
// keyValuePair.Key,
|
|
// keyValuePair.Value);
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
private static void KumaToGatus(string[] files) {
|
|
Kuma? kuma;
|
|
string json;
|
|
string checkFile;
|
|
foreach (string file in files) {
|
|
checkFile = file.ToLower().Replace('_', '-');
|
|
if (checkFile != file)
|
|
File.Move(file, checkFile);
|
|
json = File.ReadAllText(checkFile);
|
|
kuma = JsonSerializer.Deserialize(json, KumaCommonSourceGenerationContext.Default.Kuma);
|
|
if (kuma is null)
|
|
continue;
|
|
WriteGatus(checkFile, kuma);
|
|
}
|
|
}
|
|
|
|
private static void WriteGatus(string file, Kuma kuma) {
|
|
List<string> results = [
|
|
string.Empty,
|
|
$"# set GATUS_CONFIG_PATH=./{Path.GetFileName(file)}.yaml",
|
|
string.Empty,
|
|
"endpoints:"
|
|
];
|
|
string[] segments;
|
|
foreach (MonitorList monitorList in kuma.MonitorList) {
|
|
if (monitorList.Type is not "http" and not "postgres")
|
|
continue;
|
|
results.Add($" - name: {monitorList.Name}");
|
|
results.Add($" group: {monitorList.PathName.Split(' ')[0]}");
|
|
results.Add($" enabled: {monitorList.Active.ToString().ToLower()}");
|
|
results.Add($" interval: {monitorList.Interval}s");
|
|
if (monitorList.Type == "http") {
|
|
results.Add($" method: {monitorList.Method}");
|
|
results.Add($" url: \"{monitorList.Url}\"");
|
|
if (monitorList.AuthMethod == "basic") {
|
|
results.Add($" # user: \"{monitorList.BasicAuthUser}\"");
|
|
results.Add($" # password: \"{monitorList.BasicAuthPass}\"");
|
|
}
|
|
results.Add(" conditions:");
|
|
results.Add(" - \"[STATUS] < 300\"");
|
|
if (monitorList.Url.Contains("https"))
|
|
results.Add(" - \"[CERTIFICATE_EXPIRATION] > 48h\"");
|
|
results.Add($" - \"[RESPONSE_TIME] < {monitorList.Timeout}\"");
|
|
} else if (monitorList.Type == "postgres") {
|
|
segments = monitorList.DatabaseConnectionString.Split('@');
|
|
if (segments.Length != 2)
|
|
continue;
|
|
results.Add($" # connectionString: \"{monitorList.DatabaseConnectionString}\"");
|
|
results.Add($" url: \"tcp://{segments[1].Split('/')[0]}\"");
|
|
results.Add(" conditions:");
|
|
results.Add(" - \"[CONNECTED] == true\"");
|
|
} else
|
|
throw new NotImplementedException();
|
|
results.Add(" alerts:");
|
|
results.Add(" - type: email");
|
|
results.Add(" description: \"healthcheck failed\"");
|
|
results.Add(" send-on-resolved: true");
|
|
results.Add(" - type: gotify");
|
|
results.Add(" description: \"healthcheck failed\"");
|
|
results.Add(" send-on-resolved: true");
|
|
results.Add(string.Empty);
|
|
}
|
|
File.WriteAllText($"{file}.yaml", string.Join(Environment.NewLine, results));
|
|
}
|
|
|
|
} |