99 cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
1010 . "github.com/openshift-online/ocm-sdk-go/testing"
1111
12+ "github.com/openshift/rosa/pkg/arguments"
13+ "github.com/openshift/rosa/pkg/interactive"
1214 "github.com/openshift/rosa/pkg/test"
1315)
1416
@@ -21,6 +23,258 @@ var _ = Describe("Delete cluster", func() {
2123 BeforeEach (func () {
2224 t = test .NewTestRuntime ()
2325 clusterId = test .MockClusterID
26+ args .bestEffort = false
27+ args .watch = false
28+ interactive .SetEnabled (false )
29+ arguments .DisableRegionDeprecationWarning = false
30+ })
31+
32+ Context ("runWithRuntime" , func () {
33+ var argv []string
34+
35+ BeforeEach (func () {
36+ argv = []string {}
37+ args .bestEffort = false
38+ args .watch = false
39+ confirmDelete = func (string , ... interface {}) bool { return true }
40+ runUninstallLogs = func (string ) {}
41+ interactive .SetEnabled (false )
42+ arguments .DisableRegionDeprecationWarning = false
43+ })
44+
45+ It ("runs the non-STS happy path and prints the uninstall log hint" , func () {
46+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
47+ c .State (cmv1 .ClusterStateReady )
48+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
49+ })
50+ t .SetCluster (clusterId , clusterReady )
51+
52+ statusBody := fmt .Sprintf (`{
53+ "kind": "ClusterStatus",
54+ "id": "%s",
55+ "state": "ready"
56+ }` , clusterId )
57+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
58+ t .ApiServer .AppendHandlers (RespondWithJSON (
59+ http .StatusOK , test .FormatClusterList ([]* cmv1.Cluster {clusterReady })))
60+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , "" ))
61+
62+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
63+ Expect (err ).NotTo (HaveOccurred ())
64+ Expect (stderr ).To (BeEmpty ())
65+ Expect (stdout ).To (ContainSubstring ("will start uninstalling" ))
66+ Expect (stdout ).To (ContainSubstring ("rosa logs uninstall -c" ))
67+ Expect (stdout ).To (ContainSubstring ("--watch" ))
68+ })
69+
70+ It ("returns cleanly when deletion is not confirmed" , func () {
71+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
72+ c .State (cmv1 .ClusterStateReady )
73+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
74+ })
75+ t .SetCluster (clusterId , clusterReady )
76+ confirmDelete = func (string , ... interface {}) bool { return false }
77+
78+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
79+ Expect (err ).NotTo (HaveOccurred ())
80+ Expect (stderr ).To (BeEmpty ())
81+ Expect (stdout ).To (BeEmpty ())
82+ })
83+
84+ It ("prints the best-effort warning and passes the flag through" , func () {
85+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
86+ c .State (cmv1 .ClusterStateReady )
87+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
88+ })
89+ t .SetCluster (clusterId , clusterReady )
90+ args .bestEffort = true
91+
92+ statusBody := fmt .Sprintf (`{
93+ "kind": "ClusterStatus",
94+ "id": "%s",
95+ "state": "ready"
96+ }` , clusterId )
97+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
98+ t .ApiServer .AppendHandlers (RespondWithJSON (
99+ http .StatusOK , test .FormatClusterList ([]* cmv1.Cluster {clusterReady })))
100+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , "" ))
101+
102+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
103+ Expect (err ).NotTo (HaveOccurred ())
104+ Expect (stderr ).To (ContainSubstring ("best effort" ))
105+ Expect (stderr ).To (ContainSubstring ("certain resources may be left behind" ))
106+ Expect (stdout ).To (ContainSubstring ("will start uninstalling" ))
107+ })
108+
109+ It ("prints STS cleanup guidance for clusters with operator roles" , func () {
110+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
111+ c .State (cmv1 .ClusterStateReady )
112+ c .AWS (cmv1 .NewAWS ().STS (
113+ cmv1 .NewSTS ().
114+ RoleARN ("arn:aws:iam::123456789012:role/Installer" ).
115+ OIDCEndpointURL ("https://oidc.example.com" ).
116+ OperatorRolePrefix ("my-prefix" ).
117+ OperatorIAMRoles (
118+ cmv1 .NewOperatorIAMRole ().
119+ Name ("ebs-cloud-credentials" ).
120+ Namespace ("openshift-cluster-csi-drivers" ).
121+ RoleARN ("arn:aws:iam::123456789012:role/op-role" ),
122+ ),
123+ ))
124+ })
125+ t .SetCluster (clusterId , clusterReady )
126+
127+ statusBody := fmt .Sprintf (`{
128+ "kind": "ClusterStatus",
129+ "id": "%s",
130+ "state": "ready"
131+ }` , clusterId )
132+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
133+ t .ApiServer .AppendHandlers (RespondWithJSON (
134+ http .StatusOK , test .FormatClusterList ([]* cmv1.Cluster {clusterReady })))
135+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , "" ))
136+
137+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
138+ Expect (err ).NotTo (HaveOccurred ())
139+ Expect (stderr ).To (BeEmpty ())
140+ Expect (stdout ).To (ContainSubstring ("Operator IAM Roles:" ))
141+ Expect (stdout ).To (ContainSubstring ("arn:aws:iam::123456789012:role/op-role" ))
142+ Expect (stdout ).To (ContainSubstring ("OIDC Provider : https://oidc.example.com" ))
143+ Expect (stdout ).To (ContainSubstring ("rosa delete operator-roles -c" ))
144+ Expect (stdout ).To (ContainSubstring ("rosa delete oidc-provider -c" ))
145+ })
146+
147+ It ("prints STS cleanup guidance without operator role output when none remain" , func () {
148+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
149+ c .State (cmv1 .ClusterStateReady )
150+ c .AWS (cmv1 .NewAWS ().STS (
151+ cmv1 .NewSTS ().
152+ RoleARN ("arn:aws:iam::123456789012:role/Installer" ).
153+ OIDCEndpointURL ("https://oidc-no-roles.example.com" ),
154+ ))
155+ })
156+ t .SetCluster (clusterId , clusterReady )
157+
158+ statusBody := fmt .Sprintf (`{
159+ "kind": "ClusterStatus",
160+ "id": "%s",
161+ "state": "ready"
162+ }` , clusterId )
163+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
164+ t .ApiServer .AppendHandlers (RespondWithJSON (
165+ http .StatusOK , test .FormatClusterList ([]* cmv1.Cluster {clusterReady })))
166+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , "" ))
167+
168+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
169+ Expect (err ).NotTo (HaveOccurred ())
170+ Expect (stderr ).To (BeEmpty ())
171+ Expect (stdout ).NotTo (ContainSubstring ("Operator IAM Roles:" ))
172+ Expect (stdout ).To (ContainSubstring ("OIDC Provider : https://oidc-no-roles.example.com" ))
173+ Expect (stdout ).To (ContainSubstring ("rosa delete operator-roles -c" ))
174+ Expect (stdout ).To (ContainSubstring ("rosa delete oidc-provider -c" ))
175+ })
176+
177+ It ("runs uninstall logs when watch is enabled and restores the deprecation warning flag" , func () {
178+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
179+ c .State (cmv1 .ClusterStateReady )
180+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
181+ })
182+ t .SetCluster (clusterId , clusterReady )
183+ args .watch = true
184+
185+ statusBody := fmt .Sprintf (`{
186+ "kind": "ClusterStatus",
187+ "id": "%s",
188+ "state": "ready"
189+ }` , clusterId )
190+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
191+ t .ApiServer .AppendHandlers (RespondWithJSON (
192+ http .StatusOK , test .FormatClusterList ([]* cmv1.Cluster {clusterReady })))
193+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , "" ))
194+
195+ var watchedClusterKey string
196+ var sawDisabledWarning bool
197+ runUninstallLogs = func (clusterKey string ) {
198+ watchedClusterKey = clusterKey
199+ sawDisabledWarning = arguments .DisableRegionDeprecationWarning
200+ }
201+
202+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
203+ Expect (err ).NotTo (HaveOccurred ())
204+ Expect (stderr ).To (BeEmpty ())
205+ Expect (stdout ).To (ContainSubstring ("will start uninstalling" ))
206+ Expect (watchedClusterKey ).To (Equal (clusterId ))
207+ Expect (sawDisabledWarning ).To (BeTrue ())
208+ Expect (arguments .DisableRegionDeprecationWarning ).To (BeFalse ())
209+ Expect (stdout ).NotTo (ContainSubstring ("rosa logs uninstall -c" ))
210+ })
211+
212+ It ("returns the already-uninstalling path through the command wrapper" , func () {
213+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
214+ c .State (cmv1 .ClusterStateReady )
215+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
216+ })
217+ t .SetCluster (clusterId , clusterReady )
218+
219+ statusBody := fmt .Sprintf (`{
220+ "kind": "ClusterStatus",
221+ "id": "%s",
222+ "state": "uninstalling"
223+ }` , clusterId )
224+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
225+
226+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
227+ Expect (err ).NotTo (HaveOccurred ())
228+ Expect (stderr ).To (BeEmpty ())
229+ Expect (stdout ).To (ContainSubstring ("already uninstalling" ))
230+ Expect (stdout ).To (ContainSubstring ("rosa logs uninstall -c" ))
231+ })
232+
233+ It ("returns an error from GetClusterState through the command wrapper" , func () {
234+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
235+ c .State (cmv1 .ClusterStateReady )
236+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
237+ })
238+ t .SetCluster (clusterId , clusterReady )
239+
240+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusInternalServerError , "" ))
241+
242+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
243+ Expect (err ).To (HaveOccurred ())
244+ Expect (stderr ).To (BeEmpty ())
245+ Expect (stdout ).To (BeEmpty ())
246+ Expect (err .Error ()).To (ContainSubstring ("expected response content type" ))
247+ })
248+
249+ It ("returns a delete error through the command wrapper" , func () {
250+ clusterReady := test .MockCluster (func (c * cmv1.ClusterBuilder ) {
251+ c .State (cmv1 .ClusterStateReady )
252+ c .AWS (cmv1 .NewAWS ().STS (cmv1 .NewSTS ()))
253+ })
254+ t .SetCluster (clusterId , clusterReady )
255+
256+ statusBody := fmt .Sprintf (`{
257+ "kind": "ClusterStatus",
258+ "id": "%s",
259+ "state": "ready"
260+ }` , clusterId )
261+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusOK , statusBody ))
262+ t .ApiServer .AppendHandlers (RespondWithJSON (
263+ http .StatusOK , test .FormatClusterList ([]* cmv1.Cluster {clusterReady })))
264+ t .ApiServer .AppendHandlers (RespondWithJSON (http .StatusForbidden , `{
265+ "kind": "Error",
266+ "id": "403",
267+ "href": "/api/clusters_mgmt/v1/errors/403",
268+ "code": "CLUSTERS-MGMT-403",
269+ "reason": "forbidden"
270+ }` ))
271+
272+ stdout , stderr , err := test .RunWithOutputCaptureAndArgv (runWithRuntime , t .RosaRuntime , Cmd , & argv )
273+ Expect (err ).To (HaveOccurred ())
274+ Expect (stderr ).To (BeEmpty ())
275+ Expect (stdout ).To (BeEmpty ())
276+ Expect (err .Error ()).To (ContainSubstring ("forbidden" ))
277+ })
24278 })
25279
26280 Context ("handleClusterDelete" , func () {
0 commit comments