diff --git a/api/datastore/migrator/migrate_2_32_0.go b/api/datastore/migrator/migrate_2_32_0.go new file mode 100644 index 000000000..c32a63cad --- /dev/null +++ b/api/datastore/migrator/migrate_2_32_0.go @@ -0,0 +1,33 @@ +package migrator + +import ( + "github.com/pkg/errors" + portainer "github.com/portainer/portainer/api" + perrors "github.com/portainer/portainer/api/dataservices/errors" + "github.com/portainer/portainer/api/internal/endpointutils" +) + +func (m *Migrator) addEndpointRelationForEdgeAgents_2_32_0() error { + endpoints, err := m.endpointService.Endpoints() + if err != nil { + return err + } + + for _, endpoint := range endpoints { + if endpointutils.IsEdgeEndpoint(&endpoint) { + _, err := m.endpointRelationService.EndpointRelation(endpoint.ID) + if err != nil && errors.Is(err, perrors.ErrObjectNotFound) { + relation := &portainer.EndpointRelation{ + EndpointID: endpoint.ID, + EdgeStacks: make(map[portainer.EdgeStackID]bool), + } + + if err := m.endpointRelationService.Create(relation); err != nil { + return err + } + } + } + } + + return nil +} diff --git a/api/datastore/migrator/migrator.go b/api/datastore/migrator/migrator.go index 992dd0b9d..4c2a50e59 100644 --- a/api/datastore/migrator/migrator.go +++ b/api/datastore/migrator/migrator.go @@ -249,6 +249,8 @@ func (m *Migrator) initMigrations() { m.addMigrations("2.31.0", m.migrateEdgeStacksStatuses_2_31_0) + m.addMigrations("2.32.0", m.addEndpointRelationForEdgeAgents_2_32_0) + // Add new migrations above... // One function per migration, each versions migration funcs in the same file. } diff --git a/api/http/handler/edgegroups/edgegroup_update.go b/api/http/handler/edgegroups/edgegroup_update.go index 7831b634e..a51ae33d4 100644 --- a/api/http/handler/edgegroups/edgegroup_update.go +++ b/api/http/handler/edgegroups/edgegroup_update.go @@ -163,7 +163,7 @@ func (handler *Handler) edgeGroupUpdate(w http.ResponseWriter, r *http.Request) func (handler *Handler) updateEndpointStacks(tx dataservices.DataStoreTx, endpoint *portainer.Endpoint, edgeGroups []portainer.EdgeGroup, edgeStacks []portainer.EdgeStack) error { relation, err := tx.EndpointRelation().EndpointRelation(endpoint.ID) - if err != nil && !handler.DataStore.IsErrObjectNotFound(err) { + if err != nil { return err } @@ -179,12 +179,6 @@ func (handler *Handler) updateEndpointStacks(tx dataservices.DataStoreTx, endpoi edgeStackSet[edgeStackID] = true } - if relation == nil { - relation = &portainer.EndpointRelation{ - EndpointID: endpoint.ID, - EdgeStacks: make(map[portainer.EdgeStackID]bool), - } - } relation.EdgeStacks = edgeStackSet return tx.EndpointRelation().UpdateEndpointRelation(endpoint.ID, relation) diff --git a/api/http/handler/endpointedge/endpointedge_status_inspect.go b/api/http/handler/endpointedge/endpointedge_status_inspect.go index 4d6368493..9bd341561 100644 --- a/api/http/handler/endpointedge/endpointedge_status_inspect.go +++ b/api/http/handler/endpointedge/endpointedge_status_inspect.go @@ -264,9 +264,6 @@ func (handler *Handler) buildSchedules(tx dataservices.DataStoreTx, endpointID p func (handler *Handler) buildEdgeStacks(tx dataservices.DataStoreTx, endpointID portainer.EndpointID) ([]stackStatusResponse, *httperror.HandlerError) { relation, err := tx.EndpointRelation().EndpointRelation(endpointID) if err != nil { - if tx.IsErrObjectNotFound(err) { - return nil, nil - } return nil, httperror.InternalServerError("Unable to retrieve relation object from the database", err) } diff --git a/api/http/handler/endpointgroups/endpoints.go b/api/http/handler/endpointgroups/endpoints.go index b34032d9e..8b420f2a6 100644 --- a/api/http/handler/endpointgroups/endpoints.go +++ b/api/http/handler/endpointgroups/endpoints.go @@ -21,17 +21,10 @@ func (handler *Handler) updateEndpointRelations(tx dataservices.DataStoreTx, end } endpointRelation, err := tx.EndpointRelation().EndpointRelation(endpoint.ID) - if err != nil && !tx.IsErrObjectNotFound(err) { + if err != nil { return err } - if endpointRelation == nil { - endpointRelation = &portainer.EndpointRelation{ - EndpointID: endpoint.ID, - EdgeStacks: make(map[portainer.EdgeStackID]bool), - } - } - edgeGroups, err := tx.EdgeGroup().ReadAll() if err != nil { return err diff --git a/api/http/handler/endpoints/endpoint_create.go b/api/http/handler/endpoints/endpoint_create.go index 1c6415023..3cfe934bc 100644 --- a/api/http/handler/endpoints/endpoint_create.go +++ b/api/http/handler/endpoints/endpoint_create.go @@ -563,6 +563,10 @@ func (handler *Handler) saveEndpointAndUpdateAuthorizations(tx dataservices.Data return err } + if err := endpointutils.InitializeEdgeEndpointRelation(endpoint, tx); err != nil { + return err + } + for _, tagID := range endpoint.TagIDs { if err := tx.Tag().UpdateTagFunc(tagID, func(tag *portainer.Tag) { tag.Endpoints[endpoint.ID] = true diff --git a/api/http/handler/endpoints/update_edge_relations.go b/api/http/handler/endpoints/update_edge_relations.go index 1390c9fd4..c487519f0 100644 --- a/api/http/handler/endpoints/update_edge_relations.go +++ b/api/http/handler/endpoints/update_edge_relations.go @@ -17,17 +17,7 @@ func (handler *Handler) updateEdgeRelations(tx dataservices.DataStoreTx, endpoin relation, err := tx.EndpointRelation().EndpointRelation(endpoint.ID) if err != nil { - if !tx.IsErrObjectNotFound(err) { - return errors.WithMessage(err, "Unable to retrieve environment relation inside the database") - } - - relation = &portainer.EndpointRelation{ - EndpointID: endpoint.ID, - EdgeStacks: map[portainer.EdgeStackID]bool{}, - } - if err := tx.EndpointRelation().Create(relation); err != nil { - return errors.WithMessage(err, "Unable to create environment relation inside the database") - } + return errors.WithMessage(err, "Unable to retrieve environment relation inside the database") } endpointGroup, err := tx.EndpointGroup().Read(endpoint.GroupID) diff --git a/api/http/handler/tags/tag_delete.go b/api/http/handler/tags/tag_delete.go index 4f8554faf..1fa98e394 100644 --- a/api/http/handler/tags/tag_delete.go +++ b/api/http/handler/tags/tag_delete.go @@ -8,6 +8,7 @@ import ( portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/internal/edge" + "github.com/portainer/portainer/api/internal/endpointutils" httperror "github.com/portainer/portainer/pkg/libhttp/error" "github.com/portainer/portainer/pkg/libhttp/request" "github.com/portainer/portainer/pkg/libhttp/response" @@ -104,9 +105,8 @@ func deleteTag(tx dataservices.DataStoreTx, tagID portainer.TagID) error { } for _, endpoint := range endpoints { - if (tag.Endpoints[endpoint.ID] || tag.EndpointGroups[endpoint.GroupID]) && (endpoint.Type == portainer.EdgeAgentOnDockerEnvironment || endpoint.Type == portainer.EdgeAgentOnKubernetesEnvironment) { - err = updateEndpointRelations(tx, endpoint, edgeGroups, edgeStacks) - if err != nil { + if (tag.Endpoints[endpoint.ID] || tag.EndpointGroups[endpoint.GroupID]) && endpointutils.IsEdgeEndpoint(&endpoint) { + if err := updateEndpointRelations(tx, endpoint, edgeGroups, edgeStacks); err != nil { return httperror.InternalServerError("Unable to update environment relations in the database", err) } } @@ -133,17 +133,10 @@ func deleteTag(tx dataservices.DataStoreTx, tagID portainer.TagID) error { func updateEndpointRelations(tx dataservices.DataStoreTx, endpoint portainer.Endpoint, edgeGroups []portainer.EdgeGroup, edgeStacks []portainer.EdgeStack) error { endpointRelation, err := tx.EndpointRelation().EndpointRelation(endpoint.ID) - if err != nil && !tx.IsErrObjectNotFound(err) { + if err != nil { return err } - if endpointRelation == nil { - endpointRelation = &portainer.EndpointRelation{ - EndpointID: endpoint.ID, - EdgeStacks: make(map[portainer.EdgeStackID]bool), - } - } - endpointGroup, err := tx.EndpointGroup().Read(endpoint.GroupID) if err != nil { return err diff --git a/api/internal/edge/edgestacks/service.go b/api/internal/edge/edgestacks/service.go index 5932a5ec8..c0ecb5caf 100644 --- a/api/internal/edge/edgestacks/service.go +++ b/api/internal/edge/edgestacks/service.go @@ -129,9 +129,6 @@ func (service *Service) updateEndpointRelations(tx dataservices.DataStoreTx, edg for _, endpointID := range relatedEndpointIds { relation, err := endpointRelationService.EndpointRelation(endpointID) if err != nil { - if tx.IsErrObjectNotFound(err) { - continue - } return fmt.Errorf("unable to find endpoint relation in database: %w", err) } diff --git a/api/internal/endpointutils/endpointutils.go b/api/internal/endpointutils/endpointutils.go index 6b7eb1c2d..f596ae0d5 100644 --- a/api/internal/endpointutils/endpointutils.go +++ b/api/internal/endpointutils/endpointutils.go @@ -249,3 +249,19 @@ func getEndpointCheckinInterval(endpoint *portainer.Endpoint, settings *portaine return defaultInterval } + +func InitializeEdgeEndpointRelation(endpoint *portainer.Endpoint, tx dataservices.DataStoreTx) error { + if !IsEdgeEndpoint(endpoint) { + return nil + } + + relation := &portainer.EndpointRelation{ + EndpointID: endpoint.ID, + EdgeStacks: make(map[portainer.EdgeStackID]bool), + } + + if err := tx.EndpointRelation().Create(relation); err != nil { + return err + } + return nil +}