@@ -45,6 +45,7 @@ import (
45
45
"github.com/spf13/cobra"
46
46
v1 "k8s.io/api/core/v1"
47
47
rbacv1 "k8s.io/api/rbac/v1"
48
+ kerrors "k8s.io/apimachinery/pkg/api/errors"
48
49
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
49
50
)
50
51
@@ -191,15 +192,8 @@ func NewRuntimeInstallCommand() *cobra.Command {
191
192
}
192
193
193
194
func RunRuntimeInstall (ctx context.Context , opts * RuntimeInstallOptions ) error {
194
- runtimes , err := cfConfig .NewClient ().V2 ().Runtime ().List (ctx )
195
- if err != nil {
196
- return err
197
- }
198
-
199
- for _ , rt := range runtimes {
200
- if rt .Metadata .Name == opts .RuntimeName {
201
- return fmt .Errorf ("failed to create runtime: %s. A runtime by this name already exists" , opts .RuntimeName )
202
- }
195
+ if err := preInstallationChecks (ctx , opts ); err != nil {
196
+ return fmt .Errorf ("pre installation checks failed: %w" , err )
203
197
}
204
198
205
199
rt , err := runtime .Download (opts .Version , opts .RuntimeName )
@@ -290,6 +284,75 @@ func RunRuntimeInstall(ctx context.Context, opts *RuntimeInstallOptions) error {
290
284
return nil
291
285
}
292
286
287
+ func preInstallationChecks (ctx context.Context , opts * RuntimeInstallOptions ) error {
288
+ log .G (ctx ).Debug ("running pre-installation checks..." )
289
+
290
+ if err := checkRuntimeCollisions (ctx , opts .RuntimeName , opts .KubeFactory ); err != nil {
291
+ return fmt .Errorf ("runtime collision check failed: %w" , err )
292
+ }
293
+
294
+ if err := checkExistingRuntimes (ctx , opts .RuntimeName ); err != nil {
295
+ return fmt .Errorf ("existing runtime check failed: %w" , err )
296
+ }
297
+
298
+ return nil
299
+ }
300
+
301
+ func checkRuntimeCollisions (ctx context.Context , runtime string , kube kube.Factory ) error {
302
+ log .G (ctx ).Debug ("checking for argocd collisions in cluster" )
303
+
304
+ cs , err := kube .KubernetesClientSet ()
305
+ if err != nil {
306
+ return fmt .Errorf ("failed to build kubernetes clientset: %w" , err )
307
+ }
308
+
309
+ crb , err := cs .RbacV1 ().ClusterRoleBindings ().Get (ctx , store .Get ().ArgoCDServerName , metav1.GetOptions {})
310
+ if err != nil {
311
+ if kerrors .IsNotFound (err ) {
312
+ return nil // no collision
313
+ }
314
+
315
+ return fmt .Errorf ("failed to get cluster-role-binding '%s': %w" , store .Get ().ArgoCDServerName , err )
316
+ }
317
+
318
+ log .G (ctx ).Debug ("argocd cluster-role-binding found" )
319
+
320
+ if len (crb .Subjects ) == 0 {
321
+ return nil // no collision
322
+ }
323
+
324
+ subjNamespace := crb .Subjects [0 ].Namespace
325
+
326
+ // check if some argocd is actually using this crb
327
+ _ , err = cs .AppsV1 ().Deployments (subjNamespace ).Get (ctx , store .Get ().ArgoCDServerName , metav1.GetOptions {})
328
+ if err != nil {
329
+ if kerrors .IsNotFound (err ) {
330
+ log .G (ctx ).Debug ("argocd cluster-role-binding subject does not exist, no collision" )
331
+
332
+ return nil // no collision
333
+ }
334
+
335
+ return fmt .Errorf ("failed to get deployment '%s': %w" , store .Get ().ArgoCDServerName , err )
336
+ }
337
+
338
+ return fmt .Errorf ("argo-cd is already installed on this cluster in namespace '%s', you need to uninstall it first" , subjNamespace )
339
+ }
340
+
341
+ func checkExistingRuntimes (ctx context.Context , runtime string ) error {
342
+ runtimes , err := cfConfig .NewClient ().V2 ().Runtime ().List (ctx )
343
+ if err != nil {
344
+ return fmt .Errorf ("failed to list runtimes: %w" , err )
345
+ }
346
+
347
+ for _ , rt := range runtimes {
348
+ if rt .Metadata .Name == runtime {
349
+ return fmt .Errorf ("runtime '%s' already exists" , runtime )
350
+ }
351
+ }
352
+
353
+ return nil
354
+ }
355
+
293
356
func intervalCheckIsRuntimePersisted (milliseconds int , ctx context.Context , runtimeName string , wg * sync.WaitGroup ) {
294
357
interval := time .Duration (milliseconds ) * time .Millisecond
295
358
ticker := time .NewTicker (interval )
0 commit comments