Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

snapshot reporting #4138

Merged
merged 10 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions pkg/api/reporting/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ package types

// This type is mimicked in the instance_report table.
type ReportingInfo struct {
InstanceID string `json:"instance_id"`
ClusterID string `json:"cluster_id"`
Downstream DownstreamInfo `json:"downstream"`
AppStatus string `json:"app_status"`
IsKurl bool `json:"is_kurl"`
KurlNodeCountTotal int `json:"kurl_node_count_total"`
KurlNodeCountReady int `json:"kurl_node_count_ready"`
K8sVersion string `json:"k8s_version"`
K8sDistribution string `json:"k8s_distribution"`
UserAgent string `json:"user_agent"`
KOTSInstallID string `json:"kots_install_id"`
KURLInstallID string `json:"kurl_install_id"`
IsGitOpsEnabled bool `json:"is_gitops_enabled"`
GitOpsProvider string `json:"gitops_provider"`
InstanceID string `json:"instance_id"`
ClusterID string `json:"cluster_id"`
Downstream DownstreamInfo `json:"downstream"`
AppStatus string `json:"app_status"`
IsKurl bool `json:"is_kurl"`
KurlNodeCountTotal int `json:"kurl_node_count_total"`
KurlNodeCountReady int `json:"kurl_node_count_ready"`
K8sVersion string `json:"k8s_version"`
K8sDistribution string `json:"k8s_distribution"`
UserAgent string `json:"user_agent"`
KOTSInstallID string `json:"kots_install_id"`
KURLInstallID string `json:"kurl_install_id"`
IsGitOpsEnabled bool `json:"is_gitops_enabled"`
GitOpsProvider string `json:"gitops_provider"`
SnapshotProvider string `json:"snapshot_provider"`
SnapshotFullSchedule string `json:"snapshot_full_schedule"`
SnapshotFullTTL string `json:"snapshot_full_ttl"`
SnapshotPartialSchedule string `json:"snapshot_partial_schedule"`
SnapshotPartialTTL string `json:"snapshot_partial_ttl"`
}

type DownstreamInfo struct {
Expand Down
29 changes: 28 additions & 1 deletion pkg/handlers/snapshot_logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,44 @@ import (

"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/replicatedhq/kots/pkg/k8sutil"
snapshot "github.com/replicatedhq/kots/pkg/kotsadmsnapshot"
"github.com/replicatedhq/kots/pkg/logger"
kotssnapshot "github.com/replicatedhq/kots/pkg/snapshot"
"github.com/replicatedhq/kots/pkg/util"
velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
veleroclientv1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
"k8s.io/client-go/kubernetes"
)

func (h *Handler) DownloadSnapshotLogs(w http.ResponseWriter, r *http.Request) {
backupName := mux.Vars(r)["backup"]

bsl, err := kotssnapshot.FindBackupStoreLocation(r.Context(), util.PodNamespace)
cfg, err := k8sutil.GetClusterConfig()
if err != nil {
err = errors.Wrap(err, "failed to get cluster config")
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}

clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
err = errors.Wrap(err, "failed to create clientset")
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
err = errors.Wrap(err, "failed to create velero clientset")
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}

bsl, err := kotssnapshot.FindBackupStoreLocation(r.Context(), clientset, veleroClient, util.PodNamespace)
if err != nil {
err = errors.Wrap(err, "failed to find backup store location")
logger.Error(err)
Expand Down
24 changes: 18 additions & 6 deletions pkg/kotsadm/minio.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/snapshot"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
veleroclientv1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
corev1 "k8s.io/api/core/v1"
kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -180,7 +181,22 @@ func MigrateExistingMinioFilesystemDeployments(log *logger.CLILogger, deployOpti
}
veleroNamespace := veleroStatus.Namespace

bsl, err := snapshot.FindBackupStoreLocation(context.TODO(), deployOptions.Namespace)
cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return errors.Wrap(err, "failed to get cluster config")
}

clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return errors.Wrap(err, "failed to create clientset")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return errors.Wrap(err, "failed to create velero clientset")
}

bsl, err := snapshot.FindBackupStoreLocation(context.TODO(), clientset, veleroClient, deployOptions.Namespace)
Copy link
Contributor Author

@cbodonnell cbodonnell Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored FindBackupStoreLocation to accept a velero client interface so we can unit test it. A good chunk of the diff is related to this. We could use a similar pattern to increase unit test coverage for snapshots overall.

if err != nil {
return errors.Wrap(err, "failed to find backupstoragelocations")
}
Expand Down Expand Up @@ -226,10 +242,6 @@ func MigrateExistingMinioFilesystemDeployments(log *logger.CLILogger, deployOpti
}

