portainer/portainer

View on GitHub
api/dataservices/endpoint/tx.go

Summary

Maintainability
A
40 mins
Test Coverage
package endpoint

import (
    portainer "github.com/portainer/portainer/api"
    "github.com/portainer/portainer/api/dataservices"
    "github.com/portainer/portainer/api/internal/edge/cache"

    "github.com/rs/zerolog/log"
)

type ServiceTx struct {
    service *Service
    tx      portainer.Transaction
}

func (service ServiceTx) BucketName() string {
    return BucketName
}

// Endpoint returns an environment(endpoint) by ID.
func (service ServiceTx) Endpoint(ID portainer.EndpointID) (*portainer.Endpoint, error) {
    var endpoint portainer.Endpoint
    identifier := service.service.connection.ConvertToKey(int(ID))

    err := service.tx.GetObject(BucketName, identifier, &endpoint)
    if err != nil {
        return nil, err
    }

    endpoint.LastCheckInDate, _ = service.service.Heartbeat(ID)

    return &endpoint, nil
}

// UpdateEndpoint updates an environment(endpoint).
func (service ServiceTx) UpdateEndpoint(ID portainer.EndpointID, endpoint *portainer.Endpoint) error {
    identifier := service.service.connection.ConvertToKey(int(ID))

    err := service.tx.UpdateObject(BucketName, identifier, endpoint)
    if err != nil {
        return err
    }

    service.service.mu.Lock()
    if len(endpoint.EdgeID) > 0 {
        service.service.idxEdgeID[endpoint.EdgeID] = ID
    }
    service.service.heartbeats.Store(ID, endpoint.LastCheckInDate)
    service.service.mu.Unlock()

    cache.Del(endpoint.ID)

    return nil
}

// DeleteEndpoint deletes an environment(endpoint).
func (service ServiceTx) DeleteEndpoint(ID portainer.EndpointID) error {
    identifier := service.service.connection.ConvertToKey(int(ID))

    err := service.tx.DeleteObject(BucketName, identifier)
    if err != nil {
        return err
    }

    service.service.mu.Lock()
    for edgeID, endpointID := range service.service.idxEdgeID {
        if endpointID == ID {
            delete(service.service.idxEdgeID, edgeID)

            break
        }
    }
    service.service.heartbeats.Delete(ID)
    service.service.mu.Unlock()

    cache.Del(ID)

    return nil
}

// Endpoints return an array containing all the environments(endpoints).
func (service ServiceTx) Endpoints() ([]portainer.Endpoint, error) {
    var endpoints = make([]portainer.Endpoint, 0)

    return endpoints, service.tx.GetAllWithJsoniter(
        BucketName,
        &portainer.Endpoint{},
        dataservices.AppendFn(&endpoints),
    )
}

func (service ServiceTx) EndpointIDByEdgeID(edgeID string) (portainer.EndpointID, bool) {
    log.Error().Str("func", "EndpointIDByEdgeID").Msg("cannot be called inside a transaction")

    return 0, false
}

func (service ServiceTx) Heartbeat(endpointID portainer.EndpointID) (int64, bool) {
    log.Error().Str("func", "Heartbeat").Msg("cannot be called inside a transaction")

    return 0, false
}

func (service ServiceTx) UpdateHeartbeat(endpointID portainer.EndpointID) {
    log.Error().Str("func", "UpdateHeartbeat").Msg("cannot be called inside a transaction")
}

// CreateEndpoint assign an ID to a new environment(endpoint) and saves it.
func (service ServiceTx) Create(endpoint *portainer.Endpoint) error {
    err := service.tx.CreateObjectWithId(BucketName, int(endpoint.ID), endpoint)
    if err != nil {
        return err
    }

    service.service.mu.Lock()
    if len(endpoint.EdgeID) > 0 {
        service.service.idxEdgeID[endpoint.EdgeID] = endpoint.ID
    }
    service.service.heartbeats.Store(endpoint.ID, endpoint.LastCheckInDate)
    service.service.mu.Unlock()

    return nil
}

func (service ServiceTx) EndpointsByTeamID(teamID portainer.TeamID) ([]portainer.Endpoint, error) {
    var endpoints = make([]portainer.Endpoint, 0)

    return endpoints, service.tx.GetAll(
        BucketName,
        &portainer.Endpoint{},
        dataservices.FilterFn(&endpoints, func(e portainer.Endpoint) bool {
            for t := range e.TeamAccessPolicies {
                if t == teamID {
                    return true
                }
            }
            return false
        }),
    )
}

// GetNextIdentifier returns the next identifier for an environment(endpoint).
func (service ServiceTx) GetNextIdentifier() int {
    return service.tx.GetNextIdentifier(BucketName)
}