mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 05:45:22 +02:00
fix(endpointedge): optimize buildSchedules() BE-12099 (#955)
This commit is contained in:
parent
a46db61c4c
commit
e9ce3d2213
4 changed files with 114 additions and 26 deletions
|
@ -170,7 +170,7 @@ func (handler *Handler) inspectStatus(tx dataservices.DataStoreTx, r *http.Reque
|
||||||
Credentials: tunnel.Credentials,
|
Credentials: tunnel.Credentials,
|
||||||
}
|
}
|
||||||
|
|
||||||
schedules, handlerErr := handler.buildSchedules(tx, endpoint.ID)
|
schedules, handlerErr := handler.buildSchedules(tx, endpoint)
|
||||||
if handlerErr != nil {
|
if handlerErr != nil {
|
||||||
return nil, handlerErr
|
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{}
|
schedules := []edgeJobResponse{}
|
||||||
|
|
||||||
edgeJobs, err := tx.EdgeJob().ReadAll()
|
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)
|
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 {
|
for _, job := range edgeJobs {
|
||||||
_, endpointHasJob := job.Endpoints[endpointID]
|
_, endpointHasJob := job.Endpoints[endpoint.ID]
|
||||||
if !endpointHasJob {
|
if !endpointHasJob {
|
||||||
for _, edgeGroupID := range job.EdgeGroups {
|
for _, edgeGroupID := range job.EdgeGroups {
|
||||||
member, _, err := edge.EndpointInEdgeGroup(tx, endpointID, edgeGroupID)
|
member, _, err := edge.EndpointInEdgeGroup(tx, endpoint, edgeGroupID, endpointGroups)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, httperror.InternalServerError("Unable to retrieve relations", err)
|
return nil, httperror.InternalServerError("Unable to retrieve relations", err)
|
||||||
} else if member {
|
} else if member {
|
||||||
|
@ -236,10 +241,10 @@ func (handler *Handler) buildSchedules(tx dataservices.DataStoreTx, endpointID p
|
||||||
}
|
}
|
||||||
|
|
||||||
var collectLogs bool
|
var collectLogs bool
|
||||||
if _, ok := job.GroupLogsCollection[endpointID]; ok {
|
if _, ok := job.GroupLogsCollection[endpoint.ID]; ok {
|
||||||
collectLogs = job.GroupLogsCollection[endpointID].CollectLogs
|
collectLogs = job.GroupLogsCollection[endpoint.ID].CollectLogs
|
||||||
} else {
|
} else {
|
||||||
collectLogs = job.Endpoints[endpointID].CollectLogs
|
collectLogs = job.Endpoints[endpoint.ID].CollectLogs
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule := edgeJobResponse{
|
schedule := edgeJobResponse{
|
||||||
|
|
|
@ -4,13 +4,22 @@ import (
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/dataservices"
|
"github.com/portainer/portainer/api/dataservices"
|
||||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||||
|
"github.com/portainer/portainer/api/roar"
|
||||||
"github.com/portainer/portainer/api/tag"
|
"github.com/portainer/portainer/api/tag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EdgeGroupRelatedEndpoints returns a list of environments(endpoints) related to this Edge group
|
// 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 {
|
func EdgeGroupRelatedEndpoints(edgeGroup *portainer.EdgeGroup, endpoints []portainer.Endpoint, endpointGroups []portainer.EndpointGroup) []portainer.EndpointID {
|
||||||
if !edgeGroup.Dynamic {
|
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{}
|
endpointGroupsMap := map[portainer.EndpointGroupID]*portainer.EndpointGroup{}
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package edge
|
package edge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"slices"
|
|
||||||
|
|
||||||
portainer "github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/dataservices"
|
"github.com/portainer/portainer/api/dataservices"
|
||||||
|
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// EndpointRelatedEdgeStacks returns a list of Edge stacks related to this Environment(Endpoint)
|
// 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
|
// EndpointInEdgeGroup returns true and the edge group name if the endpoint is in the edge group
|
||||||
func EndpointInEdgeGroup(
|
func EndpointInEdgeGroup(
|
||||||
tx dataservices.DataStoreTx,
|
tx dataservices.DataStoreTx,
|
||||||
endpointID portainer.EndpointID,
|
endpoint *portainer.Endpoint,
|
||||||
edgeGroupID portainer.EdgeGroupID,
|
edgeGroupID portainer.EdgeGroupID,
|
||||||
|
endpointGroups []portainer.EndpointGroup,
|
||||||
) (bool, string, error) {
|
) (bool, string, error) {
|
||||||
endpointIDs, err := GetEndpointsFromEdgeGroups(
|
if !endpointutils.IsEdgeEndpoint(endpoint) || !endpoint.UserTrusted {
|
||||||
[]portainer.EdgeGroupID{edgeGroupID}, tx,
|
return false, "", nil
|
||||||
)
|
}
|
||||||
|
|
||||||
|
edgeGroup, err := tx.EdgeGroup().Read(edgeGroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return false, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if slices.Contains(endpointIDs, endpointID) {
|
r := EdgeGroupRelatedEndpoints(edgeGroup, []portainer.Endpoint{*endpoint}, endpointGroups)
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if len(r) > 0 {
|
||||||
return true, edgeGroup.Name, nil
|
return true, edgeGroup.Name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
82
api/internal/edge/endpoint_test.go
Normal file
82
api/internal/edge/endpoint_test.go
Normal 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)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue