Skip to content

Commit 070c788

Browse files
committed
Add e2e test case for alert risks
1 parent 3b365d0 commit 070c788

3 files changed

Lines changed: 99 additions & 3 deletions

File tree

cmd/cluster-version-operator-tests/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func main() {
2424
Name: "openshift/cluster-version-operator/conformance/parallel",
2525
Parents: []string{"openshift/conformance/parallel"},
2626
Qualifiers: []string{
27-
`!(name.contains("[Serial]") || "Serial" in labels || name.contains("[Slow]"))`,
27+
`!(name.contains("[Serial]") || "Serial" in labels || name.contains("[Slow]") || "Local" in labels)`,
2828
},
2929
})
3030

@@ -33,7 +33,7 @@ func main() {
3333
Name: "openshift/cluster-version-operator/conformance/serial",
3434
Parents: []string{"openshift/conformance/serial"},
3535
Qualifiers: []string{
36-
`name.contains("[Serial]") || "Serial" in labels`,
36+
`(name.contains("[Serial]") || "Serial" in labels) && !("Local" in labels)`,
3737
},
3838
})
3939

pkg/external/constants.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package external
22

3-
import "github.com/openshift/cluster-version-operator/pkg/internal"
3+
import (
4+
"github.com/openshift/cluster-version-operator/pkg/internal"
5+
)
46

57
// The constants defined here are used by the components, e.g., e2e tests that have no access
68
// to github.com/openshift/cluster-version-operator/pkg/internal
@@ -18,4 +20,13 @@ const (
1820
// ConditionalUpdateConditionTypeRecommended is a type of the condition present on a conditional update
1921
// that indicates whether the conditional update is recommended or not
2022
ConditionalUpdateConditionTypeRecommended = internal.ConditionalUpdateConditionTypeRecommended
23+
24+
// ConditionalUpdateRiskConditionTypeApplies is a type of the condition present on a conditional update risk
25+
// that indicates whether the conditional update risk applies to the cluster
26+
ConditionalUpdateRiskConditionTypeApplies = internal.ConditionalUpdateRiskConditionTypeApplies
2127
)
28+
29+
// IsAlertConditionReason checks if the given reason is legit for a condition of a risk from an alert that applies
30+
func IsAlertConditionReason(reason string) bool {
31+
return internal.IsAlertConditionReason(reason)
32+
}

test/cvo/accept_risks.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ import (
66

77
g "github.com/onsi/ginkgo/v2"
88
o "github.com/onsi/gomega"
9+
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
910
prometheusoperatorv1client "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/typed/monitoring/v1"
1011

12+
"k8s.io/apimachinery/pkg/api/errors"
1113
"k8s.io/apimachinery/pkg/api/meta"
1214
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+
"k8s.io/apimachinery/pkg/util/intstr"
1316
"k8s.io/apimachinery/pkg/util/sets"
1417
"k8s.io/apimachinery/pkg/util/wait"
1518
"k8s.io/client-go/rest"
@@ -65,6 +68,88 @@ var _ = g.Describe(`[Jira:"Cluster Version Operator"] cluster-version-operator`,
6568
}
6669
})
6770

