Skip to content

Commit

Permalink
Add new status for originCluster reference
Browse files Browse the repository at this point in the history
  • Loading branch information
mallardduck committed Nov 1, 2024
1 parent 5331844 commit f0b6b30
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 25 deletions.
3 changes: 3 additions & 0 deletions charts/rancher-backup-crd/templates/backup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ spec:
type: string
observedGeneration:
type: integer
originCluster:
nullable: true
type: string
storageLocation:
nullable: true
type: string
Expand Down
5 changes: 1 addition & 4 deletions pkg/apis/resources.cattle.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ var (
RestoreConditionReady = "Ready"
)

const (
BackupClusterOriginIndex = "field.cattle.io/originClusterId"
)

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand All @@ -43,6 +39,7 @@ type BackupSpec struct {

type BackupStatus struct {
Conditions []genericcondition.GenericCondition `json:"conditions"`
OriginCluster string `json:"originCluster,omitempty"`
LastSnapshotTS string `json:"lastSnapshotTs"`
NextSnapshotAt string `json:"nextSnapshotAt"`
ObservedGeneration int64 `json:"observedGeneration"`
Expand Down
23 changes: 20 additions & 3 deletions pkg/controllers/backup/cluster_origin.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ func newBackupClusterOriginConditionMeta(controllerClusterID string, backup *v1.
currentInPlaceRestoreCondition: false,
}

originAnnotationValue, ok := backup.GetAnnotations()[v1.BackupClusterOriginIndex]
conditionMeta.hasClusterOriginID = ok && originAnnotationValue != ""
originalValue := backup.Status.OriginCluster
conditionMeta.hasClusterOriginID = originalValue != ""
if conditionMeta.hasClusterOriginID {
conditionMeta.clusterOriginID = originAnnotationValue
conditionMeta.clusterOriginID = originalValue
}

currentOriginConditionString := condition.Cond(v1.BackupConditionClusterOrigin).GetStatus(backup)
Expand All @@ -55,6 +55,23 @@ func newBackupClusterOriginConditionMeta(controllerClusterID string, backup *v1.
// prepareClusterOriginConditions helps set the cluster origin conditions and reports if anything changed in this part of status.
func (h *handler) prepareClusterOriginConditions(backup *v1.Backup) bool {
conditionChanged := false
if !h.canUseClusterOriginStatus {
currentOriginConditionString := condition.Cond(v1.BackupConditionClusterOrigin).GetStatus(backup)
if currentOriginConditionString != "False" {
condition.Cond(v1.BackupConditionClusterOrigin).SetStatusBool(backup, false)
condition.Cond(v1.BackupConditionClusterOrigin).Message(backup, "CRD not updated to include cluster UID yet.")
conditionChanged = true
}
currentInPlaceRestoreString := condition.Cond(v1.BackupConditionInPlaceRestore).GetStatus(backup)
if currentInPlaceRestoreString != "False" {
condition.Cond(v1.BackupConditionInPlaceRestore).SetStatusBool(backup, false)
condition.Cond(v1.BackupConditionInPlaceRestore).Message(backup, "Cannot determine if in-place Restore is viable.")
conditionChanged = true
}

return conditionChanged
}

conditionMeta := newBackupClusterOriginConditionMeta(h.kubeSystemNS, backup)

// Fist pass we only care to set BackupConditionClusterOrigin based on if the context is there
Expand Down
32 changes: 14 additions & 18 deletions pkg/controllers/backup/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ type handler struct {
defaultBackupMountPath string
defaultS3BackupLocation *v1.S3ObjectStore
// TODO: rename to kubeSystemNamespaceUID; nit to improve clarity, it's not the string representation nor the NS resource
kubeSystemNS string
kubeSystemNS string
canUseClusterOriginStatus bool
}

const DefaultRetentionCount = 10
Expand All @@ -57,15 +58,16 @@ func Register(
defaultS3 *v1.S3ObjectStore) {

controller := &handler{
ctx: ctx,
backups: backups,
resourceSets: resourceSets,
secrets: secrets,
namespaces: namespaces,
discoveryClient: clientSet.Discovery(),
dynamicClient: dynamicInterface,
defaultBackupMountPath: defaultLocalBackupLocation,
defaultS3BackupLocation: defaultS3,
ctx: ctx,
backups: backups,
resourceSets: resourceSets,
secrets: secrets,
namespaces: namespaces,
discoveryClient: clientSet.Discovery(),
dynamicClient: dynamicInterface,
defaultBackupMountPath: defaultLocalBackupLocation,
defaultS3BackupLocation: defaultS3,
canUseClusterOriginStatus: util.VerifyBackupCrdHasClusterStatus(clientSet.ApiextensionsV1()),
}
if controller.defaultBackupMountPath != "" {
logrus.Infof("Default location for storing backups is %v", controller.defaultBackupMountPath)
Expand Down Expand Up @@ -185,21 +187,15 @@ func (h *handler) OnBackupChange(_ string, backup *v1.Backup) (*v1.Backup, error
}
}

backupAnnotations := backup.GetAnnotations()
if backupAnnotations == nil {
backupAnnotations = map[string]string{}
}
backupAnnotations[v1.BackupClusterOriginIndex] = h.kubeSystemNS
backup.SetAnnotations(backupAnnotations)
_, err = h.backups.Update(backup)

storageLocationType := backup.Status.StorageLocation
updateErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
var err error
backup, err = h.backups.Get(backup.Name, k8sv1.GetOptions{})
if err != nil {
return err
}
// Set the Cluster origin reference on backup
backup.Status.OriginCluster = h.kubeSystemNS
// reset conditions to remove the reconciling condition, because as per kstatus lib its presence is considered an error
backup.Status.Conditions = []genericcondition.GenericCondition{}

Expand Down
39 changes: 39 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ import (
"os"
"reflect"

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsClientSetv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"

v1core "github.com/rancher/wrangler/v3/pkg/generated/controllers/core/v1"
"github.com/sirupsen/logrus"
k8sv1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/server/options/encryptionconfig"
"k8s.io/apiserver/pkg/storage/value"
Expand Down Expand Up @@ -83,3 +87,38 @@ func FetchClusterUID(namespaces v1core.NamespaceController) (string, error) {

return string(kubesystemNamespace.UID), nil
}

// Define the GroupVersionResource for CRDs
var crdGVR = schema.GroupVersionResource{
Group: "apiextensions.k8s.io",
Version: "v1",
Resource: "customresourcedefinitions",
}

func getCRDDefinition(dynamicClient apiextensionsClientSetv1.ApiextensionsV1Interface, crdName string) (*apiextensionsv1.CustomResourceDefinition, error) {
crd, err := dynamicClient.CustomResourceDefinitions().Get(context.TODO(), crdName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return crd, nil
}

func VerifyBackupCrdHasClusterStatus(client apiextensionsClientSetv1.ApiextensionsV1Interface) bool {
crdName := "backups.resources.cattle.io"

crd, err := getCRDDefinition(client, crdName)
if err != nil {
logrus.Infof("Error fetching CRD: %v", err)
return false
}

// Inspect the status schema, for example
_, found := crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["status"].Properties["originCluster"]
if found {
logrus.Debugf("Status schema contains `originCluster` on CRD `%s`.\n", crdName)
return true
}

logrus.Debugf("`originCluster` not found on status schema for CRD `%s`.\n", crdName)
return false
}

0 comments on commit f0b6b30

Please sign in to comment.