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

Backup implementation: controller, plugins, collection, webhooks #841

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
5 changes: 4 additions & 1 deletion PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ resources:
controller: true
domain: hmc.mirantis.com
group: hmc.mirantis.com
kind: Backup
kind: ManagementBackup
path: github.com/K0rdent/kcm/api/v1alpha1
version: v1alpha1
webhooks:
validation: true
webhookVersion: v1
version: "3"
77 changes: 0 additions & 77 deletions api/v1alpha1/backup_types.go

This file was deleted.

95 changes: 95 additions & 0 deletions api/v1alpha1/management_backup_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1alpha1

import (
velerov1 "github.com/zerospiel/velero/pkg/apis/velero/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
// Name to label most of the HMC-related components.
// Mostly utilized by the backup feature.
GenericComponentLabelName = "hmc.mirantis.com/component"
// Component label value for the HMC-related components.
GenericComponentLabelValueHMC = "hmc"
)

// ManagementBackupSpec defines the desired state of ManagementBackup
type ManagementBackupSpec struct{}

// ManagementBackupStatus defines the observed state of ManagementBackup
type ManagementBackupStatus struct {
// Reference to the underlying Velero object being managed.
// Might be either Velero Backup or Schedule.
Reference *corev1.ObjectReference `json:"reference,omitempty"`
// NextAttempt indicates the time when the next scheduled backup will be performed.
// Always absent for the ManagementBackups with a schedule.
NextAttempt *metav1.Time `json:"nextAttempt,omitempty"`
// Last Velero Backup that has been created.
LastBackup *velerov1.BackupStatus `json:"lastBackup,omitempty"`
// Status of the Velero Schedule for the Management scheduled backups.
// Always absent for the ManagementBackups with a schedule.
Schedule *velerov1.ScheduleStatus `json:"schedule,omitempty"`
// SchedulePaused indicates if the Velero Schedule is paused.
SchedulePaused bool `json:"schedulePaused,omitempty"`
}

func (in *ManagementBackupStatus) GetLastBackupCopy() velerov1.BackupStatus {
if in.LastBackup == nil {
return velerov1.BackupStatus{}
}
return *in.LastBackup
}

func (in *ManagementBackupStatus) GetScheduleCopy() velerov1.ScheduleStatus {
if in.Schedule == nil {
return velerov1.ScheduleStatus{}
}
return *in.Schedule
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster,shortName=hmcbackup;mgmtbackup
// +kubebuilder:printcolumn:name="NextBackup",type=string,JSONPath=`.status.nextAttempt`,description="Next scheduled attempt to back up",priority=0
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.schedule.phase`,description="Schedule phase",priority=0
// +kubebuilder:printcolumn:name="SinceLastBackup",type=date,JSONPath=`.status.schedule.lastBackup`,description="Time elapsed since last backup run",priority=1
// +kubebuilder:printcolumn:name="LastBackupStatus",type=string,JSONPath=`.status.lastBackup.phase`,description="Status of last backup run",priority=0
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`,description="Time elapsed since object creation",priority=0
// +kubebuilder:printcolumn:name="Paused",type=boolean,JSONPath=`.status.schedulePaused`,description="Schedule is on pause",priority=1

// ManagementBackup is the Schema for the backups API
type ManagementBackup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ManagementBackupSpec `json:"spec,omitempty"`
Status ManagementBackupStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// ManagementBackupList contains a list of ManagementBackup
type ManagementBackupList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ManagementBackup `json:"items"`
}

func init() {
SchemeBuilder.Register(&ManagementBackup{}, &ManagementBackupList{})
}
33 changes: 28 additions & 5 deletions api/v1alpha1/management_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type ManagementSpec struct {
// Providers is the list of supported CAPI providers.
Providers []Provider `json:"providers,omitempty"`

Backup ManagementBackup `json:"backup,omitempty"`
Backup Backup `json:"backup,omitempty"`
}

// Core represents a structure describing core Management components.
Expand All @@ -55,15 +55,29 @@ type Core struct {
CAPI Component `json:"capi,omitempty"`
}

// ManagementBackup enables a feature to backup HMC objects into a cloud.
type ManagementBackup struct {
// Schedule is a Cron expression defining when to run the scheduled Backup.
// Backup enables a feature to backup HMC objects into a cloud.
type Backup struct {
// +kubebuilder:example={customPlugins: {"alibabacloud": "registry.<region>.aliyuncs.com/acs/velero:1.4.2", "community.openstack.org/openstack": "lirt/velero-plugin-for-openstack:v0.6.0"}}

// CustomPlugins holds key value pairs with [Velero] [community] and [custom] plugins, where:
// - key represents the provider's name in the format [velero.io/]<plugin-name>;
// - value represents the provider's plugin name;
//
// Provider name must be exactly the same as in a [BackupStorageLocation] object.
//
// [Velero]: https://velero.io
// [community]: https://velero.io/docs/v1.15/supported-providers/#provider-plugins-maintained-by-the-velero-community
// [custom]: https://velero.io/docs/v1.15/custom-plugins/
// [BackupStorageLocation]: https://velero.io/docs/v1.15/api-types/backupstoragelocation/
CustomPlugins map[string]string `json:"customPlugins,omitempty"`

// Schedule is a Cron expression defining when to run the scheduled ManagementBackup.
// Default value is to backup every 6 hours.
Schedule string `json:"schedule,omitempty"`

// Flag to indicate whether the backup feature is enabled.
// If set to true, [Velero] platform will be installed.
// If set to false, creation or modification of Backups/Restores will be blocked.
// If set to false, creation or modification of ManagementBackups will be blocked.
//
// [Velero]: https://velero.io
Enabled bool `json:"enabled,omitempty"`
Expand Down Expand Up @@ -123,6 +137,15 @@ func (in *Management) Templates() []string {
return templates
}

// GetBackupSchedule safely returns backup schedule.
func (in *Management) GetBackupSchedule() string {
if in == nil {
return ""
}

return in.Spec.Backup.Schedule
}

// ManagementStatus defines the observed state of Management
type ManagementStatus struct {
// For each CAPI provider name holds its compatibility [contract versions]
Expand Down
7 changes: 2 additions & 5 deletions api/v1alpha1/templates_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,10 @@ import (
helmcontrollerv2 "github.com/fluxcd/helm-controller/api/v2"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
clusterapiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
)

const (
// ChartAnnotationProviderName is the annotation set on components in a Template.
// This annotations allows to identify all the components belonging to a provider.
ChartAnnotationProviderName = "cluster.x-k8s.io/provider"

chartAnnoCAPIPrefix = "cluster.x-k8s.io/"

DefaultRepoName = "hmc-templates"
Expand Down Expand Up @@ -103,7 +100,7 @@ func getProvidersList(providers Providers, annotations map[string]string) Provid
return slices.Compact(res)
}

providersFromAnno := annotations[ChartAnnotationProviderName]
providersFromAnno := annotations[clusterapiv1beta1.ProviderNameLabel]
if len(providersFromAnno) == 0 {
return Providers{}
}
Expand Down
Loading
Loading