mirror of https://github.com/portainer/portainer
132 lines
3.9 KiB
Go
132 lines
3.9 KiB
Go
package edgegroups
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"slices"
|
|
|
|
portainer "github.com/portainer/portainer/api"
|
|
"github.com/portainer/portainer/api/dataservices"
|
|
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
|
)
|
|
|
|
type decoratedEdgeGroup struct {
|
|
portainer.EdgeGroup
|
|
HasEdgeStack bool `json:"HasEdgeStack"`
|
|
HasEdgeJob bool `json:"HasEdgeJob"`
|
|
EndpointTypes []portainer.EndpointType
|
|
TrustedEndpoints []portainer.EndpointID `json:"TrustedEndpoints"`
|
|
}
|
|
|
|
// @id EdgeGroupList
|
|
// @summary list EdgeGroups
|
|
// @description **Access policy**: administrator
|
|
// @tags edge_groups
|
|
// @security ApiKeyAuth
|
|
// @security jwt
|
|
// @produce json
|
|
// @success 200 {array} decoratedEdgeGroup "EdgeGroups"
|
|
// @failure 500
|
|
// @failure 503 "Edge compute features are disabled"
|
|
// @router /edge_groups [get]
|
|
func (handler *Handler) edgeGroupList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
|
var decoratedEdgeGroups []decoratedEdgeGroup
|
|
var err error
|
|
|
|
err = handler.DataStore.ViewTx(func(tx dataservices.DataStoreTx) error {
|
|
decoratedEdgeGroups, err = getEdgeGroupList(tx)
|
|
return err
|
|
})
|
|
|
|
return txResponse(w, decoratedEdgeGroups, err)
|
|
}
|
|
|
|
func getEdgeGroupList(tx dataservices.DataStoreTx) ([]decoratedEdgeGroup, error) {
|
|
edgeGroups, err := tx.EdgeGroup().ReadAll()
|
|
if err != nil {
|
|
return nil, httperror.InternalServerError("Unable to retrieve Edge groups from the database", err)
|
|
}
|
|
|
|
edgeStacks, err := tx.EdgeStack().EdgeStacks()
|
|
if err != nil {
|
|
return nil, httperror.InternalServerError("Unable to retrieve Edge stacks from the database", err)
|
|
}
|
|
|
|
usedEdgeGroups := make(map[portainer.EdgeGroupID]bool)
|
|
|
|
for _, stack := range edgeStacks {
|
|
for _, groupID := range stack.EdgeGroups {
|
|
usedEdgeGroups[groupID] = true
|
|
}
|
|
}
|
|
|
|
edgeJobs, err := tx.EdgeJob().ReadAll()
|
|
if err != nil {
|
|
return nil, httperror.InternalServerError("Unable to retrieve Edge jobs from the database", err)
|
|
}
|
|
|
|
decoratedEdgeGroups := []decoratedEdgeGroup{}
|
|
for _, orgEdgeGroup := range edgeGroups {
|
|
usedByEdgeJob := false
|
|
for _, edgeJob := range edgeJobs {
|
|
if slices.Contains(edgeJob.EdgeGroups, portainer.EdgeGroupID(orgEdgeGroup.ID)) {
|
|
usedByEdgeJob = true
|
|
break
|
|
}
|
|
}
|
|
|
|
edgeGroup := decoratedEdgeGroup{
|
|
EdgeGroup: orgEdgeGroup,
|
|
EndpointTypes: []portainer.EndpointType{},
|
|
}
|
|
if edgeGroup.Dynamic {
|
|
endpointIDs, err := GetEndpointsByTags(tx, edgeGroup.TagIDs, edgeGroup.PartialMatch)
|
|
if err != nil {
|
|
return nil, httperror.InternalServerError("Unable to retrieve environments and environment groups for Edge group", err)
|
|
}
|
|
|
|
edgeGroup.Endpoints = endpointIDs
|
|
edgeGroup.TrustedEndpoints = endpointIDs
|
|
} else {
|
|
trustedEndpoints, err := getTrustedEndpoints(tx, edgeGroup.Endpoints)
|
|
if err != nil {
|
|
return nil, httperror.InternalServerError("Unable to retrieve environments for Edge group", err)
|
|
}
|
|
|
|
edgeGroup.TrustedEndpoints = trustedEndpoints
|
|
}
|
|
|
|
endpointTypes, err := getEndpointTypes(tx, edgeGroup.Endpoints)
|
|
if err != nil {
|
|
return nil, httperror.InternalServerError("Unable to retrieve environment types for Edge group", err)
|
|
}
|
|
|
|
edgeGroup.EndpointTypes = endpointTypes
|
|
edgeGroup.HasEdgeStack = usedEdgeGroups[edgeGroup.ID]
|
|
edgeGroup.HasEdgeJob = usedByEdgeJob
|
|
|
|
decoratedEdgeGroups = append(decoratedEdgeGroups, edgeGroup)
|
|
}
|
|
|
|
return decoratedEdgeGroups, nil
|
|
}
|
|
|
|
func getEndpointTypes(tx dataservices.DataStoreTx, endpointIds []portainer.EndpointID) ([]portainer.EndpointType, error) {
|
|
typeSet := map[portainer.EndpointType]bool{}
|
|
for _, endpointID := range endpointIds {
|
|
endpoint, err := tx.Endpoint().Endpoint(endpointID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed fetching environment: %w", err)
|
|
}
|
|
|
|
typeSet[endpoint.Type] = true
|
|
}
|
|
|
|
endpointTypes := make([]portainer.EndpointType, 0, len(typeSet))
|
|
for endpointType := range typeSet {
|
|
endpointTypes = append(endpointTypes, endpointType)
|
|
}
|
|
|
|
return endpointTypes, nil
|
|
}
|