feat(snapshots): separate snapshots from endpoint DB struct EE-4099 (#7614)

pull/7721/head
matias-portainer 2022-09-22 17:05:10 -03:00 committed by GitHub
parent 4fe2a7c750
commit 6e0f83b99e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 393 additions and 136 deletions

View File

@ -40,6 +40,7 @@ type (
Role() RoleService
APIKeyRepository() APIKeyRepository
Settings() SettingsService
Snapshot() SnapshotService
SSLSettings() SSLSettingsService
Stack() StackService
Tag() TagService
@ -214,6 +215,15 @@ type (
BucketName() string
}
SnapshotService interface {
Snapshot(endpointID portainer.EndpointID) (*portainer.Snapshot, error)
Snapshots() ([]portainer.Snapshot, error)
UpdateSnapshot(snapshot *portainer.Snapshot) error
DeleteSnapshot(endpointID portainer.EndpointID) error
Create(snapshot *portainer.Snapshot) error
BucketName() string
}
// SSLSettingsService represents a service for managing application settings
SSLSettingsService interface {
Settings() (*portainer.SSLSettings, error)

View File

@ -0,0 +1,76 @@
package snapshot
import (
"fmt"
portainer "github.com/portainer/portainer/api"
"github.com/sirupsen/logrus"
)
const (
BucketName = "snapshots"
)
type Service struct {
connection portainer.Connection
}
func (service *Service) BucketName() string {
return BucketName
}
func NewService(connection portainer.Connection) (*Service, error) {
err := connection.SetServiceName(BucketName)
if err != nil {
return nil, err
}
return &Service{
connection: connection,
}, nil
}
func (service *Service) Snapshot(endpointID portainer.EndpointID) (*portainer.Snapshot, error) {
var snapshot portainer.Snapshot
identifier := service.connection.ConvertToKey(int(endpointID))
err := service.connection.GetObject(BucketName, identifier, &snapshot)
if err != nil {
return nil, err
}
return &snapshot, nil
}
func (service *Service) Snapshots() ([]portainer.Snapshot, error) {
var snapshots = make([]portainer.Snapshot, 0)
err := service.connection.GetAllWithJsoniter(
BucketName,
&portainer.Snapshot{},
func(obj interface{}) (interface{}, error) {
snapshot, ok := obj.(*portainer.Snapshot)
if !ok {
logrus.WithField("obj", obj).Errorf("Failed to convert to Snapshot object")
return nil, fmt.Errorf("failed to convert to Snapshot object: %s", obj)
}
snapshots = append(snapshots, *snapshot)
return &portainer.Snapshot{}, nil
})
return snapshots, err
}
func (service *Service) UpdateSnapshot(snapshot *portainer.Snapshot) error {
identifier := service.connection.ConvertToKey(int(snapshot.EndpointID))
return service.connection.UpdateObject(BucketName, identifier, snapshot)
}
func (service *Service) DeleteSnapshot(endpointID portainer.EndpointID) error {
identifier := service.connection.ConvertToKey(int(endpointID))
return service.connection.DeleteObject(BucketName, identifier)
}
func (service *Service) Create(snapshot *portainer.Snapshot) error {
return service.connection.CreateObjectWithId(BucketName, int(snapshot.EndpointID), snapshot)
}

View File

@ -40,6 +40,7 @@ func (store *Store) MigrateData() error {
RoleService: store.RoleService,
ScheduleService: store.ScheduleService,
SettingsService: store.SettingsService,
SnapshotService: store.SnapshotService,
StackService: store.StackService,
TagService: store.TagService,
TeamMembershipService: store.TeamMembershipService,

View File

@ -108,6 +108,9 @@ func (m *Migrator) Migrate() error {
// Portainer 2.15
newMigration(60, m.migrateDBVersionToDB60),
// Portainer 2.16
newMigration(70, m.migrateDBVersionToDB70),
}
var lastDbVersion int

View File

@ -0,0 +1,46 @@
package migrator
import (
portainer "github.com/portainer/portainer/api"
)
func (m *Migrator) migrateDBVersionToDB70() error {
// foreach endpoint
endpoints, err := m.endpointService.Endpoints()
if err != nil {
return err
}
for _, endpoint := range endpoints {
// copy snapshots to new object
migrateLog.Info("- moving snapshots from endpoint to new object")
snapshot := portainer.Snapshot{EndpointID: endpoint.ID}
if len(endpoint.Snapshots) > 0 {
snapshot.Docker = &endpoint.Snapshots[len(endpoint.Snapshots)-1]
}
if len(endpoint.Kubernetes.Snapshots) > 0 {
snapshot.Kubernetes = &endpoint.Kubernetes.Snapshots[len(endpoint.Kubernetes.Snapshots)-1]
}
// save new object
err = m.snapshotService.Create(&snapshot)
if err != nil {
return err
}
// set to nil old fields
migrateLog.Info("- deleting snapshot from endpoint")
endpoint.Snapshots = []portainer.DockerSnapshot{}
endpoint.Kubernetes.Snapshots = []portainer.KubernetesSnapshot{}
// update endpoint
err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint)
if err != nil {
return err
}
}
return nil
}

View File

@ -13,6 +13,7 @@ import (
"github.com/portainer/portainer/api/dataservices/role"
"github.com/portainer/portainer/api/dataservices/schedule"
"github.com/portainer/portainer/api/dataservices/settings"
"github.com/portainer/portainer/api/dataservices/snapshot"
"github.com/portainer/portainer/api/dataservices/stack"
"github.com/portainer/portainer/api/dataservices/tag"
"github.com/portainer/portainer/api/dataservices/teammembership"
@ -35,6 +36,7 @@ type (
roleService *role.Service
scheduleService *schedule.Service
settingsService *settings.Service
snapshotService *snapshot.Service
stackService *stack.Service
tagService *tag.Service
teamMembershipService *teammembership.Service
@ -58,6 +60,7 @@ type (
RoleService *role.Service
ScheduleService *schedule.Service
SettingsService *settings.Service
SnapshotService *snapshot.Service
StackService *stack.Service
TagService *tag.Service
TeamMembershipService *teammembership.Service
@ -83,6 +86,7 @@ func NewMigrator(parameters *MigratorParameters) *Migrator {
roleService: parameters.RoleService,
scheduleService: parameters.ScheduleService,
settingsService: parameters.SettingsService,
snapshotService: parameters.SnapshotService,
tagService: parameters.TagService,
teamMembershipService: parameters.TeamMembershipService,
stackService: parameters.StackService,

View File

@ -26,6 +26,7 @@ import (
"github.com/portainer/portainer/api/dataservices/role"
"github.com/portainer/portainer/api/dataservices/schedule"
"github.com/portainer/portainer/api/dataservices/settings"
"github.com/portainer/portainer/api/dataservices/snapshot"
"github.com/portainer/portainer/api/dataservices/ssl"
"github.com/portainer/portainer/api/dataservices/stack"
"github.com/portainer/portainer/api/dataservices/tag"
@ -63,6 +64,7 @@ type Store struct {
APIKeyRepositoryService *apikeyrepository.Service
ScheduleService *schedule.Service
SettingsService *settings.Service
SnapshotService *snapshot.Service
SSLSettingsService *ssl.Service
StackService *stack.Service
TagService *tag.Service
@ -171,6 +173,12 @@ func (store *Store) initServices() error {
}
store.SettingsService = settingsService
snapshotService, err := snapshot.NewService(store.connection)
if err != nil {
return err
}
store.SnapshotService = snapshotService
sslSettingsService, err := ssl.NewService(store.connection)
if err != nil {
return err
@ -315,6 +323,10 @@ func (store *Store) Settings() dataservices.SettingsService {
return store.SettingsService
}
func (store *Store) Snapshot() dataservices.SnapshotService {
return store.SnapshotService
}
// SSLSettings gives access to the SSL Settings data management layer
func (store *Store) SSLSettings() dataservices.SSLSettingsService {
return store.SSLSettingsService
@ -375,6 +387,7 @@ type storeExport struct {
Role []portainer.Role `json:"roles,omitempty"`
Schedules []portainer.Schedule `json:"schedules,omitempty"`
Settings portainer.Settings `json:"settings,omitempty"`
Snapshot []portainer.Snapshot `json:"snapshots,omitempty"`
SSLSettings portainer.SSLSettings `json:"ssl,omitempty"`
Stack []portainer.Stack `json:"stacks,omitempty"`
Tag []portainer.Tag `json:"tags,omitempty"`
@ -503,6 +516,14 @@ func (store *Store) Export(filename string) (err error) {
backup.Settings = *settings
}
if snapshot, err := store.Snapshot().Snapshots(); err != nil {
if !store.IsErrObjectNotFound(err) {
logrus.WithError(err).Errorf("Exporting Snapshots")
}
} else {
backup.Snapshot = snapshot
}
if settings, err := store.SSLSettings().Settings(); err != nil {
if !store.IsErrObjectNotFound(err) {
log.Error().Err(err).Msg("exporting SSL Settings")
@ -662,6 +683,10 @@ func (store *Store) Import(filename string) (err error) {
store.Settings().UpdateSettings(&backup.Settings)
store.SSLSettings().UpdateSettings(&backup.SSLSettings)
for _, v := range backup.Snapshot {
store.Snapshot().UpdateSnapshot(&v)
}
for _, v := range backup.Stack {
store.Stack().UpdateStack(v.ID, &v)
}

View File

@ -60,7 +60,7 @@
"UseLoadBalancer": false,
"UseServerMetrics": false
},
"Snapshots": null
"Snapshots": []
},
"LastCheckInDate": 0,
"Name": "local",
@ -77,127 +77,7 @@
"allowVolumeBrowserForRegularUsers": false,
"enableHostManagementFeatures": false
},
"Snapshots": [
{
"DockerSnapshotRaw": {
"Containers": null,
"Images": null,
"Info": {
"Architecture": "",
"BridgeNfIp6tables": false,
"BridgeNfIptables": false,
"CPUSet": false,
"CPUShares": false,
"CgroupDriver": "",
"ContainerdCommit": {
"Expected": "",
"ID": ""
},
"Containers": 0,
"ContainersPaused": 0,
"ContainersRunning": 0,
"ContainersStopped": 0,
"CpuCfsPeriod": false,
"CpuCfsQuota": false,
"Debug": false,
"DefaultRuntime": "",
"DockerRootDir": "",
"Driver": "",
"DriverStatus": null,
"ExperimentalBuild": false,
"GenericResources": null,
"HttpProxy": "",
"HttpsProxy": "",
"ID": "",
"IPv4Forwarding": false,
"Images": 0,
"IndexServerAddress": "",
"InitBinary": "",
"InitCommit": {
"Expected": "",
"ID": ""
},
"Isolation": "",
"KernelMemory": false,
"KernelMemoryTCP": false,
"KernelVersion": "",
"Labels": null,
"LiveRestoreEnabled": false,
"LoggingDriver": "",
"MemTotal": 0,
"MemoryLimit": false,
"NCPU": 0,
"NEventsListener": 0,
"NFd": 0,
"NGoroutines": 0,
"Name": "",
"NoProxy": "",
"OSType": "",
"OSVersion": "",
"OomKillDisable": false,
"OperatingSystem": "",
"PidsLimit": false,
"Plugins": {
"Authorization": null,
"Log": null,
"Network": null,
"Volume": null
},
"RegistryConfig": null,
"RuncCommit": {
"Expected": "",
"ID": ""
},
"Runtimes": null,
"SecurityOptions": null,
"ServerVersion": "",
"SwapLimit": false,
"Swarm": {
"ControlAvailable": false,
"Error": "",
"LocalNodeState": "",
"NodeAddr": "",
"NodeID": "",
"RemoteManagers": null
},
"SystemTime": "",
"Warnings": null
},
"Networks": null,
"Version": {
"ApiVersion": "",
"Arch": "",
"GitCommit": "",
"GoVersion": "",
"Os": "",
"Platform": {
"Name": ""
},
"Version": ""
},
"Volumes": {
"Volumes": null,
"Warnings": null
}
},
"DockerVersion": "20.10.13",
"GpuUseAll": false,
"GpuUseList": null,
"HealthyContainerCount": 0,
"ImageCount": 9,
"NodeCount": 0,
"RunningContainerCount": 5,
"ServiceCount": 0,
"StackCount": 2,
"StoppedContainerCount": 0,
"Swarm": false,
"Time": 1648610112,
"TotalCPU": 8,
"TotalMemory": 25098706944,
"UnhealthyContainerCount": 0,
"VolumeCount": 10
}
],
"Snapshots": [],
"Status": 1,
"TLSConfig": {
"TLS": false,
@ -777,6 +657,131 @@
"mpsUser": ""
}
},
"snapshots": [
{
"Docker": {
"DockerSnapshotRaw": {
"Containers": null,
"Images": null,
"Info": {
"Architecture": "",
"BridgeNfIp6tables": false,
"BridgeNfIptables": false,
"CPUSet": false,
"CPUShares": false,
"CgroupDriver": "",
"ContainerdCommit": {
"Expected": "",
"ID": ""
},
"Containers": 0,
"ContainersPaused": 0,
"ContainersRunning": 0,
"ContainersStopped": 0,
"CpuCfsPeriod": false,
"CpuCfsQuota": false,
"Debug": false,
"DefaultRuntime": "",
"DockerRootDir": "",
"Driver": "",
"DriverStatus": null,
"ExperimentalBuild": false,
"GenericResources": null,
"HttpProxy": "",
"HttpsProxy": "",
"ID": "",
"IPv4Forwarding": false,
"Images": 0,
"IndexServerAddress": "",
"InitBinary": "",
"InitCommit": {
"Expected": "",
"ID": ""
},
"Isolation": "",
"KernelMemory": false,
"KernelMemoryTCP": false,
"KernelVersion": "",
"Labels": null,
"LiveRestoreEnabled": false,
"LoggingDriver": "",
"MemTotal": 0,
"MemoryLimit": false,
"NCPU": 0,
"NEventsListener": 0,
"NFd": 0,
"NGoroutines": 0,
"Name": "",
"NoProxy": "",
"OSType": "",
"OSVersion": "",
"OomKillDisable": false,
"OperatingSystem": "",
"PidsLimit": false,
"Plugins": {
"Authorization": null,
"Log": null,
"Network": null,
"Volume": null
},
"RegistryConfig": null,
"RuncCommit": {
"Expected": "",
"ID": ""
},
"Runtimes": null,
"SecurityOptions": null,
"ServerVersion": "",
"SwapLimit": false,
"Swarm": {
"ControlAvailable": false,
"Error": "",
"LocalNodeState": "",
"NodeAddr": "",
"NodeID": "",
"RemoteManagers": null
},
"SystemTime": "",
"Warnings": null
},
"Networks": null,
"Version": {
"ApiVersion": "",
"Arch": "",
"GitCommit": "",
"GoVersion": "",
"Os": "",
"Platform": {
"Name": ""
},
"Version": ""
},
"Volumes": {
"Volumes": null,
"Warnings": null
}
},
"DockerVersion": "20.10.13",
"GpuUseAll": false,
"GpuUseList": null,
"HealthyContainerCount": 0,
"ImageCount": 9,
"NodeCount": 0,
"RunningContainerCount": 5,
"ServiceCount": 0,
"StackCount": 2,
"StoppedContainerCount": 0,
"Swarm": false,
"Time": 1648610112,
"TotalCPU": 8,
"TotalMemory": 25098706944,
"UnhealthyContainerCount": 0,
"VolumeCount": 10
},
"EndpointId": 1,
"Kubernetes": null
}
],
"ssl": {
"certPath": "",
"httpEnabled": true,

View File

@ -60,6 +60,15 @@ func initDemoLocalEndpoint(store dataservices.DataStore) (portainer.EndpointID,
}
err := store.Endpoint().Create(localEndpoint)
if err != nil {
return id, errors.WithMessage(err, "failed creating local endpoint")
}
err = store.Snapshot().Create(&portainer.Snapshot{EndpointID: id})
if err != nil {
return id, errors.WithMessage(err, "failed creating snapshot")
}
return id, errors.WithMessage(err, "failed creating local endpoint")
}

View File

@ -44,5 +44,18 @@ func (handler *Handler) endpointInspect(w http.ResponseWriter, r *http.Request)
hideFields(endpoint)
endpoint.ComposeSyntaxMaxVersion = handler.ComposeStackManager.ComposeSyntaxMaxVersion()
if !excludeSnapshot(r) {
err = handler.SnapshotService.FillSnapshotData(endpoint)
if err != nil {
return httperror.InternalServerError("Unable to add snapshot data", err)
}
}
return response.JSON(w, endpoint)
}
func excludeSnapshot(r *http.Request) bool {
excludeSnapshot, _ := request.RetrieveBooleanQueryParameter(r, "excludeSnapshot", true)
return excludeSnapshot
}

View File

@ -103,6 +103,12 @@ func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *ht
paginatedEndpoints[idx].EdgeCheckinInterval = settings.EdgeAgentCheckinInterval
}
paginatedEndpoints[idx].QueryDate = time.Now().Unix()
if !query.excludeSnapshots {
err = handler.SnapshotService.FillSnapshotData(&paginatedEndpoints[idx])
if err != nil {
return httperror.InternalServerError("Unable to add snapshot data", err)
}
}
}
w.Header().Set("X-Total-Count", strconv.Itoa(filteredEndpointCount))

View File

@ -11,6 +11,7 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/snapshot"
"github.com/portainer/portainer/api/internal/testhelpers"
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/stretchr/testify/assert"
@ -203,6 +204,8 @@ func setup(t *testing.T, endpoints []portainer.Endpoint) (handler *Handler, tear
handler.DataStore = store
handler.ComposeStackManager = testhelpers.NewComposeStackManager()
handler.SnapshotService, _ = snapshot.NewService("1s", store, nil, nil, nil)
return handler, teardown
}

View File

@ -53,8 +53,6 @@ func (handler *Handler) endpointSnapshot(w http.ResponseWriter, r *http.Request)
latestEndpointReference.Status = portainer.EndpointStatusDown
}
latestEndpointReference.Snapshots = endpoint.Snapshots
latestEndpointReference.Kubernetes.Snapshots = endpoint.Kubernetes.Snapshots
latestEndpointReference.Agent.Version = endpoint.Agent.Version
err = handler.DataStore.Endpoint().UpdateEndpoint(latestEndpointReference.ID, latestEndpointReference)

View File

@ -56,8 +56,6 @@ func (handler *Handler) endpointSnapshots(w http.ResponseWriter, r *http.Request
endpoint.Status = portainer.EndpointStatusDown
}
latestEndpointReference.Snapshots = endpoint.Snapshots
latestEndpointReference.Kubernetes.Snapshots = endpoint.Kubernetes.Snapshots
latestEndpointReference.Agent.Version = endpoint.Agent.Version
err = handler.DataStore.Endpoint().UpdateEndpoint(latestEndpointReference.ID, latestEndpointReference)

View File

@ -329,5 +329,10 @@ func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) *
}
}
err = handler.SnapshotService.FillSnapshotData(endpoint)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to add snapshot data", err}
}
return response.JSON(w, endpoint)
}

View File

@ -24,6 +24,7 @@ type EnvironmentsQuery struct {
status []portainer.EndpointStatus
edgeDevice *bool
edgeDeviceUntrusted bool
excludeSnapshots bool
name string
agentVersions []string
}
@ -74,6 +75,8 @@ func parseQuery(r *http.Request) (EnvironmentsQuery, error) {
edgeDeviceUntrusted, _ := request.RetrieveBooleanQueryParameter(r, "edgeDeviceUntrusted", true)
excludeSnapshots, _ := request.RetrieveBooleanQueryParameter(r, "excludeSnapshots", true)
return EnvironmentsQuery{
search: search,
types: endpointTypes,
@ -84,6 +87,7 @@ func parseQuery(r *http.Request) (EnvironmentsQuery, error) {
status: status,
edgeDevice: edgeDevice,
edgeDeviceUntrusted: edgeDeviceUntrusted,
excludeSnapshots: excludeSnapshots,
name: name,
agentVersions: agentVersions,
}, nil

View File

@ -57,6 +57,15 @@ func (factory *ProxyFactory) newDockerHTTPProxy(endpoint *portainer.Endpoint) (h
endpointURL.Scheme = "https"
}
snapshot, err := factory.dataStore.Snapshot().Snapshot(endpoint.ID)
if err != nil {
return nil, err
}
if snapshot.Docker != nil {
endpoint.Snapshots = []portainer.DockerSnapshot{*snapshot.Docker}
}
transportParameters := &docker.TransportParameters{
Endpoint: endpoint,
DataStore: factory.dataStore,

View File

@ -119,27 +119,59 @@ func (service *Service) SnapshotEndpoint(endpoint *portainer.Endpoint) error {
return service.snapshotDockerEndpoint(endpoint)
}
func (service *Service) snapshotKubernetesEndpoint(endpoint *portainer.Endpoint) error {
snapshot, err := service.kubernetesSnapshotter.CreateSnapshot(endpoint)
func (service *Service) Create(snapshot portainer.Snapshot) error {
return service.dataStore.Snapshot().Create(&snapshot)
}
func (service *Service) FillSnapshotData(endpoint *portainer.Endpoint) error {
snapshot, err := service.dataStore.Snapshot().Snapshot(endpoint.ID)
if service.dataStore.IsErrObjectNotFound(err) {
endpoint.Snapshots = []portainer.DockerSnapshot{}
endpoint.Kubernetes.Snapshots = []portainer.KubernetesSnapshot{}
return nil
}
if err != nil {
return err
}
if snapshot != nil {
endpoint.Kubernetes.Snapshots = []portainer.KubernetesSnapshot{*snapshot}
if snapshot.Docker != nil {
endpoint.Snapshots = []portainer.DockerSnapshot{*snapshot.Docker}
}
if snapshot.Kubernetes != nil {
endpoint.Kubernetes.Snapshots = []portainer.KubernetesSnapshot{*snapshot.Kubernetes}
}
return nil
}
func (service *Service) snapshotKubernetesEndpoint(endpoint *portainer.Endpoint) error {
kubernetesSnapshot, err := service.kubernetesSnapshotter.CreateSnapshot(endpoint)
if err != nil {
return err
}
if kubernetesSnapshot != nil {
snapshot := &portainer.Snapshot{EndpointID: endpoint.ID, Kubernetes: kubernetesSnapshot}
return service.dataStore.Snapshot().Create(snapshot)
}
return nil
}
func (service *Service) snapshotDockerEndpoint(endpoint *portainer.Endpoint) error {
snapshot, err := service.dockerSnapshotter.CreateSnapshot(endpoint)
dockerSnapshot, err := service.dockerSnapshotter.CreateSnapshot(endpoint)
if err != nil {
return err
}
if snapshot != nil {
endpoint.Snapshots = []portainer.DockerSnapshot{*snapshot}
if dockerSnapshot != nil {
snapshot := &portainer.Snapshot{EndpointID: endpoint.ID, Docker: dockerSnapshot}
return service.dataStore.Snapshot().Create(snapshot)
}
return nil
@ -203,8 +235,6 @@ func (service *Service) snapshotEndpoints() error {
latestEndpointReference.Status = portainer.EndpointStatusDown
}
latestEndpointReference.Snapshots = endpoint.Snapshots
latestEndpointReference.Kubernetes.Snapshots = endpoint.Kubernetes.Snapshots
latestEndpointReference.Agent.Version = endpoint.Agent.Version
err = service.dataStore.Endpoint().UpdateEndpoint(latestEndpointReference.ID, latestEndpointReference)

View File

@ -25,6 +25,7 @@ type testDatastore struct {
role dataservices.RoleService
sslSettings dataservices.SSLSettingsService
settings dataservices.SettingsService
snapshot dataservices.SnapshotService
stack dataservices.StackService
tag dataservices.TagService
teamMembership dataservices.TeamMembershipService
@ -69,6 +70,7 @@ func (d *testDatastore) APIKeyRepository() dataservices.APIKeyRepository {
return d.apiKeyRepositoryService
}
func (d *testDatastore) Settings() dataservices.SettingsService { return d.settings }
func (d *testDatastore) Snapshot() dataservices.SnapshotService { return d.snapshot }
func (d *testDatastore) SSLSettings() dataservices.SSLSettingsService { return d.sslSettings }
func (d *testDatastore) Stack() dataservices.StackService { return d.stack }
func (d *testDatastore) Tag() dataservices.TagService { return d.tag }

View File

@ -1243,6 +1243,12 @@ type (
// WebhookType represents the type of resource a webhook is related to
WebhookType int
Snapshot struct {
EndpointID EndpointID `json:"EndpointId"`
Docker *DockerSnapshot `json:"Docker"`
Kubernetes *KubernetesSnapshot `json:"Kubernetes"`
}
// CLIService represents a service for managing CLI
CLIService interface {
ParseFlags(version string) (*CLIFlags, error)
@ -1420,6 +1426,7 @@ type (
Start()
SetSnapshotInterval(snapshotInterval string) error
SnapshotEndpoint(endpoint *Endpoint) error
FillSnapshotData(endpoint *Endpoint) error
}
// SwarmStackManager represents a service to manage Swarm stacks

View File

@ -92,6 +92,7 @@ function Loader({ children, storageKey }: LoaderProps) {
edgeDevice: true,
search: debouncedSearchValue,
types: EdgeTypes,
excludeSnapshots: true,
...pagination,
},
settings.autoRefreshRate * 1000

View File

@ -17,6 +17,7 @@ export function WaitingRoomView() {
const { environments, isLoading, totalCount } = useEnvironmentList({
edgeDevice: true,
edgeDeviceUntrusted: true,
excludeSnapshots: true,
types: EdgeTypes,
});

View File

@ -24,6 +24,7 @@ export interface EnvironmentsQueryParams {
status?: EnvironmentStatus[];
edgeDevice?: boolean;
edgeDeviceUntrusted?: boolean;
excludeSnapshots?: boolean;
provisioned?: boolean;
name?: string;
agentVersions?: string[];

View File

@ -50,7 +50,7 @@ function EndpointsController($q, $scope, $state, $async, EndpointService, GroupS
function getPaginatedEndpoints(start, limit, search) {
const deferred = $q.defer();
$q.all({
endpoints: getEnvironments({ start, limit, query: { search } }),
endpoints: getEnvironments({ start, limit, query: { search, excludeSnapshots: true } }),
groups: GroupService.groups(),
})
.then(function success(data) {