feat(endpoints): filter by ids and/or tag ids (#3690)

* feat(endpoints): add filter by tagIds

* refactor(endpoints): change endpoints service to query by tagIds

* fix(endpoints): filter by tags

* feat(endpoints): filter by endpoint groups tags

* feat(endpoints): filter by ids
pull/3692/head^2
Chaim Lev-Ari 2020-04-08 12:14:50 +03:00 committed by GitHub
parent df13f3b4cc
commit 2542d30a09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 6 deletions

View File

@ -30,6 +30,12 @@ func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *ht
limit, _ := request.RetrieveNumericQueryParameter(r, "limit", true)
endpointType, _ := request.RetrieveNumericQueryParameter(r, "type", true)
var tagIDs []portainer.TagID
request.RetrieveJSONQueryParameter(r, "tagIds", &tagIDs, true)
var endpointIDs []portainer.EndpointID
request.RetrieveJSONQueryParameter(r, "endpointIds", &endpointIDs, true)
endpointGroups, err := handler.EndpointGroupService.EndpointGroups()
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve endpoint groups from the database", err}
@ -47,6 +53,10 @@ func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *ht
filteredEndpoints := security.FilterEndpoints(endpoints, endpointGroups, securityContext)
if endpointIDs != nil {
filteredEndpoints = filteredEndpointsByIds(filteredEndpoints, endpointIDs)
}
if groupID != 0 {
filteredEndpoints = filterEndpointsByGroupID(filteredEndpoints, portainer.EndpointGroupID(groupID))
}
@ -67,6 +77,10 @@ func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *ht
filteredEndpoints = filterEndpointsByType(filteredEndpoints, portainer.EndpointType(endpointType))
}
if tagIDs != nil {
filteredEndpoints = filteredEndpointsByTags(filteredEndpoints, tagIDs, endpointGroups)
}
filteredEndpointCount := len(filteredEndpoints)
paginatedEndpoints := paginateEndpoints(filteredEndpoints, start, limit)
@ -187,3 +201,58 @@ func convertTagIDsToTags(tagsMap map[portainer.TagID]string, tagIDs []portainer.
}
return tags
}
func filteredEndpointsByTags(endpoints []portainer.Endpoint, tagIDs []portainer.TagID, endpointGroups []portainer.EndpointGroup) []portainer.Endpoint {
filteredEndpoints := make([]portainer.Endpoint, 0)
for _, endpoint := range endpoints {
missingTags := make(map[portainer.TagID]bool)
for _, tagID := range tagIDs {
missingTags[tagID] = true
}
for _, tagID := range endpoint.TagIDs {
if missingTags[tagID] {
delete(missingTags, tagID)
}
}
missingTags = endpointGroupHasTags(endpoint.GroupID, endpointGroups, missingTags)
if len(missingTags) == 0 {
filteredEndpoints = append(filteredEndpoints, endpoint)
}
}
return filteredEndpoints
}
func endpointGroupHasTags(groupID portainer.EndpointGroupID, groups []portainer.EndpointGroup, missingTags map[portainer.TagID]bool) map[portainer.TagID]bool {
var endpointGroup portainer.EndpointGroup
for _, group := range groups {
if group.ID == groupID {
endpointGroup = group
break
}
}
for _, tagID := range endpointGroup.TagIDs {
if missingTags[tagID] {
delete(missingTags, tagID)
}
}
return missingTags
}
func filteredEndpointsByIds(endpoints []portainer.Endpoint, ids []portainer.EndpointID) []portainer.Endpoint {
filteredEndpoints := make([]portainer.Endpoint, 0)
idsSet := make(map[portainer.EndpointID]bool)
for _, id := range ids {
idsSet[id] = true
}
for _, endpoint := range endpoints {
if idsSet[endpoint.ID] {
filteredEndpoints = append(filteredEndpoints, endpoint)
}
}
return filteredEndpoints
}

View File

@ -8,8 +8,8 @@ function EndpointServiceFactory($q, Endpoints, FileUploadService) {
return Endpoints.get({id: endpointID}).$promise;
};
service.endpoints = function(start, limit, search) {
return Endpoints.query({start, limit, search}).$promise;
service.endpoints = function(start, limit, { search, type, tagIds, endpointIds } = {}) {
return Endpoints.query({ start, limit, search, type, tagIds, endpointIds }).$promise;
};
service.snapshotEndpoints = function() {

View File

@ -22,10 +22,10 @@ function ($q, $scope, $state, EndpointService, GroupService, EndpointHelper, Not
};
$scope.getPaginatedEndpoints = getPaginatedEndpoints;
function getPaginatedEndpoints(lastId, limit, filter) {
function getPaginatedEndpoints(lastId, limit, search) {
const deferred = $q.defer();
$q.all({
endpoints: EndpointService.endpoints(lastId, limit, filter),
endpoints: EndpointService.endpoints(lastId, limit, { search }),
groups: GroupService.groups()
})
.then(function success(data) {

View File

@ -146,10 +146,10 @@ angular.module('portainer.app')
}
$scope.getPaginatedEndpoints = getPaginatedEndpoints;
function getPaginatedEndpoints(lastId, limit, filter) {
function getPaginatedEndpoints(lastId, limit, search) {
const deferred = $q.defer();
$q.all({
endpoints: EndpointService.endpoints(lastId, limit, filter),
endpoints: EndpointService.endpoints(lastId, limit, {search}),
groups: GroupService.groups()
})
.then(function success(data) {