1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 13:55:21 +02:00

fix(endpointedge): optimize buildSchedules() BE-12099 (#955)

This commit is contained in:
andres-portainer 2025-07-28 19:19:07 -03:00 committed by GitHub
parent a46db61c4c
commit e9ce3d2213
4 changed files with 114 additions and 26 deletions

View file

@ -170,7 +170,7 @@ func (handler *Handler) inspectStatus(tx dataservices.DataStoreTx, r *http.Reque
Credentials: tunnel.Credentials,
}
schedules, handlerErr := handler.buildSchedules(tx, endpoint.ID)
schedules, handlerErr := handler.buildSchedules(tx, endpoint)
if handlerErr != nil {
return nil, handlerErr
}
@ -208,7 +208,7 @@ func parseAgentPlatform(r *http.Request) (portainer.EndpointType, error) {
}
}
func (handler *Handler) buildSchedules(tx dataservices.DataStoreTx, endpointID portainer.EndpointID) ([]edgeJobResponse, *httperror.HandlerError) {
func (handler *Handler) buildSchedules(tx dataservices.DataStoreTx, endpoint *portainer.Endpoint) ([]edgeJobResponse, *httperror.HandlerError) {
schedules := []edgeJobResponse{}
edgeJobs, err := tx.EdgeJob().ReadAll()
@ -216,11 +216,16 @@ func (handler *Handler) buildSchedules(tx dataservices.DataStoreTx, endpointID p
return nil, httperror.InternalServerError("Unable to retrieve Edge Jobs", err)
}
endpointGroups, err := tx.EndpointGroup().ReadAll()
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve endpoint groups", err)
}
for _, job := range edgeJobs {
_, endpointHasJob := job.Endpoints[endpointID]
_, endpointHasJob := job.Endpoints[endpoint.ID]
if !endpointHasJob {
for _, edgeGroupID := range job.EdgeGroups {
member, _, err := edge.EndpointInEdgeGroup(tx, endpointID, edgeGroupID)
member, _, err := edge.EndpointInEdgeGroup(tx, endpoint, edgeGroupID, endpointGroups)
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve relations", err)
} else if member {
@ -236,10 +241,10 @@ func (handler *Handler) buildSchedules(tx dataservices.DataStoreTx, endpointID p
}
var collectLogs bool
if _, ok := job.GroupLogsCollection[endpointID]; ok {
collectLogs = job.GroupLogsCollection[endpointID].CollectLogs
if _, ok := job.GroupLogsCollection[endpoint.ID]; ok {
collectLogs = job.GroupLogsCollection[endpoint.ID].CollectLogs
} else {
collectLogs = job.Endpoints[endpointID].CollectLogs
collectLogs = job.Endpoints[endpoint.ID].CollectLogs
}
schedule := edgeJobResponse{

View file

@ -4,13 +4,22 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/portainer/portainer/api/roar"
"github.com/portainer/portainer/api/tag"
)
// EdgeGroupRelatedEndpoints returns a list of environments(endpoints) related to this Edge group
func EdgeGroupRelatedEndpoints(edgeGroup *portainer.EdgeGroup, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup) []portainer.EndpointID {
if !edgeGroup.Dynamic {
return edgeGroup.EndpointIDs.ToSlice()
var r roar.Roar[portainer.EndpointID]
for _, endpoint := range endpoints {
if edgeGroup.EndpointIDs.Contains(endpoint.ID) {
r.Add(endpoint.ID)
}
}
return r.ToSlice()
}
endpointGroupsMap := map[portainer.EndpointGroupID]*portainer.EndpointGroup{}

View file

@ -1,12 +1,9 @@
package edge
import (
"slices"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/rs/zerolog/log"
"github.com/portainer/portainer/api/internal/endpointutils"
)
// EndpointRelatedEdgeStacks returns a list of Edge stacks related to this Environment(Endpoint)
@ -47,27 +44,22 @@ func EffectiveCheckinInterval(tx dataservices.DataStoreTx, endpoint *portainer.E
// EndpointInEdgeGroup returns true and the edge group name if the endpoint is in the edge group
func EndpointInEdgeGroup(
tx dataservices.DataStoreTx,
endpointID portainer.EndpointID,
endpoint *portainer.Endpoint,
edgeGroupID portainer.EdgeGroupID,
endpointGroups []portainer.EndpointGroup,
) (bool, string, error) {
endpointIDs, err := GetEndpointsFromEdgeGroups(
[]portainer.EdgeGroupID{edgeGroupID}, tx,
)
if !endpointutils.IsEdgeEndpoint(endpoint) || !endpoint.UserTrusted {
return false, "", nil
}
edgeGroup, err := tx.EdgeGroup().Read(edgeGroupID)
if err != nil {
return false, "", err
}
if slices.Contains(endpointIDs, endpointID) {
edgeGroup, err := tx.EdgeGroup().Read(edgeGroupID)
if err != nil {
log.Warn().
Err(err).
Int("edgeGroupID", int(edgeGroupID)).
Msg("Unable to retrieve edge group")
return false, "", err
}
r := EdgeGroupRelatedEndpoints(edgeGroup, []portainer.Endpoint{*endpoint}, endpointGroups)
if len(r) > 0 {
return true, edgeGroup.Name, nil
}

View file

@ -0,0 +1,82 @@
package edge
import (
"testing"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/roar"
"github.com/stretchr/testify/require"
)
func TestEndpointInEdgeGroup(t *testing.T) {
_, store := datastore.MustNewTestStore(t, true, false)
endpointGroups := []portainer.EndpointGroup{{ID: 1, Name: "test-group"}}
endpoint := &portainer.Endpoint{
ID: 1,
Name: "test-endpoint",
Type: portainer.EdgeAgentOnDockerEnvironment,
UserTrusted: true,
GroupID: endpointGroups[0].ID,
}
edgeGroupID := portainer.EdgeGroupID(1)
untrustedEndpoint := &portainer.Endpoint{
ID: 2,
Name: "untrusted-endpoint",
Type: portainer.EdgeAgentOnDockerEnvironment,
UserTrusted: false,
GroupID: endpointGroups[0].ID,
}
nonEdgeEndpoint := &portainer.Endpoint{
ID: 2,
Name: "untrusted-endpoint",
Type: portainer.AgentOnDockerEnvironment,
UserTrusted: true,
GroupID: endpointGroups[0].ID,
}
err := store.EdgeGroup().Create(&portainer.EdgeGroup{
ID: edgeGroupID,
Name: "test-edge-group",
Dynamic: false,
EndpointIDs: roar.FromSlice([]portainer.EndpointID{endpoint.ID, untrustedEndpoint.ID}),
})
require.NoError(t, err)
// Related endpoint in a static edge group
inEdgeGroup, _, err := EndpointInEdgeGroup(store, endpoint, edgeGroupID, endpointGroups)
require.NoError(t, err)
require.True(t, inEdgeGroup)
// Unrelated endpoint in a static edge group
unrelatedEndpoint := &portainer.Endpoint{
ID: 3,
Name: "unrelated-endpoint",
Type: portainer.EdgeAgentOnDockerEnvironment,
UserTrusted: true,
GroupID: 0,
}
inEdgeGroup, _, err = EndpointInEdgeGroup(store, unrelatedEndpoint, edgeGroupID, endpointGroups)
require.NoError(t, err)
require.False(t, inEdgeGroup)
// Untrusted endpoint
inEdgeGroup, _, err = EndpointInEdgeGroup(store, untrustedEndpoint, edgeGroupID, endpointGroups)
require.NoError(t, err)
require.False(t, inEdgeGroup)
// Non-edge endpoint
inEdgeGroup, _, err = EndpointInEdgeGroup(store, nonEdgeEndpoint, edgeGroupID, endpointGroups)
require.NoError(t, err)
require.False(t, inEdgeGroup)
}