package kubernetes
import (
"context"
"time"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/kubernetes/cli"
"github.com/rs/zerolog/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
type Snapshotter struct {
clientFactory *cli.ClientFactory
}
// NewSnapshotter returns a new Snapshotter instance
func NewSnapshotter(clientFactory *cli.ClientFactory) *Snapshotter {
return &Snapshotter{
clientFactory: clientFactory,
// CreateSnapshot creates a snapshot of a specific Kubernetes environment(endpoint)
func (snapshotter *Snapshotter) CreateSnapshot(endpoint *portainer.Endpoint) (*portainer.KubernetesSnapshot, error) {
client, err := snapshotter.clientFactory.CreateClient(endpoint)
if err != nil {
return nil, err
return snapshot(client, endpoint)
func snapshot(cli *kubernetes.Clientset, endpoint *portainer.Endpoint) (*portainer.KubernetesSnapshot, error) {
res := cli.RESTClient().Get().AbsPath("/healthz").Do(context.TODO())
if res.Error() != nil {
return nil, res.Error()
snapshot := &portainer.KubernetesSnapshot{}
err := snapshotVersion(snapshot, cli)
log.Warn().Str("endpoint", endpoint.Name).Err(err).Msg("unable to snapshot cluster version")
err = snapshotNodes(snapshot, cli)
log.Warn().Str("endpoint", endpoint.Name).Err(err).Msg("unable to snapshot cluster nodes")
snapshot.Time = time.Now().Unix()
return snapshot, nil
func snapshotVersion(snapshot *portainer.KubernetesSnapshot, cli *kubernetes.Clientset) error {
versionInfo, err := cli.ServerVersion()
return err
snapshot.KubernetesVersion = versionInfo.GitVersion
return nil
func snapshotNodes(snapshot *portainer.KubernetesSnapshot, cli *kubernetes.Clientset) error {
nodeList, err := cli.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
var totalCPUs, totalMemory int64
for _, node := range nodeList.Items {
totalCPUs += node.Status.Capacity.Cpu().Value()
totalMemory += node.Status.Capacity.Memory().Value()
snapshot.TotalCPU = totalCPUs
snapshot.TotalMemory = totalMemory
snapshot.NodeCount = len(nodeList.Items)