using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace ServicesDAO.models { /// /// Estado observado de un objeto de Kubernetes (Service o Ingress) de un release. /// La escribe k8s_monitor_services por observación continua; nadie más la toca. /// /// /// El monitor sincroniza vía Upsert con conflict_fields compuestos /// ["ReleaseIdentificator", "K8sContext", "ResourceKind", "ResourceName"], que /// empatan con el índice único uk_service_endpoints_release. /// [Table("service_endpoints")] public class ServiceEndpoints { [Key] [Column("ServiceEndpointsID")] public long ServiceEndpointsID { get; set; } [Column("request_queue_id")] public long RequestQueueId { get; set; } [Column("k8s_context")] public string K8sContext { get; set; } [Column("namespace")] public string Namespace { get; set; } [Column("release_identificator")] public string ReleaseIdentificator { get; set; } /// 'Service' o 'Ingress'. [Column("resource_kind")] public string ResourceKind { get; set; } [Column("resource_name")] public string ResourceName { get; set; } /// Etiqueta app.kubernetes.io/component del objeto. Empata con service_connection_info.component. [Column("resource_role")] public string? ResourceRole { get; set; } /// LoadBalancer | ClusterIP | NodePort. Nulo en los Ingress. [Column("service_type")] public string? ServiceType { get; set; } [Column("external_ip")] public string? ExternalIp { get; set; } /// Incluye el literal 'None' en los Services headless. [Column("cluster_ip")] public string? ClusterIp { get; set; } [Column("hostname")] public string? Hostname { get; set; } /// /// Array JSON de los spec.ports del objeto, por ejemplo /// [{"name":"restAPI","port":9200,"targetPort":9200,"protocol":"TCP"}]. /// /// /// Debe escribirse como CADENA ya serializada, nunca como estructura anidada: /// ConvertValue del repositorio intenta Convert.ChangeType sobre el /// Dictionary/List que produce ProtoValueToObject, la excepción se captura en /// silencio y la columna quedaría en NULL con el Upsert reportando éxito. /// [Column("ports")] public string? Ports { get; set; } [Column("status_id")] public int? StatusId { get; set; } /// Última vez que se reconcilió contra el clúster. Distingue "es el estado actual" de "es lo último que se observó". [Column("synced_at")] public DateTime? SyncedAt { get; set; } [Column("created_at")] public DateTime CreatedAt { get; set; } [Column("updated_at")] public DateTime? UpdatedAt { get; set; } } }