71+
g.It("should work with risks from alerts", g.Label("OTA-1813"), g.Label("Serial"), g.Label("Local"), func() {
72+
// This test case relies on a public service util.FauxinnatiAPIURL
73+
o.Expect(util.SkipIfNetworkRestricted(ctx, c, util.FauxinnatiAPIURL)).To(o.BeNil())
74+
75+
cv, err := configClient.ClusterVersions().Get(ctx, external.DefaultClusterVersionName, metav1.GetOptions{})
76+
o.Expect(err).NotTo(o.HaveOccurred())
77+
78+
g.By("Using fauxinnati as the upstream and its simple channel")
79+
cv.Spec.Upstream = util.FauxinnatiAPIURL
80+
cv.Spec.Channel = "simple"
81+
82+
_, err = configClient.ClusterVersions().Update(ctx, cv, metav1.UpdateOptions{})
83+
o.Expect(err).NotTo(o.HaveOccurred())
84+
needRecover = true
85+
86+
g.By("Create a critical alert for testing")
87+
prometheusRule := &monitoringv1.PrometheusRule{
88+
ObjectMeta: metav1.ObjectMeta{
89+
Name: "testing",
90+
Namespace: external.DefaultCVONamespace,
91+
},
92+
Spec: monitoringv1.PrometheusRuleSpec{
93+
Groups: []monitoringv1.RuleGroup{
94+
{
95+
Name: "test",
96+
Rules: []monitoringv1.Rule{
97+
{
98+
Alert: "TestAlertFeatureE2ETestOTA1813",
99+
Annotations: map[string]string{"summary": "Test summary.", "description": "Test description."},
100+
Expr: intstr.IntOrString{
101+
Type: intstr.String,
102+
StrVal: `up{job="cluster-version-operator"} == 1`,
103+
},
104+
Labels: map[string]string{"severity": "critical", "namespace": "openshift-cluster-version", "openShiftUpdatePrecheck": "true"},
105+
},
106+
},
107+
},
108+
},
109+
},
110+
}
111+
created, err := monitoringClient.PrometheusRules(external.DefaultCVONamespace).Create(ctx, prometheusRule, metav1.CreateOptions{})
112+
o.Expect(err).NotTo(o.HaveOccurred())
113+
defer func() {
114+
err := monitoringClient.PrometheusRules(external.DefaultCVONamespace).Delete(ctx, created.Name, metav1.DeleteOptions{})
115+
if !errors.IsNotFound(err) {
116+
o.Expect(err).To(o.BeNil())
117+
}
118+
}()
119+
120+
g.By("Checking if the risk shows up in ClusterVersion's status")
121+
o.Expect(wait.PollUntilContextTimeout(ctx, 30*time.Second, 10*time.Minute, true, func(ctx context.Context) (done bool, err error) {
122+
cv, err := configClient.ClusterVersions().Get(ctx, external.DefaultClusterVersionName, metav1.GetOptions{})
123+
o.Expect(err).NotTo(o.HaveOccurred())
124+
for _, risk := range cv.Status.ConditionalUpdateRisks {
125+
if risk.Name == "TestAlertFeatureE2ETestOTA1813" {
126+
if c := meta.FindStatusCondition(risk.Conditions, external.ConditionalUpdateRiskConditionTypeApplies); c != nil {
127+
if c.Status == metav1.ConditionTrue && external.IsAlertConditionReason(c.Reason) {
128+
return true, nil
129+
}
130+
}
131+
}
132+
}
133+
return false, nil
134+
})).NotTo(o.HaveOccurred(), "no conditional update risk from alert found in ClusterVersion's status")
135+
136+
g.By("Checking that no updates is recommended if alert is firing")
137+
o.Expect(wait.PollUntilContextTimeout(ctx, 30*time.Second, 5*time.Minute, true, func(ctx context.Context) (done bool, err error) {
138+
cv, err := configClient.ClusterVersions().Get(ctx, external.DefaultClusterVersionName, metav1.GetOptions{})
139+
o.Expect(err).NotTo(o.HaveOccurred())
140+
if len(cv.Status.AvailableUpdates) > 0 {
141+
return false, nil
142+
}
143+
for _, cu := range cv.Status.ConditionalUpdates {
144+
condition := meta.FindStatusCondition(cu.Conditions, external.ConditionalUpdateConditionTypeRecommended)
145+
if condition == nil || condition.Status == metav1.ConditionTrue || condition.Status == metav1.ConditionUnknown {
146+
return false, nil
147+
}
148+
}
149+
return true, nil
150+
})).NotTo(o.HaveOccurred(), "still recommending updates while alert is firing")
151+
})
152+
68153
g.It("should work with accept risks", g.Label("Serial"), func() {
69154
// This test case relies on a public service util.FauxinnatiAPIURL
70155
o.Expect(util.SkipIfNetworkRestricted(ctx, c, util.FauxinnatiAPIURL)).To(o.BeNil())

0 commit comments

Comments
 (0)