@@ -499,6 +499,9 @@ func NewUniversalPathologicalEventMatchers(kubeConfig *rest.Config, finalInterva
499499 newCrioReloadedTooOftenEventMatcher := newCrioReloadedTooOftenEventMatcher (finalIntervals )
500500 registry .AddPathologicalEventMatcherOrDie (newCrioReloadedTooOftenEventMatcher )
501501
502+ twoNodeEtcdEndpointsMatcher := newTwoNodeEtcdEndpointsConfigMissingEventMatcher (finalIntervals )
503+ registry .AddPathologicalEventMatcherOrDie (twoNodeEtcdEndpointsMatcher )
504+
502505 return registry
503506}
504507
@@ -715,6 +718,20 @@ var CertificateRotation = &SimplePathologicalEventMatcher{
715718 messageReasonRegex : regexp .MustCompile (`^(CABundleUpdateRequired|SignerUpdateRequired|TargetUpdateRequired|CertificateUpdated|CertificateRemoved|CertificateUpdateFailed|CSRCreated|CSRApproved|CertificateRotationStarted|ClientCertificateCreated|NoValidCertificateFound)$` ),
716719}
717720
721+ func newTwoNodeEtcdEndpointsConfigMissingEventMatcher (finalIntervals monitorapi.Intervals ) EventMatcher {
722+ // Use topology-based detection for DualReplica (two-node fencing) clusters
723+ dualReplicaTopology := v1 .DualReplicaTopologyMode
724+ return & SimplePathologicalEventMatcher {
725+ name : "EtcdEndpointsConfigMissingDuringTwoNodeTests" ,
726+ locatorKeyRegexes : map [monitorapi.LocatorKey ]* regexp.Regexp {
727+ monitorapi .LocatorNamespaceKey : regexp .MustCompile (`^openshift-kube-apiserver-operator$` ),
728+ },
729+ messageReasonRegex : regexp .MustCompile (`^ConfigMissing$` ),
730+ messageHumanRegex : regexp .MustCompile (`apiServerArguments\.etcd-servers has less than two live etcd endpoints` ),
731+ topology : & dualReplicaTopology ,
732+ }
733+ }
734+
718735// IsEventAfterInstallation returns true if the monitorEvent represents an event that happened after installation.
719736func IsEventAfterInstallation (monitorEvent monitorapi.Interval , kubeClientConfig * rest.Config ) (bool , error ) {
720737 if kubeClientConfig == nil {
0 commit comments