// Add the config map to configure the new plugin
clientset, err := k8sutil.GetClientset()
if err != nil {
return errors.Wrap(err, "failed to get k8s clientset")
}
fsDeployOptions := &snapshot.FileSystemDeployOptions{
Namespace: deployOptions.Namespace,
IsOpenShift: k8sutil.IsOpenShift(clientset),
Expand All @@ -250,7 +262,7 @@ func MigrateExistingMinioFilesystemDeployments(log *logger.CLILogger, deployOpti
success := false
defer func() {
if !success {
err := snapshot.RevertToMinioFS(context.TODO(), deployOptions.Namespace, veleroNamespace, previousBsl)
err := snapshot.RevertToMinioFS(context.TODO(), clientset, veleroClient, deployOptions.Namespace, veleroNamespace, previousBsl)
if err != nil {
log.Error(errors.Wrap(err, "Could not restore minio backup storage location"))
return
Expand Down
137 changes: 81 additions & 56 deletions pkg/kotsadmsnapshot/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,23 @@ func CreateApplicationBackup(ctx context.Context, a *apptypes.App, isScheduled b
return nil, errors.Wrap(err, "failed to get app version archive")
}

cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to get cluster config")
}

clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

kotsadmNamespace := util.PodNamespace
kotsadmVeleroBackendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
kotsadmVeleroBackendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return nil, errors.Wrap(err, "failed to find backupstoragelocations")
}
Expand Down Expand Up @@ -160,26 +175,11 @@ func CreateApplicationBackup(ctx context.Context, a *apptypes.App, isScheduled b
}
}

clientset, err := k8sutil.GetClientset()
if err != nil {
return nil, errors.Wrap(err, "failed to create k8s clientset")
}

err = excludeShutdownPodsFromBackup(ctx, clientset, veleroBackup)
if err != nil {
logger.Error(errors.Wrap(err, "failed to exclude shutdown pods from backup"))
}

cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to get cluster config")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}

backup, err := veleroClient.Backups(kotsadmVeleroBackendStorageLocation.Namespace).Create(ctx, veleroBackup, metav1.CreateOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to create velero backup")
Expand All @@ -191,9 +191,14 @@ func CreateApplicationBackup(ctx context.Context, a *apptypes.App, isScheduled b
func CreateInstanceBackup(ctx context.Context, cluster *downstreamtypes.Downstream, isScheduled bool) (*velerov1.Backup, error) {
logger.Debug("creating instance backup")

clientset, err := k8sutil.GetClientset()
cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to get cluster config")
}

clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create k8s clientset")
return nil, errors.Wrap(err, "failed to create clientset")
}

isKurl, err := kurl.IsKurl(clientset)
Expand Down Expand Up @@ -310,7 +315,12 @@ func CreateInstanceBackup(ctx context.Context, cluster *downstreamtypes.Downstre
backupHooks.Resources = append(backupHooks.Resources, veleroBackup.Spec.Hooks.Resources...)
}

kotsadmVeleroBackendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

kotsadmVeleroBackendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return nil, errors.Wrap(err, "failed to find backupstoragelocations")
}
Expand Down Expand Up @@ -398,16 +408,6 @@ func CreateInstanceBackup(ctx context.Context, cluster *downstreamtypes.Downstre
logger.Error(errors.Wrap(err, "failed to exclude shutdown pods from backup"))
}

cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to get cluster config")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

backup, err := veleroClient.Backups(kotsadmVeleroBackendStorageLocation.Namespace).Create(ctx, veleroBackup, metav1.CreateOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to create velero backup")
Expand All @@ -422,12 +422,17 @@ func ListBackupsForApp(ctx context.Context, kotsadmNamespace string, appID strin
return nil, errors.Wrap(err, "failed to get cluster config")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}

backendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

backendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return nil, errors.Wrap(err, "failed to find backupstoragelocations")
}
Expand Down Expand Up @@ -550,12 +555,17 @@ func ListInstanceBackups(ctx context.Context, kotsadmNamespace string) ([]*types
return nil, errors.Wrap(err, "failed to get cluster config")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}

backendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

backendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return nil, errors.Wrap(err, "failed to find backupstoragelocations")
}
Expand Down Expand Up @@ -717,7 +727,22 @@ func getSnapshotVolumeSummary(ctx context.Context, veleroBackup *velerov1.Backup
}

func GetBackup(ctx context.Context, kotsadmNamespace string, snapshotName string) (*velerov1.Backup, error) {
bsl, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to get cluster config")
}

clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

bsl, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return nil, errors.Wrap(err, "failed to get velero namespace")
}
Expand All @@ -728,26 +753,31 @@ func GetBackup(ctx context.Context, kotsadmNamespace string, snapshotName string
veleroNamespace := bsl.Namespace

// get the backup
cfg, err := k8sutil.GetClusterConfig()
backup, err := veleroClient.Backups(veleroNamespace).Get(ctx, snapshotName, metav1.GetOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to get cluster config")
return nil, errors.Wrap(err, "failed to get backup")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
return backup, nil
}

func DeleteBackup(ctx context.Context, kotsadmNamespace string, snapshotName string) error {
cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
return errors.Wrap(err, "failed to get cluster config")
}

backup, err := veleroClient.Backups(veleroNamespace).Get(ctx, snapshotName, metav1.GetOptions{})
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to get backup")
return errors.Wrap(err, "failed to create clientset")
}

return backup, nil
}
veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return errors.Wrap(err, "failed to create velero clientset")
}

func DeleteBackup(ctx context.Context, kotsadmNamespace string, snapshotName string) error {
bsl, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
bsl, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return errors.Wrap(err, "failed to get velero namespace")
}
Expand All @@ -766,16 +796,6 @@ func DeleteBackup(ctx context.Context, kotsadmNamespace string, snapshotName str
},
}

cfg, err := k8sutil.GetClusterConfig()
if err != nil {
return errors.Wrap(err, "failed to get cluster config")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return errors.Wrap(err, "failed to create clientset")
}

_, err = veleroClient.DeleteBackupRequests(veleroNamespace).Create(context.TODO(), veleroDeleteBackupRequest, metav1.CreateOptions{})
if err != nil {
return errors.Wrap(err, "failed to create delete backup request")
Expand Down Expand Up @@ -820,12 +840,17 @@ func GetBackupDetail(ctx context.Context, kotsadmNamespace string, backupName st
return nil, errors.Wrap(err, "failed to get cluster config")
}

veleroClient, err := veleroclientv1.NewForConfig(cfg)
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create clientset")
}

backendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, kotsadmNamespace)
veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create velero clientset")
}

backendStorageLocation, err := kotssnapshot.FindBackupStoreLocation(ctx, clientset, veleroClient, kotsadmNamespace)
if err != nil {
return nil, errors.Wrap(err, "failed to find backupstoragelocations")
}
Expand Down
Loading
Loading