diff --git a/api/http/handler/endpoints/endpoint_list.go b/api/http/handler/endpoints/endpoint_list.go index 79bcd9ead..eba9a4c23 100644 --- a/api/http/handler/endpoints/endpoint_list.go +++ b/api/http/handler/endpoints/endpoint_list.go @@ -66,6 +66,11 @@ func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *ht return httperror.InternalServerError("Unable to retrieve environment groups from the database", err) } + edgeGroups, err := handler.DataStore.EdgeGroup().ReadAll() + if err != nil { + return httperror.InternalServerError("Unable to retrieve edge groups from the database", err) + } + endpoints, err := handler.DataStore.Endpoint().Endpoints() if err != nil { return httperror.InternalServerError("Unable to retrieve environments from the database", err) @@ -88,7 +93,7 @@ func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *ht filteredEndpoints := security.FilterEndpoints(endpoints, endpointGroups, securityContext) - filteredEndpoints, totalAvailableEndpoints, err := handler.filterEndpointsByQuery(filteredEndpoints, query, endpointGroups, settings) + filteredEndpoints, totalAvailableEndpoints, err := handler.filterEndpointsByQuery(filteredEndpoints, query, endpointGroups, edgeGroups, settings) if err != nil { return httperror.InternalServerError("Unable to filter endpoints", err) } diff --git a/api/http/handler/endpoints/filter.go b/api/http/handler/endpoints/filter.go index 0397ee52d..3d071afc1 100644 --- a/api/http/handler/endpoints/filter.go +++ b/api/http/handler/endpoints/filter.go @@ -118,7 +118,13 @@ func parseQuery(r *http.Request) (EnvironmentsQuery, error) { }, nil } -func (handler *Handler) filterEndpointsByQuery(filteredEndpoints []portainer.Endpoint, query EnvironmentsQuery, groups []portainer.EndpointGroup, settings *portainer.Settings) ([]portainer.Endpoint, int, error) { +func (handler *Handler) filterEndpointsByQuery( + filteredEndpoints []portainer.Endpoint, + query EnvironmentsQuery, + groups []portainer.EndpointGroup, + edgeGroups []portainer.EdgeGroup, + settings *portainer.Settings, +) ([]portainer.Endpoint, int, error) { totalAvailableEndpoints := len(filteredEndpoints) if len(query.endpointIds) > 0 { @@ -190,7 +196,7 @@ func (handler *Handler) filterEndpointsByQuery(filteredEndpoints []portainer.End tagsMap[tag.ID] = tag.Name } - filteredEndpoints = filterEndpointsBySearchCriteria(filteredEndpoints, groups, tagsMap, query.search) + filteredEndpoints = filterEndpointsBySearchCriteria(filteredEndpoints, groups, edgeGroups, tagsMap, query.search) } if len(query.types) > 0 { @@ -285,7 +291,13 @@ func filterEndpointsByGroupIDs(endpoints []portainer.Endpoint, endpointGroupIDs return endpoints[:n] } -func filterEndpointsBySearchCriteria(endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup, tagsMap map[portainer.TagID]string, searchCriteria string) []portainer.Endpoint { +func filterEndpointsBySearchCriteria( + endpoints []portainer.Endpoint, + endpointGroups []portainer.EndpointGroup, + edgeGroups []portainer.EdgeGroup, + tagsMap map[portainer.TagID]string, + searchCriteria string, +) []portainer.Endpoint { n := 0 for _, endpoint := range endpoints { endpointTags := convertTagIDsToTags(tagsMap, endpoint.TagIDs) @@ -300,6 +312,11 @@ func filterEndpointsBySearchCriteria(endpoints []portainer.Endpoint, endpointGro endpoints[n] = endpoint n++ } + + if edgeGroupMatchSearchCriteria(&endpoint, edgeGroups, searchCriteria) { + endpoints[n] = endpoint + n++ + } } return endpoints[:n] @@ -378,6 +395,24 @@ func endpointGroupMatchSearchCriteria(endpoint *portainer.Endpoint, endpointGrou return false } +func edgeGroupMatchSearchCriteria( + endpoint *portainer.Endpoint, + edgeGroups []portainer.EdgeGroup, + searchCriteria string, +) bool { + for _, edgeGroup := range edgeGroups { + for _, endpointID := range edgeGroup.Endpoints { + if endpointID == endpoint.ID { + if strings.Contains(strings.ToLower(edgeGroup.Name), searchCriteria) { + return true + } + } + } + } + + return false +} + func filterEndpointsByTypes(endpoints []portainer.Endpoint, endpointTypes []portainer.EndpointType) []portainer.Endpoint { typeSet := map[portainer.EndpointType]bool{} for _, endpointType := range endpointTypes { diff --git a/api/http/handler/endpoints/filter_test.go b/api/http/handler/endpoints/filter_test.go index f98ddd20f..aa8a50913 100644 --- a/api/http/handler/endpoints/filter_test.go +++ b/api/http/handler/endpoints/filter_test.go @@ -158,7 +158,13 @@ func runTests(tests []filterTest, t *testing.T, handler *Handler, endpoints []po func runTest(t *testing.T, test filterTest, handler *Handler, endpoints []portainer.Endpoint) { is := assert.New(t) - filteredEndpoints, _, err := handler.filterEndpointsByQuery(endpoints, test.query, []portainer.EndpointGroup{}, &portainer.Settings{}) + filteredEndpoints, _, err := handler.filterEndpointsByQuery( + endpoints, + test.query, + []portainer.EndpointGroup{}, + []portainer.EdgeGroup{}, + &portainer.Settings{}, + ) is.NoError(err) diff --git a/app/react/edge/edge-devices/WaitingRoomView/Datatable/useEnvironments.ts b/app/react/edge/edge-devices/WaitingRoomView/Datatable/useEnvironments.ts index dcf0da69d..8e02be406 100644 --- a/app/react/edge/edge-devices/WaitingRoomView/Datatable/useEnvironments.ts +++ b/app/react/edge/edge-devices/WaitingRoomView/Datatable/useEnvironments.ts @@ -70,6 +70,7 @@ export function useEnvironments({ select: (groups) => Object.fromEntries(groups.map((g) => [g.Id, g.Name] as const)), }); + const environmentEdgeGroupsQuery = useEdgeGroups({ select: (groups) => _.groupBy( @@ -80,6 +81,7 @@ export function useEnvironments({ (env) => env.id ), }); + const tagsQuery = useTags({ select: (tags) => Object.fromEntries(tags.map((tag) => [tag.ID, tag.Name] as const)),