1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-02 20:35:25 +02:00

feat(transactions): migrate some parts to use transactional code EE-5494 (#9213)

This commit is contained in:
andres-portainer 2023-07-17 17:36:00 -03:00 committed by GitHub
parent fbec123595
commit 8c533bee67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 305 additions and 88 deletions

View file

@ -15,6 +15,7 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/agent"
"github.com/portainer/portainer/api/crypto"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/client"
"github.com/portainer/portainer/api/internal/edge"
"github.com/portainer/portainer/api/internal/endpointutils"
@ -217,7 +218,7 @@ func (handler *Handler) endpointCreate(w http.ResponseWriter, r *http.Request) *
return httperror.NewError(http.StatusConflict, "Name is not unique", nil)
}
endpoint, endpointCreationError := handler.createEndpoint(payload)
endpoint, endpointCreationError := handler.createEndpoint(handler.DataStore, payload)
if endpointCreationError != nil {
return endpointCreationError
}
@ -273,17 +274,17 @@ func (handler *Handler) endpointCreate(w http.ResponseWriter, r *http.Request) *
return response.JSON(w, endpoint)
}
func (handler *Handler) createEndpoint(payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
func (handler *Handler) createEndpoint(tx dataservices.DataStoreTx, payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
var err error
switch payload.EndpointCreationType {
case azureEnvironment:
return handler.createAzureEndpoint(payload)
return handler.createAzureEndpoint(tx, payload)
case edgeAgentEnvironment:
return handler.createEdgeAgentEndpoint(payload)
return handler.createEdgeAgentEndpoint(tx, payload)
case localKubernetesEnvironment:
return handler.createKubernetesEndpoint(payload)
return handler.createKubernetesEndpoint(tx, payload)
}
endpointType := portainer.DockerEnvironment
@ -312,12 +313,13 @@ func (handler *Handler) createEndpoint(payload *endpointCreatePayload) (*portain
}
if payload.TLS {
return handler.createTLSSecuredEndpoint(payload, endpointType, agentVersion)
return handler.createTLSSecuredEndpoint(tx, payload, endpointType, agentVersion)
}
return handler.createUnsecuredEndpoint(payload)
return handler.createUnsecuredEndpoint(tx, payload)
}
func (handler *Handler) createAzureEndpoint(payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
func (handler *Handler) createAzureEndpoint(tx dataservices.DataStoreTx, payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
credentials := portainer.AzureCredentials{
ApplicationID: payload.AzureApplicationID,
TenantID: payload.AzureTenantID,
@ -330,7 +332,7 @@ func (handler *Handler) createAzureEndpoint(payload *endpointCreatePayload) (*po
return nil, httperror.InternalServerError("Unable to authenticate against Azure", err)
}
endpointID := handler.DataStore.Endpoint().GetNextIdentifier()
endpointID := tx.Endpoint().GetNextIdentifier()
endpoint := &portainer.Endpoint{
ID: portainer.EndpointID(endpointID),
Name: payload.Name,
@ -348,7 +350,7 @@ func (handler *Handler) createAzureEndpoint(payload *endpointCreatePayload) (*po
Kubernetes: portainer.KubernetesDefault(),
}
err = handler.saveEndpointAndUpdateAuthorizations(endpoint)
err = handler.saveEndpointAndUpdateAuthorizations(tx, endpoint)
if err != nil {
return nil, httperror.InternalServerError("An error occurred while trying to create the environment", err)
}
@ -356,7 +358,7 @@ func (handler *Handler) createAzureEndpoint(payload *endpointCreatePayload) (*po
return endpoint, nil
}
func (handler *Handler) createEdgeAgentEndpoint(payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
func (handler *Handler) createEdgeAgentEndpoint(tx dataservices.DataStoreTx, payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
endpointID := handler.DataStore.Endpoint().GetNextIdentifier()
portainerHost, err := edge.ParseHostForEdge(payload.URL)
@ -401,7 +403,7 @@ func (handler *Handler) createEdgeAgentEndpoint(payload *endpointCreatePayload)
endpoint.EdgeID = edgeID.String()
}
err = handler.saveEndpointAndUpdateAuthorizations(endpoint)
err = handler.saveEndpointAndUpdateAuthorizations(tx, endpoint)
if err != nil {
return nil, httperror.InternalServerError("An error occurred while trying to create the environment", err)
}
@ -409,7 +411,7 @@ func (handler *Handler) createEdgeAgentEndpoint(payload *endpointCreatePayload)
return endpoint, nil
}
func (handler *Handler) createUnsecuredEndpoint(payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
func (handler *Handler) createUnsecuredEndpoint(tx dataservices.DataStoreTx, payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
endpointType := portainer.DockerEnvironment
if payload.URL == "" {
@ -419,7 +421,7 @@ func (handler *Handler) createUnsecuredEndpoint(payload *endpointCreatePayload)
}
}
endpointID := handler.DataStore.Endpoint().GetNextIdentifier()
endpointID := tx.Endpoint().GetNextIdentifier()
endpoint := &portainer.Endpoint{
ID: portainer.EndpointID(endpointID),
Name: payload.Name,
@ -439,7 +441,7 @@ func (handler *Handler) createUnsecuredEndpoint(payload *endpointCreatePayload)
Kubernetes: portainer.KubernetesDefault(),
}
err := handler.snapshotAndPersistEndpoint(endpoint)
err := handler.snapshotAndPersistEndpoint(tx, endpoint)
if err != nil {
return nil, err
}
@ -447,12 +449,12 @@ func (handler *Handler) createUnsecuredEndpoint(payload *endpointCreatePayload)
return endpoint, nil
}
func (handler *Handler) createKubernetesEndpoint(payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
func (handler *Handler) createKubernetesEndpoint(tx dataservices.DataStoreTx, payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
if payload.URL == "" {
payload.URL = "https://kubernetes.default.svc"
}
endpointID := handler.DataStore.Endpoint().GetNextIdentifier()
endpointID := tx.Endpoint().GetNextIdentifier()
endpoint := &portainer.Endpoint{
ID: portainer.EndpointID(endpointID),
@ -474,7 +476,7 @@ func (handler *Handler) createKubernetesEndpoint(payload *endpointCreatePayload)
Kubernetes: portainer.KubernetesDefault(),
}
err := handler.snapshotAndPersistEndpoint(endpoint)
err := handler.snapshotAndPersistEndpoint(tx, endpoint)
if err != nil {
return nil, err
}
@ -482,8 +484,8 @@ func (handler *Handler) createKubernetesEndpoint(payload *endpointCreatePayload)
return endpoint, nil
}
func (handler *Handler) createTLSSecuredEndpoint(payload *endpointCreatePayload, endpointType portainer.EndpointType, agentVersion string) (*portainer.Endpoint, *httperror.HandlerError) {
endpointID := handler.DataStore.Endpoint().GetNextIdentifier()
func (handler *Handler) createTLSSecuredEndpoint(tx dataservices.DataStoreTx, payload *endpointCreatePayload, endpointType portainer.EndpointType, agentVersion string) (*portainer.Endpoint, *httperror.HandlerError) {
endpointID := tx.Endpoint().GetNextIdentifier()
endpoint := &portainer.Endpoint{
ID: portainer.EndpointID(endpointID),
Name: payload.Name,
@ -511,7 +513,7 @@ func (handler *Handler) createTLSSecuredEndpoint(payload *endpointCreatePayload,
return nil, err
}
err = handler.snapshotAndPersistEndpoint(endpoint)
err = handler.snapshotAndPersistEndpoint(tx, endpoint)
if err != nil {
return nil, err
}
@ -519,7 +521,7 @@ func (handler *Handler) createTLSSecuredEndpoint(payload *endpointCreatePayload,
return endpoint, nil
}
func (handler *Handler) snapshotAndPersistEndpoint(endpoint *portainer.Endpoint) *httperror.HandlerError {
func (handler *Handler) snapshotAndPersistEndpoint(tx dataservices.DataStoreTx, endpoint *portainer.Endpoint) *httperror.HandlerError {
err := handler.SnapshotService.SnapshotEndpoint(endpoint)
if err != nil {
if (endpoint.Type == portainer.AgentOnDockerEnvironment && strings.Contains(err.Error(), "Invalid request signature")) ||
@ -529,7 +531,7 @@ func (handler *Handler) snapshotAndPersistEndpoint(endpoint *portainer.Endpoint)
return httperror.InternalServerError("Unable to initiate communications with environment", err)
}
err = handler.saveEndpointAndUpdateAuthorizations(endpoint)
err = handler.saveEndpointAndUpdateAuthorizations(tx, endpoint)
if err != nil {
return httperror.InternalServerError("An error occurred while trying to create the environment", err)
}
@ -537,7 +539,7 @@ func (handler *Handler) snapshotAndPersistEndpoint(endpoint *portainer.Endpoint)
return nil
}
func (handler *Handler) saveEndpointAndUpdateAuthorizations(endpoint *portainer.Endpoint) error {
func (handler *Handler) saveEndpointAndUpdateAuthorizations(tx dataservices.DataStoreTx, endpoint *portainer.Endpoint) error {
endpoint.SecuritySettings = portainer.EndpointSecuritySettings{
AllowVolumeBrowserForRegularUsers: false,
EnableHostManagementFeatures: false,
@ -551,13 +553,13 @@ func (handler *Handler) saveEndpointAndUpdateAuthorizations(endpoint *portainer.
AllowStackManagementForRegularUsers: true,
}
err := handler.DataStore.Endpoint().Create(endpoint)
err := tx.Endpoint().Create(endpoint)
if err != nil {
return err
}
for _, tagID := range endpoint.TagIDs {
err = handler.DataStore.Tag().UpdateTagFunc(tagID, func(tag *portainer.Tag) {
err = tx.Tag().UpdateTagFunc(tagID, func(tag *portainer.Tag) {
tag.Endpoints[endpoint.ID] = true
})
if err != nil {

View file

@ -1,6 +1,7 @@
package endpoints
import (
"errors"
"net/http"
"strconv"
@ -8,8 +9,11 @@ import (
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
httperrors "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/portainer/portainer/pkg/featureflags"
"github.com/rs/zerolog/log"
)
@ -33,41 +37,84 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
return httperror.BadRequest("Invalid environment identifier route variable", err)
}
// This is a Portainer provisioned cloud environment
deleteCluster, err := request.RetrieveBooleanQueryParameter(r, "deleteCluster", true)
if err != nil {
return httperror.BadRequest("Invalid boolean query parameter", err)
}
if handler.demoService.IsDemoEnvironment(portainer.EndpointID(endpointID)) {
return httperror.Forbidden(httperrors.ErrNotAvailableInDemo.Error(), httperrors.ErrNotAvailableInDemo)
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
if featureflags.IsEnabled(portainer.FeatureNoTx) {
err = handler.deleteEndpoint(handler.DataStore, portainer.EndpointID(endpointID), deleteCluster)
} else {
err = handler.DataStore.UpdateTx(func(tx dataservices.DataStoreTx) error {
return handler.deleteEndpoint(tx, portainer.EndpointID(endpointID), deleteCluster)
})
}
if err != nil {
var handlerError *httperror.HandlerError
if errors.As(err, &handlerError) {
return handlerError
}
return httperror.InternalServerError("Unexpected error", err)
}
return response.Empty(w)
}
func (handler *Handler) deleteEndpoint(tx dataservices.DataStoreTx, endpointID portainer.EndpointID, deleteCluster bool) error {
endpoint, err := tx.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if tx.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to read the environment record from the database", err)
}
if endpoint.TLSConfig.TLS {
folder := strconv.Itoa(endpointID)
folder := strconv.Itoa(int(endpointID))
err = handler.FileService.DeleteTLSFiles(folder)
if err != nil {
log.Error().Err(err).Msgf("Unable to remove TLS files from disk when deleting endpoint %d", endpointID)
}
}
err = handler.DataStore.Snapshot().Delete(portainer.EndpointID(endpointID))
err = tx.Snapshot().Delete(endpointID)
if err != nil {
log.Warn().Err(err).Msgf("Unable to remove the snapshot from the database")
}
handler.ProxyManager.DeleteEndpointProxy(endpoint.ID)
err = handler.DataStore.EndpointRelation().DeleteEndpointRelation(endpoint.ID)
if len(endpoint.UserAccessPolicies) > 0 || len(endpoint.TeamAccessPolicies) > 0 {
err = handler.AuthorizationService.UpdateUsersAuthorizationsTx(tx)
if err != nil {
log.Warn().Err(err).Msgf("Unable to update user authorizations")
}
}
err = tx.EndpointRelation().DeleteEndpointRelation(endpoint.ID)
if err != nil {
log.Warn().Err(err).Msgf("Unable to remove environment relation from the database")
}
for _, tagID := range endpoint.TagIDs {
err = handler.DataStore.Tag().UpdateTagFunc(tagID, func(tag *portainer.Tag) {
delete(tag.Endpoints, endpoint.ID)
})
if featureflags.IsEnabled(portainer.FeatureNoTx) {
err = handler.DataStore.Tag().UpdateTagFunc(tagID, func(tag *portainer.Tag) {
delete(tag.Endpoints, endpoint.ID)
})
} else {
var tag *portainer.Tag
tag, err = tx.Tag().Read(tagID)
if err == nil {
delete(tag.Endpoints, endpoint.ID)
err = tx.Tag().Update(tagID, tag)
}
}
if handler.DataStore.IsErrObjectNotFound(err) {
log.Warn().Err(err).Msgf("Unable to find tag inside the database")
@ -76,21 +123,27 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
}
}
edgeGroups, err := handler.DataStore.EdgeGroup().ReadAll()
edgeGroups, err := tx.EdgeGroup().ReadAll()
if err != nil {
log.Warn().Err(err).Msgf("Unable to retrieve edge groups from the database")
}
for _, edgeGroup := range edgeGroups {
err = handler.DataStore.EdgeGroup().UpdateEdgeGroupFunc(edgeGroup.ID, func(g *portainer.EdgeGroup) {
g.Endpoints = removeElement(g.Endpoints, endpoint.ID)
})
if featureflags.IsEnabled(portainer.FeatureNoTx) {
err = handler.DataStore.EdgeGroup().UpdateEdgeGroupFunc(edgeGroup.ID, func(g *portainer.EdgeGroup) {
g.Endpoints = removeElement(g.Endpoints, endpoint.ID)
})
} else {
edgeGroup.Endpoints = removeElement(edgeGroup.Endpoints, endpoint.ID)
tx.EdgeGroup().Update(edgeGroup.ID, &edgeGroup)
}
if err != nil {
log.Warn().Err(err).Msgf("Unable to update edge group")
}
}
edgeStacks, err := handler.DataStore.EdgeStack().EdgeStacks()
edgeStacks, err := tx.EdgeStack().EdgeStacks()
if err != nil {
log.Warn().Err(err).Msgf("Unable to retrieve edge stacks from the database")
}
@ -99,14 +152,14 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
edgeStack := &edgeStacks[idx]
if _, ok := edgeStack.Status[endpoint.ID]; ok {
delete(edgeStack.Status, endpoint.ID)
err = handler.DataStore.EdgeStack().UpdateEdgeStack(edgeStack.ID, edgeStack)
err = tx.EdgeStack().UpdateEdgeStack(edgeStack.ID, edgeStack)
if err != nil {
log.Warn().Err(err).Msgf("Unable to update edge stack")
}
}
}
registries, err := handler.DataStore.Registry().ReadAll()
registries, err := tx.Registry().ReadAll()
if err != nil {
log.Warn().Err(err).Msgf("Unable to retrieve registries from the database")
}
@ -115,7 +168,7 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
registry := &registries[idx]
if _, ok := registry.RegistryAccesses[endpoint.ID]; ok {
delete(registry.RegistryAccesses, endpoint.ID)
err = handler.DataStore.Registry().Update(registry.ID, registry)
err = tx.Registry().Update(registry.ID, registry)
if err != nil {
log.Warn().Err(err).Msgf("Unable to update registry accesses")
}
@ -131,9 +184,14 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
for idx := range edgeJobs {
edgeJob := &edgeJobs[idx]
if _, ok := edgeJob.Endpoints[endpoint.ID]; ok {
err = handler.DataStore.EdgeJob().UpdateEdgeJobFunc(edgeJob.ID, func(j *portainer.EdgeJob) {
delete(j.Endpoints, endpoint.ID)
})
if featureflags.IsEnabled(portainer.FeatureNoTx) {
err = tx.EdgeJob().UpdateEdgeJobFunc(edgeJob.ID, func(j *portainer.EdgeJob) {
delete(j.Endpoints, endpoint.ID)
})
} else {
delete(edgeJob.Endpoints, endpoint.ID)
err = tx.EdgeJob().Update(edgeJob.ID, edgeJob)
}
if err != nil {
log.Warn().Err(err).Msgf("Unable to update edge job")
@ -142,12 +200,12 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
}
}
err = handler.DataStore.Endpoint().DeleteEndpoint(portainer.EndpointID(endpointID))
err = tx.Endpoint().DeleteEndpoint(portainer.EndpointID(endpointID))
if err != nil {
return httperror.InternalServerError("Unable to remove environment from the database", err)
return httperror.InternalServerError("Unable to delete the environment from the database", err)
}
return response.Empty(w)
return nil
}
func removeElement(slice []portainer.EndpointID, elem portainer.EndpointID) []portainer.EndpointID {

View file

@ -3,13 +3,16 @@ package endpoints
import (
"net/http"
"github.com/pkg/errors"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/portainer/portainer/pkg/featureflags"
"github.com/pkg/errors"
)
// @id endpointRegistriesList
@ -26,45 +29,68 @@ import (
// @failure 500 "Server error"
// @router /endpoints/{id}/registries [get]
func (handler *Handler) endpointRegistriesList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
securityContext, err := security.RetrieveRestrictedRequestContext(r)
if err != nil {
return httperror.InternalServerError("Unable to retrieve info from request context", err)
}
user, err := handler.DataStore.User().Read(securityContext.UserID)
if err != nil {
return httperror.InternalServerError("Unable to retrieve user from the database", err)
}
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {
return httperror.BadRequest("Invalid environment identifier route variable", err)
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
var registries []portainer.Registry
if featureflags.IsEnabled(portainer.FeatureNoTx) {
registries, err = handler.listRegistries(handler.DataStore, r, portainer.EndpointID(endpointID))
} else {
err = handler.DataStore.ViewTx(func(tx dataservices.DataStoreTx) error {
registries, err = handler.listRegistries(tx, r, portainer.EndpointID(endpointID))
return err
})
}
if err != nil {
var httpErr *httperror.HandlerError
if errors.As(err, &httpErr) {
return httpErr
}
return httperror.InternalServerError("Unexpected error", err)
}
return response.JSON(w, registries)
}
func (handler *Handler) listRegistries(tx dataservices.DataStoreTx, r *http.Request, endpointID portainer.EndpointID) ([]portainer.Registry, error) {
securityContext, err := security.RetrieveRestrictedRequestContext(r)
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve info from request context", err)
}
user, err := tx.User().Read(securityContext.UserID)
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve user from the database", err)
}
endpoint, err := tx.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if tx.IsErrObjectNotFound(err) {
return nil, httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
return nil, httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
}
isAdmin := securityContext.IsAdmin
registries, err := handler.DataStore.Registry().ReadAll()
registries, err := tx.Registry().ReadAll()
if err != nil {
return httperror.InternalServerError("Unable to retrieve registries from the database", err)
return nil, httperror.InternalServerError("Unable to retrieve registries from the database", err)
}
registries, handleError := handler.filterRegistriesByAccess(r, registries, endpoint, user, securityContext.UserMemberships)
if handleError != nil {
return handleError
return nil, handleError
}
for idx := range registries {
hideRegistryFields(&registries[idx], !isAdmin)
}
return response.JSON(w, registries)
return registries, err
}
func (handler *Handler) filterRegistriesByAccess(r *http.Request, registries []portainer.Registry, endpoint *portainer.Endpoint, user *portainer.User, memberships []portainer.TeamMembership) ([]portainer.Registry, *httperror.HandlerError) {

View file

@ -1,13 +1,16 @@
package endpoints
import (
"errors"
"net/http"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/pkg/featureflags"
)
type registryAccessPayload struct {
@ -48,8 +51,29 @@ func (handler *Handler) endpointRegistryAccess(w http.ResponseWriter, r *http.Re
return httperror.BadRequest("Invalid registry identifier route variable", err)
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
if featureflags.IsEnabled(portainer.FeatureNoTx) {
err = handler.updateRegistryAccess(handler.DataStore, r, portainer.EndpointID(endpointID), portainer.RegistryID(registryID))
} else {
err = handler.DataStore.UpdateTx(func(tx dataservices.DataStoreTx) error {
return handler.updateRegistryAccess(tx, r, portainer.EndpointID(endpointID), portainer.RegistryID(registryID))
})
}
if err != nil {
var httpErr *httperror.HandlerError
if errors.As(err, &httpErr) {
return httpErr
}
return httperror.InternalServerError("Unexpected error", err)
}
return response.Empty(w)
}
func (handler *Handler) updateRegistryAccess(tx dataservices.DataStoreTx, r *http.Request, endpointID portainer.EndpointID, registryID portainer.RegistryID) error {
endpoint, err := tx.Endpoint().Endpoint(endpointID)
if tx.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
@ -69,8 +93,8 @@ func (handler *Handler) endpointRegistryAccess(w http.ResponseWriter, r *http.Re
return httperror.Forbidden("User is not authorized", err)
}
registry, err := handler.DataStore.Registry().Read(portainer.RegistryID(registryID))
if handler.DataStore.IsErrObjectNotFound(err) {
registry, err := tx.Registry().Read(registryID)
if tx.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
@ -106,9 +130,7 @@ func (handler *Handler) endpointRegistryAccess(w http.ResponseWriter, r *http.Re
registry.RegistryAccesses[portainer.EndpointID(endpointID)] = registryAccess
handler.DataStore.Registry().Update(registry.ID, registry)
return response.Empty(w)
return tx.Registry().Update(registry.ID, registry)
}
func (handler *Handler) updateKubeAccess(endpoint *portainer.Endpoint, registry *portainer.Registry, oldNamespaces, newNamespaces []string) error {