github.com/argoproj/argo-events@v1.9.1/controllers/eventbus/installer/installer.go (about) 1 package installer 2 3 import ( 4 "context" 5 "fmt" 6 7 "go.uber.org/zap" 8 "k8s.io/client-go/kubernetes" 9 "sigs.k8s.io/controller-runtime/pkg/client" 10 11 "github.com/argoproj/argo-events/common" 12 "github.com/argoproj/argo-events/controllers" 13 "github.com/argoproj/argo-events/pkg/apis/eventbus/v1alpha1" 14 eventsourcev1alpha1 "github.com/argoproj/argo-events/pkg/apis/eventsource/v1alpha1" 15 sensorv1alpha1 "github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1" 16 ) 17 18 // Installer is an interface for event bus installation 19 type Installer interface { 20 Install(ctx context.Context) (*v1alpha1.BusConfig, error) 21 // Uninsall only needs to handle those resources not cascade deleted. 22 // For example, undeleted PVCs not automatically deleted when deleting a StatefulSet 23 Uninstall(ctx context.Context) error 24 } 25 26 // Install function installs the event bus 27 func Install(ctx context.Context, eventBus *v1alpha1.EventBus, client client.Client, kubeClient kubernetes.Interface, config *controllers.GlobalConfig, logger *zap.SugaredLogger) error { 28 installer, err := getInstaller(eventBus, client, kubeClient, config, logger) 29 if err != nil { 30 logger.Errorw("failed to an installer", zap.Error(err)) 31 return err 32 } 33 busConfig, err := installer.Install(ctx) 34 if err != nil { 35 logger.Errorw("installation error", zap.Error(err)) 36 return err 37 } 38 eventBus.Status.Config = *busConfig 39 return nil 40 } 41 42 // GetInstaller returns Installer implementation 43 func getInstaller(eventBus *v1alpha1.EventBus, client client.Client, kubeClient kubernetes.Interface, config *controllers.GlobalConfig, logger *zap.SugaredLogger) (Installer, error) { 44 if nats := eventBus.Spec.NATS; nats != nil { 45 if nats.Exotic != nil { 46 return NewExoticNATSInstaller(eventBus, logger), nil 47 } else if nats.Native != nil { 48 return NewNATSInstaller(client, eventBus, config, getLabels(eventBus), kubeClient, logger), nil 49 } 50 } else if js := eventBus.Spec.JetStream; js != nil { 51 return NewJetStreamInstaller(client, eventBus, config, getLabels(eventBus), kubeClient, logger), nil 52 } else if kafka := eventBus.Spec.Kafka; kafka != nil { 53 return NewExoticKafkaInstaller(eventBus, logger), nil 54 } else if js := eventBus.Spec.JetStreamExotic; js != nil { 55 return NewExoticJetStreamInstaller(eventBus, logger), nil 56 } 57 return nil, fmt.Errorf("invalid eventbus spec") 58 } 59 60 func getLabels(bus *v1alpha1.EventBus) map[string]string { 61 return map[string]string{ 62 "controller": "eventbus-controller", 63 "eventbus-name": bus.Name, 64 common.LabelOwnerName: bus.Name, 65 } 66 } 67 68 // Uninstall function will be run before the EventBus object is deleted, 69 // usually it could be used to uninstall the extra resources who would not be cleaned 70 // up when an EventBus is deleted. Most of the time this is not needed as all 71 // the dependency resources should have been deleted by owner references cascade 72 // deletion, but things like PVC created by StatefulSet need to be cleaned up 73 // separately. 74 // 75 // It could also be used to check if the EventBus object can be safely deleted. 76 func Uninstall(ctx context.Context, eventBus *v1alpha1.EventBus, client client.Client, kubeClient kubernetes.Interface, config *controllers.GlobalConfig, logger *zap.SugaredLogger) error { 77 linkedEventSources, err := linkedEventSources(ctx, eventBus.Namespace, eventBus.Name, client) 78 if err != nil { 79 logger.Errorw("failed to query linked EventSources", zap.Error(err)) 80 return fmt.Errorf("failed to check if there is any EventSource linked, %w", err) 81 } 82 if linkedEventSources > 0 { 83 return fmt.Errorf("can not delete an EventBus with %v EventSources connected", linkedEventSources) 84 } 85 86 linkedSensors, err := linkedSensors(ctx, eventBus.Namespace, eventBus.Name, client) 87 if err != nil { 88 logger.Errorw("failed to query linked Sensors", zap.Error(err)) 89 return fmt.Errorf("failed to check if there is any Sensor linked, %w", err) 90 } 91 if linkedSensors > 0 { 92 return fmt.Errorf("can not delete an EventBus with %v Sensors connected", linkedSensors) 93 } 94 95 installer, err := getInstaller(eventBus, client, kubeClient, config, logger) 96 if err != nil { 97 logger.Errorw("failed to get an installer", zap.Error(err)) 98 return err 99 } 100 return installer.Uninstall(ctx) 101 } 102 103 func linkedEventSources(ctx context.Context, namespace, eventBusName string, c client.Client) (int, error) { 104 esl := &eventsourcev1alpha1.EventSourceList{} 105 if err := c.List(ctx, esl, &client.ListOptions{ 106 Namespace: namespace, 107 }); err != nil { 108 return 0, err 109 } 110 result := 0 111 for _, es := range esl.Items { 112 ebName := es.Spec.EventBusName 113 if ebName == "" { 114 ebName = common.DefaultEventBusName 115 } 116 if ebName == eventBusName { 117 result++ 118 } 119 } 120 return result, nil 121 } 122 123 func linkedSensors(ctx context.Context, namespace, eventBusName string, c client.Client) (int, error) { 124 sl := &sensorv1alpha1.SensorList{} 125 if err := c.List(ctx, sl, &client.ListOptions{ 126 Namespace: namespace, 127 }); err != nil { 128 return 0, err 129 } 130 result := 0 131 for _, s := range sl.Items { 132 sName := s.Spec.EventBusName 133 if sName == "" { 134 sName = common.DefaultEventBusName 135 } 136 if sName == eventBusName { 137 result++ 138 } 139 } 140 return result, nil 141 }