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,6 +53,10 @@ 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 () {
@@ -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,15 +182,38 @@ 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" , "test" , "--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
181206		g .It ("runs successfully when listing all updates" , func () {
182- 			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 ()
183- 			o .Expect (err ).NotTo (o .HaveOccurred ())
184- 			err  =  matchRegexp (out , `Upstream update service: http://.* 
185- Channel: test-channel [(]available channels: other-channel, test-channel[)] 
207+ 			oc .WithKubeConfigCopy (func (oc  * exutil.CLI ) {
208+ 				o .Expect (oc .Run ("config" , "set-credentials" ).Args ("test" , "--token" , token ).Execute ()).To (o .Succeed ())
209+ 				o .Expect (oc .Run ("config" , "set-context" ).Args ("--current" , "--user" , "test" ).Execute ()).To (o .Succeed ())
186210
211+ 				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 ()
212+ 				o .Expect (err ).NotTo (o .HaveOccurred ())
213+ 				err  =  matchRegexp (out , `The following conditions found no cause for concern in updating this cluster to later releases.* 
214+ 
215+ Upstream update service: http://.* 
216+ Channel: test-channel [(]available channels: other-channel, test-channel[)] 
187217Updates to 4.[0-9]*: 
188218
189219  Version: 4[.][0-9]*[.]0 
@@ -195,23 +225,18 @@ Updates to 4[.][0-9]*:
195225  VERSION  *ISSUES 
196226  4[.][0-9]*[.]999  *no known issues relevant to this cluster 
197227  4[.][0-9]*[.]998  *no known issues relevant to this cluster` )
198- 			o .Expect (err ).NotTo (o .HaveOccurred ())
228+ 				o .Expect (err ).NotTo (o .HaveOccurred ())
229+ 			})
199230		})
200231
201232		g .It ("runs successfully with an accepted conditional recommendation to the --version target" , func () {
202- 			// alert retrieval requires a token-based kubeconfig to avoid: 
203- 			//   Failed to check for at least some preconditions: failed to get alerts from Thanos: no token is currently in use for this session 
204- 			o .Expect (oc .Run ("create" ).Args ("serviceaccount" , "test" ).Execute ()).To (o .Succeed ())
205- 			o .Expect (oc .Run ("create" ).Args ("clusterrolebinding" , "test" , "--clusterrole=cluster-admin" , fmt .Sprintf ("--serviceaccount=%s:test" , oc .Namespace ())).Execute ()).To (o .Succeed ())
206- 			token , err  :=  oc .Run ("create" ).Args ("token" , "test" ).Output ()
207- 			o .Expect (err ).NotTo (o .HaveOccurred ())
208- 
209233			oc .WithKubeConfigCopy (func (oc  * exutil.CLI ) {
210234				o .Expect (oc .Run ("config" , "set-credentials" ).Args ("test" , "--token" , token ).Execute ()).To (o .Succeed ())
211235				o .Expect (oc .Run ("config" , "set-context" ).Args ("--current" , "--user" , "test" ).Execute ()).To (o .Succeed ())
212236
213- 				out , err  :=  oc .Run ("adm" , "upgrade" , "recommend" , "--version" , fmt .Sprintf ("4.%d.0" , currentVersion .Minor + 1 ), "--accept" , "ConditionalUpdateRisk" ).EnvVar ("OC_ENABLE_CMD_UPGRADE_RECOMMEND" , "true" ).EnvVar ("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK" , "true" ).EnvVar ("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT" , "true" ).Output ()
214- 				o .Expect (err ).To (o .HaveOccurred ())
237+ 				out , err  :=  oc .Run ("--certificate-authority" , caBundleFilePath , "adm" , "upgrade" , "recommend" , "--version" , fmt .Sprintf ("4.%d.0" , currentVersion .Minor + 1 ), "--accept" , "ConditionalUpdateRisk" ).EnvVar ("OC_ENABLE_CMD_UPGRADE_RECOMMEND" , "true" ).EnvVar ("OC_ENABLE_CMD_UPGRADE_RECOMMEND_PRECHECK" , "true" ).EnvVar ("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT" , "true" ).Output ()
238+ 
239+ 				o .Expect (err ).NotTo (o .HaveOccurred ())
215240				err  =  matchRegexp (out , `The following conditions found no cause for concern in updating this cluster to later releases.* 
216241
217242Upstream update service: http://.* 
@@ -305,3 +330,43 @@ python3 -m http.server --bind ::
305330		Path :   "graph" ,
306331	}, nil 
307332}
333+ 
334+ func  getDefaultIngressCertificate (ctx  context.Context , oc  * exutil.CLI ) (string , error ) {
335+ 	defaultIngressSecretName , err  :=  oc .Run ("get" ).Args ("--namespace=openshift-ingress-operator" , "-o" , "jsonpath={.spec.defaultCertificate.name}" , "ingresscontroller.operator.openshift.io" , "default" ).Output ()
336+ 	if  err  !=  nil  {
337+ 		return  "" , err 
338+ 	}
339+ 
340+ 	if  defaultIngressSecretName  ==  ""  {
341+ 		defaultIngressSecretName  =  "router-certs-default" 
342+ 	}
343+ 
344+ 	ingressNamespace  :=  "openshift-ingress" 
345+ 	defaultIngressCert , err  :=  oc .Run ("extract" ).Args ("--namespace" , ingressNamespace , fmt .Sprintf ("secret/%s" , defaultIngressSecretName ), "--keys=tls.crt" , "--to=-" ).Output ()
346+ 	if  err  !=  nil  {
347+ 		return  "" , err 
348+ 	}
349+ 	defaultIngressCert  =  fmt .Sprintf ("%s\n " , defaultIngressCert ) // ensure a trailing newline, even if the earlier Output() stripped trailing newlines 
350+ 	framework .Logf ("default ingress certificate from the %s secret in the %s namespace: %q" , defaultIngressSecretName , ingressNamespace , defaultIngressCert )
351+ 	return  defaultIngressCert , nil 
352+ }
353+ 
354+ func  getKubernetesAPIServerCertificates (ctx  context.Context , oc  * exutil.CLI ) (string , error ) {
355+ 	kubeNamespace  :=  "openshift-kube-apiserver" 
356+ 	secrets , err  :=  oc .AdminKubeClient ().CoreV1 ().Secrets (kubeNamespace ).List (ctx , metav1.ListOptions {})
357+ 	if  err  !=  nil  {
358+ 		return  "" , err 
359+ 	}
360+ 
361+ 	certs  :=  make ([]string , 0 , len (secrets .Items ))
362+ 	for  _ , secret  :=  range  secrets .Items  {
363+ 		if  secret .Type  !=  corev1 .SecretTypeTLS  {
364+ 			continue 
365+ 		}
366+ 		certs  =  append (certs , string (secret .Data ["tls.crt" ]))
367+ 	}
368+ 
369+ 	kubeCerts  :=  strings .Join (certs , "" )
370+ 	framework .Logf ("default Kubernetes certificates from TLS secrets in the %s namespace: %q" , kubeNamespace , kubeCerts )
371+ 	return  kubeCerts , nil 
372+ }
0 commit comments