@@ -201,15 +201,42 @@ func (r *GrafanaServiceAccountReconciler) finalize(ctx context.Context, cr *v1be
201
201
return err
202
202
}
203
203
204
- // Try to create client and remove account if Grafana instance exists
205
204
gClient , err := client2 .NewGeneratedGrafanaClient (ctx , r .Client , grafana )
206
205
if err != nil {
207
206
return fmt .Errorf ("creating Grafana client: %w" , err )
208
207
}
209
208
210
- err = r .removeAccount (ctx , gClient , cr )
209
+ _ , err = gClient .ServiceAccounts .DeleteServiceAccountWithParams ( // nolint:errcheck
210
+ service_accounts .
211
+ NewDeleteServiceAccountParamsWithContext (ctx ).
212
+ WithServiceAccountID (cr .Status .Account .ID ),
213
+ )
211
214
if err != nil {
212
- return fmt .Errorf ("removing service account: %w" , err )
215
+ // ATM, service_accounts.DeleteServiceAccountNotFound doesn't have Is, Unwrap, Unwrap.
216
+ // So, we cannot rely only on errors.Is().
217
+ _ , ok := err .(* service_accounts.DeleteServiceAccountNotFound ) // nolint:errorlint
218
+ if ok || errors .Is (err , service_accounts .NewDeleteServiceAccountNotFound ()) {
219
+ logf .FromContext (ctx ).Info ("service account not found, skipping removal" ,
220
+ "serviceAccountID" , cr .Status .Account .ID ,
221
+ "serviceAccountName" , cr .Spec .Name ,
222
+ )
223
+
224
+ return nil
225
+ }
226
+
227
+ // TODO: Grafana Operator currently deploys Grafana 11.3.0 (see controllers/config/operator_constants.go#L6).
228
+ // Until Grafana 12.0.2 there was no reliable way to detect a 404 when deleting a service account.
229
+ // The API still returns 500 (see https://github.com/grafana/grafana/issues/106618).
230
+ //
231
+ // Once we upgrade to Grafana > 12.0.2 and bump github.com/grafana/grafana-openapi-client-go,
232
+ // we can handle the real 404 explicitly.
233
+ //
234
+ // In the meantime we treat any non-nil error from the delete call as "already removed" and just log it for visibility.
235
+ logf .FromContext (ctx ).Error (err , "failed to delete service account (may already be deleted)" ,
236
+ "serviceAccountID" , cr .Status .Account .ID ,
237
+ "serviceAccountName" , cr .Spec .Name ,
238
+ )
239
+ // return fmt.Errorf("deleting service account %q: %w", status.SpecID, err)
213
240
}
214
241
215
242
return nil
@@ -691,70 +718,6 @@ func (r *GrafanaServiceAccountReconciler) upsertAccount(
691
718
return nil
692
719
}
693
720
694
- func (r * GrafanaServiceAccountReconciler ) removeAccountSecrets (
695
- ctx context.Context ,
696
- cr * v1beta1.GrafanaServiceAccount ,
697
- ) error {
698
- for i := range cr .Status .Account .Tokens {
699
- err := r .removeTokenSecret (ctx , & cr .Status .Account .Tokens [i ])
700
- if err != nil {
701
- return fmt .Errorf ("removing token secret %q: %w" , cr .Status .Account .Tokens [i ].Name , err )
702
- }
703
- }
704
-
705
- return nil
706
- }
707
-
708
- func (r * GrafanaServiceAccountReconciler ) removeAccount (
709
- ctx context.Context ,
710
- gClient * genapi.GrafanaHTTPAPI ,
711
- cr * v1beta1.GrafanaServiceAccount ,
712
- ) error {
713
- // We don't need to remove tokens, because they will be removed automatically.
714
- // The only thing we need to do is to remove the secrets.
715
- err := r .removeAccountSecrets (ctx , cr )
716
- if err != nil {
717
- return fmt .Errorf ("removing secrets: %w" , err )
718
- }
719
-
720
- cr .Status .Account .Tokens = nil
721
-
722
- _ , err = gClient .ServiceAccounts .DeleteServiceAccountWithParams ( // nolint:errcheck
723
- service_accounts .
724
- NewDeleteServiceAccountParamsWithContext (ctx ).
725
- WithServiceAccountID (cr .Status .Account .ID ),
726
- )
727
- if err != nil {
728
- // ATM, service_accounts.DeleteServiceAccountNotFound doesn't have Is, Unwrap, Unwrap.
729
- // So, we cannot rely only on errors.Is().
730
- _ , ok := err .(* service_accounts.DeleteServiceAccountNotFound ) // nolint:errorlint
731
- if ok || errors .Is (err , service_accounts .NewDeleteServiceAccountNotFound ()) {
732
- logf .FromContext (ctx ).Info ("service account not found, skipping removal" ,
733
- "serviceAccountID" , cr .Status .Account .ID ,
734
- "serviceAccountName" , cr .Spec .Name ,
735
- )
736
-
737
- return nil
738
- }
739
-
740
- // TODO: Grafana Operator currently deploys Grafana 11.3.0 (see controllers/config/operator_constants.go#L6).
741
- // Until Grafana 12.0.2 there was no reliable way to detect a 404 when deleting a service account.
742
- // The API still returns 500 (see https://github.com/grafana/grafana/issues/106618).
743
- //
744
- // Once we upgrade to Grafana > 12.0.2 and bump github.com/grafana/grafana-openapi-client-go,
745
- // we can handle the real 404 explicitly.
746
- //
747
- // In the meantime we treat any non-nil error from the delete call as "already removed" and just log it for visibility.
748
- logf .FromContext (ctx ).Error (err , "failed to delete service account (may already be deleted)" ,
749
- "serviceAccountID" , cr .Status .Account .ID ,
750
- "serviceAccountName" , cr .Spec .Name ,
751
- )
752
- // return fmt.Errorf("deleting service account %q: %w", status.SpecID, err)
753
- }
754
-
755
- return nil
756
- }
757
-
758
721
func (r * GrafanaServiceAccountReconciler ) removeTokenSecret (
759
722
ctx context.Context ,
760
723
tokenStatus * v1beta1.GrafanaServiceAccountTokenStatus ,
0 commit comments