diff --git a/frontend/endpoints/destination_recognition/destination_finder.go b/frontend/endpoints/destination_recognition/destination_finder.go index 607c53549..4470d66e2 100644 --- a/frontend/endpoints/destination_recognition/destination_finder.go +++ b/frontend/endpoints/destination_recognition/destination_finder.go @@ -2,16 +2,14 @@ package destination_recognition import ( "github.com/gin-gonic/gin" + "github.com/odigos-io/odigos/common" + "github.com/odigos-io/odigos/frontend/kube" + "github.com/odigos-io/odigos/k8sutils/pkg/client" k8s "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -type DestinationType string - -const ( - JaegerDestinationType DestinationType = "jaeger" -) - -var SupportedDestinationType = []DestinationType{JaegerDestinationType} +var SupportedDestinationType = []common.DestinationType{common.JaegerDestinationType, common.ElasticsearchDestinationType} type DestinationDetails struct { Name string `json:"name"` @@ -36,32 +34,43 @@ func (d *DestinationFinder) fetchDestinationDetails(service k8s.Service) Destina } func GetAllPotentialDestinationDetails(ctx *gin.Context, namespaces []k8s.Namespace) ([]DestinationDetails, error) { - helmManagedServices, err := getAllHelmManagedServices(ctx, namespaces) - if err != nil { - return nil, err - } - var destinationFinder *DestinationFinder var destinationDetails []DestinationDetails - for _, service := range helmManagedServices { - for _, destinationType := range SupportedDestinationType { - destinationFinder = getDestinationFinder(destinationType) - if destinationFinder.isPotentialService(service) { - destinationDetails = append(destinationDetails, destinationFinder.fetchDestinationDetails(service)) - break - } - } + var err error + + for _, ns := range namespaces { + err = client.ListWithPages(client.DefaultPageSize, kube.DefaultClient.CoreV1().Services(ns.Name).List, + ctx, metav1.ListOptions{}, func(services *k8s.ServiceList) error { + for _, service := range services.Items { + for _, destinationType := range SupportedDestinationType { + destinationFinder = getDestinationFinder(destinationType) + if destinationFinder.isPotentialService(service) { + destinationDetails = append(destinationDetails, destinationFinder.fetchDestinationDetails(service)) + break + } + } + } + return nil + }) + } + + if err != nil { + return nil, err } return destinationDetails, nil } -func getDestinationFinder(destinationType DestinationType) *DestinationFinder { +func getDestinationFinder(destinationType common.DestinationType) *DestinationFinder { switch destinationType { - case JaegerDestinationType: + case common.JaegerDestinationType: return &DestinationFinder{ destinationFinder: &JaegerDestinationFinder{}, } + case common.ElasticsearchDestinationType: + return &DestinationFinder{ + destinationFinder: &ElasticSearchDestinationFinder{}, + } } return nil diff --git a/frontend/endpoints/destination_recognition/elasticsearch.go b/frontend/endpoints/destination_recognition/elasticsearch.go new file mode 100644 index 000000000..baf9505a0 --- /dev/null +++ b/frontend/endpoints/destination_recognition/elasticsearch.go @@ -0,0 +1,35 @@ +package destination_recognition + +import ( + "fmt" + "github.com/odigos-io/odigos/common" + k8s "k8s.io/api/core/v1" + "strings" +) + +type ElasticSearchDestinationFinder struct{} + +const ElasticSearchHttpPort int32 = 9200 +const ElasticSearchHttpUrlFormat = "https://%s.%s:%d" + +func (j *ElasticSearchDestinationFinder) isPotentialService(service k8s.Service) bool { + for _, port := range service.Spec.Ports { + if isElasticSearchService(port.Port, service.Name) { + return true + } + } + + return false +} + +func isElasticSearchService(portNumber int32, name string) bool { + return portNumber == ElasticSearchHttpPort && strings.Contains(name, string(common.ElasticsearchDestinationType)) +} + +func (j *ElasticSearchDestinationFinder) fetchDestinationDetails(service k8s.Service) DestinationDetails { + urlString := fmt.Sprintf(ElasticSearchHttpUrlFormat, service.Name, service.Namespace, ElasticSearchHttpPort) + return DestinationDetails{ + Name: string(common.ElasticsearchDestinationType), + UrlString: urlString, + } +} diff --git a/frontend/endpoints/destination_recognition/utils.go b/frontend/endpoints/destination_recognition/utils.go deleted file mode 100644 index 11484d386..000000000 --- a/frontend/endpoints/destination_recognition/utils.go +++ /dev/null @@ -1,42 +0,0 @@ -package destination_recognition - -import ( - "github.com/gin-gonic/gin" - "github.com/odigos-io/odigos/frontend/kube" - "github.com/odigos-io/odigos/k8sutils/pkg/client" - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func getAllHelmManagedServices(ctx *gin.Context, namespaces []v1.Namespace) ([]v1.Service, error) { - var helmManagedServices []v1.Service - var err error - for _, ns := range namespaces { - err = client.ListWithPages(client.DefaultPageSize, kube.DefaultClient.CoreV1().Services(ns.Name).List, - ctx, metav1.ListOptions{}, func(services *v1.ServiceList) error { - for _, service := range services.Items { - if isHelmManagedService(service) { - helmManagedServices = append(helmManagedServices, service) - } - } - return nil - }) - } - - if err != nil { - return nil, err - } - - return helmManagedServices, nil -} - -// isHelmManagedService checks if a Service was created by Helm -func isHelmManagedService(service v1.Service) bool { - annotations := service.GetAnnotations() - labels := service.GetLabels() - - _, hasHelmReleaseName := annotations["meta.helm.sh/release-name"] - managedByHelm := labels["app.kubernetes.io/managed-by"] == "Helm" - - return hasHelmReleaseName && managedByHelm -}