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
Changes from 1 commit
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
Prev Previous commit
Next Next commit
snapshot provider, schedule, and retention policy
Craig O'Donnell committed Nov 16, 2023
commit 7d23c76d8acc5283092c8bee4eb33c44751a82fa
37 changes: 23 additions & 14 deletions pkg/api/reporting/types/types.go
Original file line number Diff line number Diff line change
@@ -2,20 +2,23 @@ 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"`
SnapshotSchedule string `json:"snapshot_schedule"`
SnapshotRetentionPolicy string `json:"snapshot_retention_policy"`
}

type DownstreamInfo struct {
@@ -31,6 +34,12 @@ type DownstreamInfo struct {
NativeHelmInstalls int `json:"native_helm_installs"`
}

type SnapshotReport struct {
Provider string
Schedule string
RetentionPolicy string
}

// This type is mimicked in the preflight_report table.
type PreflightStatus struct {
InstanceID string `json:"instance_id"`
56 changes: 54 additions & 2 deletions pkg/reporting/app.go
Original file line number Diff line number Diff line change
@@ -19,10 +19,12 @@ import (
"github.com/replicatedhq/kots/pkg/kotsutil"
"github.com/replicatedhq/kots/pkg/kurl"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/snapshot"
"github.com/replicatedhq/kots/pkg/store"
"github.com/replicatedhq/kots/pkg/util"
troubleshootpreflight "github.com/replicatedhq/troubleshoot/pkg/preflight"
"github.com/segmentio/ksuid"
veleroclientv1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
helmrelease "helm.sh/helm/v3/pkg/release"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@@ -33,6 +35,12 @@ var (
clusterID string // set when in Helm managed mode
)

type SnapshotReport struct {
Provider string
Schedule string
RetentionPolicy string
}

func Init() error {
if util.IsHelmManaged() {
err := initFromHelm()
@@ -185,9 +193,14 @@ func GetReportingInfo(appID string) *types.ReportingInfo {
UserAgent: buildversion.GetUserAgent(),
}

clientset, err := k8sutil.GetClientset()
cfg, err := k8sutil.GetClusterConfig()
if err != nil {
logger.Debugf(errors.Wrap(err, "failed to get kubernetes clientset").Error())
logger.Debugf("failed to get cluster config: %v", err.Error())
}

clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
logger.Debugf("failed to get clientset: %v", err.Error())
}

if util.IsHelmManaged() {
@@ -248,6 +261,23 @@ func GetReportingInfo(appID string) *types.ReportingInfo {
}

r.IsGitOpsEnabled, r.GitOpsProvider = getGitOpsReport(clientset, appID, r.ClusterID)

veleroClient, err := veleroclientv1.NewForConfig(cfg)
if err != nil {
logger.Debugf("failed to get velero client: %v", err.Error())
}

if clientset != nil && veleroClient != nil {
report, err := getSnapshotReport(store.GetStore(), clientset, veleroClient, appID)
if err != nil {
logger.Debugf("failed to get snapshot report: %v", err.Error())
} else {
r.SnapshotProvider = report.Provider
r.SnapshotSchedule = report.Schedule
r.SnapshotRetentionPolicy = report.RetentionPolicy
}
}

return &r
}

@@ -325,3 +355,25 @@ func getGitOpsReport(clientset kubernetes.Interface, appID string, clusterID str
}
return false, ""
}

func getSnapshotReport(kotsStore store.Store, clientset kubernetes.Interface, veleroClient veleroclientv1.VeleroV1Interface, appID string) (*SnapshotReport, error) {
report := &SnapshotReport{}

bsl, err := snapshot.FindBackupStoreLocation(context.TODO(), clientset, veleroClient, util.PodNamespace)
Copy link
Member

Choose a reason for hiding this comment

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

How about calling this outside of the getSnapshotReport function and pass the BSL as a parameter to avoid refactoring lots of the code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

bsl as a parameter to getSnapshotReport makes sense. it still seems like a worthwhile refactor to open up unit testing of snapshot code paths, but i can revert that if needed

if err != nil {
return nil, errors.Wrap(err, "failed to find backup store location")
}
if bsl == nil {
return nil, errors.New("no backup store location found")
}
report.Provider = bsl.Spec.Provider

app, err := kotsStore.GetApp(appID)
if err != nil {
return nil, errors.Wrap(err, "failed to get app")
}
report.Schedule = app.SnapshotSchedule
report.RetentionPolicy = app.SnapshotTTL

return report, nil
}
3 changes: 3 additions & 0 deletions pkg/reporting/app_airgap.go
Original file line number Diff line number Diff line change
@@ -69,6 +69,9 @@ func BuildInstanceReport(licenseID string, reportingInfo *types.ReportingInfo) *
KurlInstallID: reportingInfo.KURLInstallID,
IsGitOpsEnabled: reportingInfo.IsGitOpsEnabled,
GitOpsProvider: reportingInfo.GitOpsProvider,
SnapshotProvider: reportingInfo.SnapshotProvider,
SnapshotSchedule: reportingInfo.SnapshotSchedule,
SnapshotRetentionPolicy: reportingInfo.SnapshotRetentionPolicy,
DownstreamChannelID: reportingInfo.Downstream.ChannelID,
DownstreamChannelSequence: downstreamSequence,
DownstreamChannelName: reportingInfo.Downstream.ChannelName,
3 changes: 3 additions & 0 deletions pkg/reporting/instance_report.go
Original file line number Diff line number Diff line change
@@ -29,6 +29,9 @@ type InstanceReportEvent struct {
KurlInstallID string `json:"kurl_install_id,omitempty"`
IsGitOpsEnabled bool `json:"is_gitops_enabled"`
GitOpsProvider string `json:"gitops_provider"`
SnapshotProvider string `json:"snapshot_provider"`
SnapshotSchedule string `json:"snapshot_schedule"`
SnapshotRetentionPolicy string `json:"snapshot_retention_policy"`
DownstreamChannelID string `json:"downstream_channel_id,omitempty"`
DownstreamChannelSequence uint64 `json:"downstream_channel_sequence,omitempty"`
DownstreamChannelName string `json:"downstream_channel_name,omitempty"`
4 changes: 4 additions & 0 deletions pkg/reporting/util.go
Original file line number Diff line number Diff line change
@@ -68,6 +68,10 @@ func GetReportingInfoHeaders(reportingInfo *types.ReportingInfo) map[string]stri
headers["X-Replicated-IsGitOpsEnabled"] = strconv.FormatBool(reportingInfo.IsGitOpsEnabled)
headers["X-Replicated-GitOpsProvider"] = reportingInfo.GitOpsProvider

headers["X-Replicated-SnapshotProvider"] = reportingInfo.SnapshotProvider
headers["X-Replicated-SnapshotSchedule"] = reportingInfo.SnapshotSchedule
headers["X-Replicated-SnapshotRetentionPolicy"] = reportingInfo.SnapshotRetentionPolicy

if reportingInfo.K8sDistribution != "" {
headers["X-Replicated-K8sDistribution"] = reportingInfo.K8sDistribution
}

Unchanged files with check annotations Beta

className="btn primary blue"
disabled={preflightCheck?.showDeploymentBlocked}
onClick={() =>
preflightCheck?.shouldShowConfirmContinueWithFailedPreflights

Check warning on line 208 in web/src/components/PreflightResultPage.tsx

GitHub Actions / lint-web

This line has a length of 85. Maximum allowed is 80
? setShowContinueWithFailedPreflightsModal(true)
: deployKotsDownstream({
continueWithFailedPreflights: true,
{generateAddNodeCommandError?.message}
</p>
)}
{!generateAddNodeCommandLoading && generateAddNodeCommand?.command && (

Check warning on line 515 in web/src/components/apps/EmbeddedClusterManagement.tsx

GitHub Actions / lint-web

This line has a length of 83. Maximum allowed is 80
<>
<CodeSnippet
key={selectedNodeTypes.toString()}