Skip to content

Commit 755c0d2

Browse files
Merge pull request #30113 from wking/test-oc-adm-upgrade-recommend-with-precheck-and-accept
OCPBUGS-61063: test/extended/cli/adm_upgrade/recommend: Enable precheck and accept
2 parents 2af38a7 + 78ac50f commit 755c0d2

File tree

1 file changed

+100
-14
lines changed

1 file changed

+100
-14
lines changed

test/extended/cli/adm_upgrade/recommend.go

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"net"
77
"net/url"
8+
"os"
89
"strconv"
910
"strings"
1011
"text/template"
@@ -31,6 +32,7 @@ var _ = g.Describe("[Serial][sig-cli] oc adm upgrade recommend", g.Ordered, func
3132
oc := exutil.NewCLIWithFramework(f).AsAdmin()
3233
var cv *configv1.ClusterVersion
3334
var restoreChannel, restoreUpstream bool
35+
var caBundleFilePath string
3436

3537
g.BeforeAll(func() {
3638
isMicroShift, err := exutil.IsMicroShiftCluster(oc.AdminKubeClient())
@@ -51,10 +53,14 @@ var _ = g.Describe("[Serial][sig-cli] oc adm upgrade recommend", g.Ordered, func
5153
if restoreUpstream {
5254
oc.Run("patch", "clusterversions.config.openshift.io", "version", "--type", "json", "-p", fmt.Sprintf(`[{"op": "add", "path": "/spec/upstream", "value": "%s"}]`, cv.Spec.Upstream)).Execute()
5355
}
56+
57+
if caBundleFilePath != "" {
58+
os.Remove(caBundleFilePath)
59+
}
5460
})
5561

5662
g.It("runs successfully, even without upstream OpenShift Update Service customization", func() {
57-
_, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").Output()
63+
_, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT", "true").Output()
5864
o.Expect(err).NotTo(o.HaveOccurred())
5965
})
6066

@@ -65,7 +71,7 @@ var _ = g.Describe("[Serial][sig-cli] oc adm upgrade recommend", g.Ordered, func
6571
}
6672
restoreChannel = true
6773

68-
out, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").Output()
74+
out, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT", "true").Output()
6975
o.Expect(err).NotTo(o.HaveOccurred())
7076
err = matchRegexp(out, `.*The update channel has not been configured.*`)
7177
o.Expect(err).NotTo(o.HaveOccurred())
@@ -99,7 +105,7 @@ var _ = g.Describe("[Serial][sig-cli] oc adm upgrade recommend", g.Ordered, func
99105
})
100106

101107
g.It("runs successfully", func() {
102-
out, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").Output()
108+
out, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT", "true").Output()
103109
o.Expect(err).NotTo(o.HaveOccurred())
104110
err = matchRegexp(out, `.*Upstream update service: http://.*
105111
Channel: test-channel [(]available channels: other-channel, test-channel[)]
@@ -110,6 +116,7 @@ No updates available. You may still upgrade to a specific release image.*`)
110116

111117
g.Context("When the update service has conditional recommendations", func() {
112118
var currentVersion *semver.Version
119+
var token string
113120

114121
g.BeforeAll(func() {
115122
isHyperShift, err := exutil.IsHypershift(ctx, oc.AdminConfigClient())
@@ -175,16 +182,45 @@ No updates available. You may still upgrade to a specific release image.*`)
175182
}
176183
restoreUpstream = true
177184

185+
defaultIngressCert, err := getDefaultIngressCertificate(ctx, oc)
186+
o.Expect(err).NotTo(o.HaveOccurred())
187+
188+
kubeCerts, err := getKubernetesAPIServerCertificates(ctx, oc)
189+
o.Expect(err).NotTo(o.HaveOccurred())
190+
191+
caBundleFile, err := os.CreateTemp("", "ca-bundle")
192+
caBundleFilePath = caBundleFile.Name()
193+
_, err = caBundleFile.WriteString(fmt.Sprintf("%s\n%s", defaultIngressCert, kubeCerts))
194+
o.Expect(err).NotTo(o.HaveOccurred())
195+
196+
// alert retrieval requires a token-based kubeconfig to avoid:
197+
// Failed to check for at least some preconditions: failed to get alerts from Thanos: no token is currently in use for this session
198+
o.Expect(oc.Run("create").Args("serviceaccount", "test").Execute()).To(o.Succeed())
199+
o.Expect(oc.Run("create").Args("clusterrolebinding", fmt.Sprintf("%s-test", oc.Namespace()), "--clusterrole=cluster-admin", fmt.Sprintf("--serviceaccount=%s:test", oc.Namespace())).Execute()).To(o.Succeed())
200+
token, err = oc.Run("create").Args("token", "test").Output()
201+
o.Expect(err).NotTo(o.HaveOccurred())
202+
178203
time.Sleep(16 * time.Second) // Give the CVO time to retrieve recommendations and push to status
179204
})
180205

206+
g.AfterAll(func() {
207+
// apparently ClusterRoleBindings are not automatically garbage-collected after the referenced service-account is removed (as part of namespace removal).
208+
oc.Run("delete").Args("clusterrolebinding", fmt.Sprintf("%s-test", oc.Namespace())).Execute()
209+
})
210+
181211
g.It("runs successfully when listing all updates", func() {
182-
out, err := oc.Run("adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").Output()
183-
o.Expect(err).NotTo(o.HaveOccurred())
184-
err = matchRegexp(out, `Upstream update service: http://.*
212+
oc.WithKubeConfigCopy(func(oc *exutil.CLI) {
213+
o.Expect(oc.Run("config", "set-credentials").Args("test", "--token", token).Execute()).To(o.Succeed())
214+
o.Expect(oc.Run("config", "set-context").Args("--current", "--user", "test").Execute()).To(o.Succeed())
215+
216+
out, err := oc.Run("--certificate-authority", caBundleFilePath, "adm", "upgrade", "recommend").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT", "true").Output()
217+
o.Expect(err).NotTo(o.HaveOccurred())
218+
err = matchRegexp(out, `The following conditions found no cause for concern in updating this cluster to later releases.*
219+
220+
Upstream update service: http://.*
185221
Channel: test-channel [(]available channels: other-channel, test-channel[)]
186222
187-
Updates to 4.[0-9]*:
223+
Updates to 4[.][0-9]*:
188224
189225
Version: 4[.][0-9]*[.]0
190226
Image: example[.]com/test@sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
@@ -195,21 +231,31 @@ Updates to 4[.][0-9]*:
195231
VERSION *ISSUES
196232
4[.][0-9]*[.]999 *no known issues relevant to this cluster
197233
4[.][0-9]*[.]998 *no known issues relevant to this cluster`)
198-
o.Expect(err).NotTo(o.HaveOccurred())
234+
o.Expect(err).NotTo(o.HaveOccurred())
235+
})
199236
})
200237

201238
g.It("runs successfully with conditional recommendations to the --version target", func() {
202-
out, err := oc.Run("adm", "upgrade", "recommend", "--version", fmt.Sprintf("4.%d.0", currentVersion.Minor+1)).EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").Output()
203-
o.Expect(err).NotTo(o.HaveOccurred())
204-
err = matchRegexp(out, `Upstream update service: http://.*
239+
oc.WithKubeConfigCopy(func(oc *exutil.CLI) {
240+
o.Expect(oc.Run("config", "set-credentials").Args("test", "--token", token).Execute()).To(o.Succeed())
241+
o.Expect(oc.Run("config", "set-context").Args("--current", "--user", "test").Execute()).To(o.Succeed())
242+
243+
out, err := oc.Run("--certificate-authority", caBundleFilePath, "adm", "upgrade", "recommend", "--version", fmt.Sprintf("4.%d.0", currentVersion.Minor+1), "--accept", "ConditionalUpdateRisk,Failing").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK", "true").EnvVar("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT", "true").Output()
244+
245+
o.Expect(err).NotTo(o.HaveOccurred())
246+
err = matchRegexp(out, `The following conditions found no cause for concern in updating this cluster to later releases.*
247+
248+
Upstream update service: http://.*
205249
Channel: test-channel [(]available channels: other-channel, test-channel[)]
206250
207251
Update to 4[.][0-9]*[.]0 Recommended=False:
208252
Image: example.com/test@sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
209253
Release URL: https://example.com/release/4[.][0-9]*[.]0
210-
Reason: (TestRiskA|MultipleReasons)
211-
Message: (?s:.*)This is a test risk. https://example.com/testRiskA`)
212-
o.Expect(err).NotTo(o.HaveOccurred())
254+
Reason: accepted (TestRiskA|MultipleReasons) via ConditionalUpdateRisk
255+
Message: (?s:.*)This is a test risk[.] https://example.com/testRiskA
256+
Update to 4[.][0-9]*[.]0 has no known issues relevant to this cluster other than the accepted ConditionalUpdateRisk(|,Failing).`)
257+
o.Expect(err).NotTo(o.HaveOccurred())
258+
})
213259
})
214260
})
215261
})
@@ -291,3 +337,43 @@ python3 -m http.server --bind ::
291337
Path: "graph",
292338
}, nil
293339
}
340+
341+
func getDefaultIngressCertificate(ctx context.Context, oc *exutil.CLI) (string, error) {
342+
defaultIngressSecretName, err := oc.Run("get").Args("--namespace=openshift-ingress-operator", "-o", "jsonpath={.spec.defaultCertificate.name}", "ingresscontroller.operator.openshift.io", "default").Output()
343+
if err != nil {
344+
return "", err
345+
}
346+
347+
if defaultIngressSecretName == "" {
348+
defaultIngressSecretName = "router-certs-default"
349+
}
350+
351+
ingressNamespace := "openshift-ingress"
352+
defaultIngressCert, err := oc.Run("extract").Args("--namespace", ingressNamespace, fmt.Sprintf("secret/%s", defaultIngressSecretName), "--keys=tls.crt", "--to=-").Output()
353+
if err != nil {
354+
return "", err
355+
}
356+
defaultIngressCert = fmt.Sprintf("%s\n", defaultIngressCert) // ensure a trailing newline, even if the earlier Output() stripped trailing newlines
357+
framework.Logf("default ingress certificate from the %s secret in the %s namespace: %q", defaultIngressSecretName, ingressNamespace, fmt.Sprintf("%s...", defaultIngressCert[:30]))
358+
return defaultIngressCert, nil
359+
}
360+
361+
func getKubernetesAPIServerCertificates(ctx context.Context, oc *exutil.CLI) (string, error) {
362+
kubeNamespace := "openshift-kube-apiserver"
363+
secrets, err := oc.AdminKubeClient().CoreV1().Secrets(kubeNamespace).List(ctx, metav1.ListOptions{})
364+
if err != nil {
365+
return "", err
366+
}
367+
368+
certs := make([]string, 0, len(secrets.Items))
369+
for _, secret := range secrets.Items {
370+
if secret.Type != corev1.SecretTypeTLS {
371+
continue
372+
}
373+
certs = append(certs, string(secret.Data["tls.crt"]))
374+
}
375+
376+
kubeCerts := strings.Join(certs, "")
377+
framework.Logf("default Kubernetes certificates from TLS secrets in the %s namespace: %q", kubeNamespace, fmt.Sprintf("%s...", kubeCerts[:30]))
378+
return kubeCerts, nil
379+
}

0 commit comments

Comments
 (0)