mirror of
https://github.com/portainer/portainer.git
synced 2025-08-02 20:35:25 +02:00
feat(edgejobs): support edge groups when using edge jobs EE-3873 (#8099)
This commit is contained in:
parent
9732d1b5d8
commit
e1b474d04f
29 changed files with 544 additions and 83 deletions
|
@ -9,6 +9,10 @@ import (
|
|||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/internal/edge"
|
||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||
"github.com/portainer/portainer/api/internal/maps"
|
||||
"github.com/portainer/portainer/api/internal/slices"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
@ -18,12 +22,13 @@ type edgeJobUpdatePayload struct {
|
|||
CronExpression *string
|
||||
Recurring *bool
|
||||
Endpoints []portainer.EndpointID
|
||||
EdgeGroups []portainer.EdgeGroupID
|
||||
FileContent *string
|
||||
}
|
||||
|
||||
func (payload *edgeJobUpdatePayload) Validate(r *http.Request) error {
|
||||
if payload.Name != nil && !govalidator.Matches(*payload.Name, `^[a-zA-Z0-9][a-zA-Z0-9_.-]+$`) {
|
||||
return errors.New("Invalid Edge job name format. Allowed characters are: [a-zA-Z0-9_.-]")
|
||||
return errors.New("invalid Edge job name format. Allowed characters are: [a-zA-Z0-9_.-]")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -80,16 +85,26 @@ func (handler *Handler) updateEdgeSchedule(edgeJob *portainer.EdgeJob, payload *
|
|||
edgeJob.Name = *payload.Name
|
||||
}
|
||||
|
||||
endpointsToAdd := map[portainer.EndpointID]bool{}
|
||||
endpointsToRemove := map[portainer.EndpointID]bool{}
|
||||
|
||||
if payload.Endpoints != nil {
|
||||
endpointsMap := map[portainer.EndpointID]portainer.EdgeJobEndpointMeta{}
|
||||
|
||||
newEndpoints := endpointutils.EndpointSet(payload.Endpoints)
|
||||
for endpointID := range edgeJob.Endpoints {
|
||||
if !newEndpoints[endpointID] {
|
||||
endpointsToRemove[endpointID] = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, endpointID := range payload.Endpoints {
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(endpointID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if endpoint.Type != portainer.EdgeAgentOnDockerEnvironment && endpoint.Type != portainer.EdgeAgentOnKubernetesEnvironment {
|
||||
if !endpointutils.IsEdgeEndpoint(endpoint) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -97,12 +112,73 @@ func (handler *Handler) updateEdgeSchedule(edgeJob *portainer.EdgeJob, payload *
|
|||
endpointsMap[endpointID] = meta
|
||||
} else {
|
||||
endpointsMap[endpointID] = portainer.EdgeJobEndpointMeta{}
|
||||
endpointsToAdd[endpointID] = true
|
||||
}
|
||||
}
|
||||
|
||||
edgeJob.Endpoints = endpointsMap
|
||||
}
|
||||
|
||||
if len(payload.EdgeGroups) == 0 && len(edgeJob.EdgeGroups) > 0 {
|
||||
endpoints, err := edge.GetEndpointsFromEdgeGroups(edgeJob.EdgeGroups, handler.DataStore)
|
||||
if err != nil {
|
||||
return errors.New("unable to get endpoints from edge groups")
|
||||
}
|
||||
|
||||
for _, endpointID := range endpoints {
|
||||
endpointsToRemove[portainer.EndpointID(endpointID)] = true
|
||||
}
|
||||
|
||||
edgeJob.EdgeGroups = nil
|
||||
}
|
||||
|
||||
edgeGroupsToAdd := []portainer.EdgeGroupID{}
|
||||
edgeGroupsToRemove := []portainer.EdgeGroupID{}
|
||||
endpointsFromGroupsToAddMap := map[portainer.EndpointID]portainer.EdgeJobEndpointMeta{}
|
||||
|
||||
if len(payload.EdgeGroups) > 0 {
|
||||
for _, edgeGroupID := range payload.EdgeGroups {
|
||||
_, err := handler.DataStore.EdgeGroup().EdgeGroup(edgeGroupID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !slices.Contains(edgeJob.EdgeGroups, edgeGroupID) {
|
||||
edgeGroupsToAdd = append(edgeGroupsToAdd, edgeGroupID)
|
||||
}
|
||||
}
|
||||
|
||||
endpointsFromGroupsToAdd, err := edge.GetEndpointsFromEdgeGroups(edgeGroupsToAdd, handler.DataStore)
|
||||
if err != nil {
|
||||
return errors.New("unable to get endpoints from edge groups")
|
||||
}
|
||||
endpointsFromGroupsToAddMap = handler.convertEndpointsToMetaObject(endpointsFromGroupsToAdd)
|
||||
|
||||
for endpointID := range endpointsFromGroupsToAddMap {
|
||||
endpointsToAdd[endpointID] = true
|
||||
}
|
||||
|
||||
newEdgeGroups := edge.EdgeGroupSet(payload.EdgeGroups)
|
||||
for _, edgeGroupID := range edgeJob.EdgeGroups {
|
||||
if !newEdgeGroups[edgeGroupID] {
|
||||
edgeGroupsToRemove = append(edgeGroupsToRemove, edgeGroupID)
|
||||
}
|
||||
}
|
||||
|
||||
endpointsFromGroupsToRemove, err := edge.GetEndpointsFromEdgeGroups(edgeGroupsToRemove, handler.DataStore)
|
||||
if err != nil {
|
||||
return errors.New("unable to get endpoints from edge groups")
|
||||
}
|
||||
|
||||
endpointsToRemoveMap := handler.convertEndpointsToMetaObject(endpointsFromGroupsToRemove)
|
||||
|
||||
for endpointID := range endpointsToRemoveMap {
|
||||
endpointsToRemove[endpointID] = true
|
||||
}
|
||||
|
||||
edgeJob.EdgeGroups = payload.EdgeGroups
|
||||
}
|
||||
|
||||
updateVersion := false
|
||||
if payload.CronExpression != nil && *payload.CronExpression != edgeJob.CronExpression {
|
||||
edgeJob.CronExpression = *payload.CronExpression
|
||||
|
@ -133,9 +209,15 @@ func (handler *Handler) updateEdgeSchedule(edgeJob *portainer.EdgeJob, payload *
|
|||
edgeJob.Version++
|
||||
}
|
||||
|
||||
for endpointID := range edgeJob.Endpoints {
|
||||
maps.Copy(endpointsFromGroupsToAddMap, edgeJob.Endpoints)
|
||||
|
||||
for endpointID := range endpointsFromGroupsToAddMap {
|
||||
handler.ReverseTunnelService.AddEdgeJob(endpointID, edgeJob)
|
||||
}
|
||||
|
||||
for endpointID := range endpointsToRemove {
|
||||
handler.ReverseTunnelService.RemoveEdgeJobFromEndpoint(endpointID, edgeJob.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue