diff --git a/pkg/monitortests/testframework/operatorloganalyzer/operator_lease_check.go b/pkg/monitortests/testframework/operatorloganalyzer/operator_lease_check.go index ee2e05a4436f..9bf5f7f1d36a 100644 --- a/pkg/monitortests/testframework/operatorloganalyzer/operator_lease_check.go +++ b/pkg/monitortests/testframework/operatorloganalyzer/operator_lease_check.go @@ -10,7 +10,9 @@ import ( "github.com/openshift/origin/pkg/monitor/monitorapi" "github.com/openshift/origin/pkg/monitortestframework" + "github.com/openshift/origin/pkg/monitortestlibrary/platformidentification" "github.com/openshift/origin/pkg/test/ginkgo/junitapi" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/rest" ) @@ -131,6 +133,13 @@ func (intervals byLeaseAcquisition) Swap(i, j int) { intervals[i], intervals[j] = intervals[j], intervals[i] } +// getNamespaceForJUnits makes a clone of the known namespaces +func getNamespacesForJUnits() sets.String { + namespaces := platformidentification.KnownNamespaces.Clone() + namespaces.Insert("") + return namespaces +} + func (*operatorLeaseCheck) EvaluateTestsFromConstructedIntervals(ctx context.Context, finalIntervals monitorapi.Intervals) ([]*junitapi.JUnitTestCase, error) { leaseIntervals := finalIntervals.Filter(func(eventInterval monitorapi.Interval) bool { if eventInterval.Message.Reason == monitorapi.LeaseAcquiring { @@ -140,6 +149,15 @@ func (*operatorLeaseCheck) EvaluateTestsFromConstructedIntervals(ctx context.Con }) testNameToFailures := map[string][]string{} + + // we get intermittent hits for openshift-operators that pass + // but don't show in all aggregated results, causing failures + // init all known namespaces + namespaces := getNamespacesForJUnits() + for ns := range namespaces { + testName := fmt.Sprintf("[sig-arch] all leases in ns/%s must gracefully release", ns) + testNameToFailures[testName] = []string{} + } for _, interval := range leaseIntervals { ns := monitorapi.NamespaceFromLocator(interval.Locator) testName := fmt.Sprintf("[sig-arch] all leases in ns/%s must gracefully release", ns) diff --git a/test/extended/cli/mustgather.go b/test/extended/cli/mustgather.go index e27117642a4b..997c548a5abe 100644 --- a/test/extended/cli/mustgather.go +++ b/test/extended/cli/mustgather.go @@ -340,6 +340,50 @@ var _ = g.Describe("[sig-cli] oc adm must-gather", func() { }) }) }) + + g.It("runs successfully for metrics gathering [apigroup:config.openshift.io]", func() { + tempDir, err := os.MkdirTemp("", "test.oc-adm-must-gather.") + o.Expect(err).NotTo(o.HaveOccurred()) + defer os.RemoveAll(tempDir) + + args := []string{ + "--dest-dir", tempDir, + "--", + "/usr/bin/gather_metrics", + fmt.Sprintf("--min-time=%d", time.Now().Add(-5*time.Minute).UnixMilli()), + fmt.Sprintf("--max-time=%d", time.Now().UnixMilli()), + "--match=prometheus_ready", + "--match=prometheus_build_info", + } + o.Expect(oc.Run("adm", "must-gather").Args(args...).Execute()).To(o.Succeed()) + + // wait for the contents to show up in the plugin output directory + time.Sleep(5 * time.Second) + + pluginOutputDir := GetPluginOutputDir(tempDir) + metricsFile := path.Join(pluginOutputDir, "monitoring", "metrics", "metrics.openmetrics") + errorFile := path.Join(pluginOutputDir, "monitoring", "metrics", "metrics.stderr") + + // The error file should be empty + o.Expect(errorFile).To(o.BeAnExistingFile()) + errorContent, err := os.ReadFile(errorFile) + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(errorContent).To(o.BeEmpty()) + + // The metrics file should contain some series with a given format + o.Expect(metricsFile).To(o.BeAnExistingFile()) + metrics, err := os.ReadFile(metricsFile) + o.Expect(err).NotTo(o.HaveOccurred()) + + lines := strings.Split(strings.TrimSpace(string(metrics)), "\n") + count := len(lines) + o.Expect(count).To(o.BeNumerically(">=", 5)) + for _, line := range lines[:count-1] { + o.Expect(line).To(o.MatchRegexp(`^(prometheus_ready|prometheus_build_info)\{.*\} \d+ \d+`)) + } + + o.Expect(lines[count-1]).To(o.Equal("# EOF")) + }) }) // GetPluginOutputDir returns the directory containing must-gather assets. diff --git a/test/extended/images/dryrun.go b/test/extended/images/dryrun.go index 8be9d28d560f..7b146cc50d08 100644 --- a/test/extended/images/dryrun.go +++ b/test/extended/images/dryrun.go @@ -1,13 +1,16 @@ package images import ( + "context" + "time" + g "github.com/onsi/ginkgo/v2" o "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/util/wait" admissionapi "k8s.io/pod-security-admission/api" exutil "github.com/openshift/origin/test/extended/util" - "github.com/openshift/origin/test/extended/util/image" ) var _ = g.Describe("[sig-imageregistry] Image --dry-run", func() { @@ -19,7 +22,7 @@ var _ = g.Describe("[sig-imageregistry] Image --dry-run", func() { g.It("should not delete resources [apigroup:image.openshift.io]", func() { g.By("preparing the image stream where the test image will be pushed") - err := oc.Run("tag").Args("--source=docker", image.ShellImage(), "test:latest").Execute() + err := oc.Run("tag").Args("openshift/cli:latest", "test:latest").Execute() o.Expect(err).NotTo(o.HaveOccurred()) err = exutil.WaitForAnImageStreamTag(oc, oc.Namespace(), "test", "latest") @@ -41,4 +44,36 @@ var _ = g.Describe("[sig-imageregistry] Image --dry-run", func() { _, err = oc.Run("get").Args("imagestream", "test", "-o", "jsonpath={.image.metadata.name}").Output() o.Expect(err).NotTo(o.HaveOccurred()) }) + + g.It("should not update resources [apigroup:image.openshift.io]", func() { + + g.By("actually creating imagestream for update dry-run test") + err := oc.Run("create").Args("imagestream", "dryrun-test").Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + defer func() { + g.By("cleaning up imagestream") + err := oc.Run("delete").Args("imagestream/dryrun-test", "--ignore-not-found=true").Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + }() + + g.By("verifying the imagestream was actually created") + err = wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 30*time.Second, true, func(ctx context.Context) (bool, error) { + _, err := oc.Run("get").Args("imagestream", "dryrun-test", "-o", "jsonpath={.metadata.name}").Output() + if err != nil { + return false, nil // Continue polling + } + return true, nil // Success + }) + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("triggering imagestream annotation update with --dry-run=server") + err = oc.Run("annotate").Args("imagestream/dryrun-test", "test-annotation=value1", "--dry-run=server").Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("verifying the annotation was not persisted") + output, err := oc.Run("get").Args("imagestream", "dryrun-test", "-o", "jsonpath={.metadata.annotations.test-annotation}").Output() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(output).To(o.BeEmpty()) + }) }) diff --git a/test/extended/util/annotate/generated/zz_generated.annotations.go b/test/extended/util/annotate/generated/zz_generated.annotations.go index 29b0bf4b2ee8..fcec5608d9c7 100644 --- a/test/extended/util/annotate/generated/zz_generated.annotations.go +++ b/test/extended/util/annotate/generated/zz_generated.annotations.go @@ -801,6 +801,8 @@ var Annotations = map[string]string{ "[sig-cli] oc adm must-gather runs successfully for audit logs [apigroup:config.openshift.io][apigroup:oauth.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc adm must-gather runs successfully for metrics gathering [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-cli] oc adm must-gather runs successfully with options [apigroup:config.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-cli] oc adm must-gather when looking at the audit logs [apigroup:config.openshift.io] [sig-node] kubelet runs apiserver processes strictly sequentially in order to not risk audit log corruption": " [Suite:openshift/conformance/parallel]", diff --git a/test/extended/util/compat_otp/testdata/opm/render/validate/catalog-error/operator-2/index.json b/test/extended/util/compat_otp/testdata/opm/render/validate/catalog-error/operator-2/index.json index fa67b2522cf1..2d73356e7807 100644 --- a/test/extended/util/compat_otp/testdata/opm/render/validate/catalog-error/operator-2/index.json +++ b/test/extended/util/compat_otp/testdata/opm/render/validate/catalog-error/operator-2/index.json @@ -1,8 +1,9 @@ +[ { "schema": "olm.package", "name": "operator-2", "defaultChannel": "beta" -} +}, { "schema": "olm.channel", "name": "4.7", @@ -15,7 +16,7 @@ ] } ] -} +}, { "schema": "olm.channel", "name": "4.8", @@ -30,7 +31,7 @@ "replaces": "operator-2.v0.4.0" } ] -} +}, { "schema": "olm.channel", "name": "4.9", @@ -41,7 +42,7 @@ "skipRange": ">=0.1.0 <0.6.0" } ] -} +}, { "schema": "olm.channel", "name": "alpha", @@ -55,7 +56,7 @@ "replaces": "operator-2.v0.1.1" } ] -} +}, { "schema": "olm.bundle", "name": "operator-2.v0.1.0", @@ -78,7 +79,7 @@ } } ] -} +}, { "schema": "olm.bundle", "name": "operator-2.v0.2.0", @@ -101,7 +102,7 @@ } } ] -} +}, { "schema": "olm.bundle", "name": "operator-2.v0.3.0", @@ -124,7 +125,7 @@ } } ] -} +}, { "schema": "olm.bundle", "name": "operator-2.v0.4.0", @@ -147,7 +148,7 @@ } } ] -} +}, { "schema": "olm.bundle", "name": "operator-2.v0.5.0", @@ -170,7 +171,7 @@ } } ] -} +}, { "schema": "olm.bundle", "name": "operator-2.v0.6.0", @@ -194,3 +195,4 @@ } ] } +]