Work on flapping exports status

This commit is contained in:
2025-01-10 16:20:54 +00:00
parent f556d864d1
commit 35e64bd439
4 changed files with 124 additions and 104 deletions
@@ -76,6 +76,10 @@ type ClusterImageExportSpec struct {
// ClusterImageExportStatus defines the observed state of ClusterImageExport // ClusterImageExportStatus defines the observed state of ClusterImageExport
type ClusterImageExportStatus struct { type ClusterImageExportStatus struct {
Progress string `json:"progress,omitempty"` Progress string `json:"progress,omitempty"`
// Total number of images to be exported
TotalImages int `json:"totalImages,omitempty"`
// Number of images that have completed export
CompletedImages int `json:"completedImages,omitempty"`
} }
// +kubebuilder:object:root=true // +kubebuilder:object:root=true
@@ -85,6 +89,8 @@ type ClusterImageExportStatus struct {
// +kubebuilder:printcolumn:name="BasePath",type="string",JSONPath=".spec.basePath" // +kubebuilder:printcolumn:name="BasePath",type="string",JSONPath=".spec.basePath"
// +kubebuilder:printcolumn:name="Storage",type="string",JSONPath=".spec.storage.target" // +kubebuilder:printcolumn:name="Storage",type="string",JSONPath=".spec.storage.target"
// +kubebuilder:printcolumn:name="Progress",type="string",JSONPath=".status.progress" // +kubebuilder:printcolumn:name="Progress",type="string",JSONPath=".status.progress"
// +kubebuilder:printcolumn:name="Images",type="string",JSONPath=".status.completedImages"
// +kubebuilder:printcolumn:name="Total",type="string",JSONPath=".status.totalImages"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
type ClusterImageExport struct { type ClusterImageExport struct {
metav1.TypeMeta `json:",inline"` metav1.TypeMeta `json:",inline"`
@@ -24,6 +24,12 @@ spec:
- jsonPath: .status.progress - jsonPath: .status.progress
name: Progress name: Progress
type: string type: string
- jsonPath: .status.completedImages
name: Images
type: string
- jsonPath: .status.totalImages
name: Total
type: string
- jsonPath: .metadata.creationTimestamp - jsonPath: .metadata.creationTimestamp
name: Age name: Age
type: date type: date
@@ -160,8 +166,14 @@ spec:
status: status:
description: ClusterImageExportStatus defines the observed state of ClusterImageExport description: ClusterImageExportStatus defines the observed state of ClusterImageExport
properties: properties:
completedImages:
description: Number of images that have completed export
type: integer
progress: progress:
type: string type: string
totalImages:
description: Total number of images to be exported
type: integer
type: object type: object
type: object type: object
served: true served: true
+67 -68
View File
@@ -4,71 +4,70 @@ kind: ClusterRole
metadata: metadata:
name: impex-mgr name: impex-mgr
rules: rules:
- apiGroups: - apiGroups:
- "" - ""
resources: resources:
- pods - pods
verbs: verbs:
- create - create
- delete - delete
- deletecollection - get
- get - list
- list - patch
- patch - update
- update - watch
- watch - apiGroups:
- apiGroups: - apps
- apps resources:
resources: - daemonsets
- daemonsets - deployments
- deployments verbs:
verbs: - get
- get - list
- list - watch
- watch - apiGroups:
- apiGroups: - batch
- batch resources:
resources: - cronjobs
- cronjobs verbs:
verbs: - get
- get - list
- list - watch
- watch - apiGroups:
- apiGroups: - batch
- batch resources:
resources: - jobs
- jobs verbs:
verbs: - create
- create - delete
- delete - get
- get - list
- list - patch
- patch - update
- update - watch
- watch - apiGroups:
- apiGroups: - raczylo.com
- raczylo.com resources:
resources: - '*'
- "*" verbs:
verbs: - create
- create - delete
- delete - get
- get - list
- list - patch
- patch - update
- update - watch
- watch - apiGroups:
- apiGroups: - raczylo.com
- raczylo.com resources:
resources: - '*/finalizers'
- "*/finalizers" verbs:
verbs: - update
- update - apiGroups:
- apiGroups: - raczylo.com
- raczylo.com resources:
resources: - '*/status'
- "*/status" verbs:
verbs: - get
- get - patch
- patch - update
- update
@@ -83,38 +83,15 @@ func (r *ClusterImageExportReconciler) Reconcile(ctx context.Context, req ctrl.R
} }
} }
// Handle status updates with retries // Proceed with reconciliation logic
if err := r.updateStatusWithRetry(ctx, clusterImageExport, func(export *raczylocomv1.ClusterImageExport) error { // Get list of all images to be exported
// Reset status if the ClusterImageExport is in a completed state
if export.Status.Progress == shared.STATUS_SUCCESS || export.Status.Progress == shared.STATUS_FAILED {
export.Status.Progress = ""
return nil
}
// Set to PENDING if empty
if export.Status.Progress == "" {
export.Status.Progress = shared.STATUS_PENDING
return nil
}
return nil
}); err != nil {
l.Error(err, "unable to update ClusterImageExport status")
return ctrl.Result{}, err
}
// If we just reset the status, requeue to process with reset status
if clusterImageExport.Status.Progress == "" {
return ctrl.Result{Requeue: true}, nil
}
// Proceed with the rest of the reconciliation logic
fullImagesList, err := r.listImagesInCluster(ctx, l, clusterImageExport) fullImagesList, err := r.listImagesInCluster(ctx, l, clusterImageExport)
if err != nil { if err != nil {
l.Error(err, "unable to list images in the cluster") l.Error(err, "unable to list images in the cluster")
return ctrl.Result{}, err return ctrl.Result{}, err
} }
// Add additional images if specified
if len(clusterImageExport.Spec.AdditionalImages) > 0 { if len(clusterImageExport.Spec.AdditionalImages) > 0 {
for _, image := range clusterImageExport.Spec.AdditionalImages { for _, image := range clusterImageExport.Spec.AdditionalImages {
img, err := shared.ProcessContainerName(image) img, err := shared.ProcessContainerName(image)
@@ -126,12 +103,19 @@ func (r *ClusterImageExportReconciler) Reconcile(ctx context.Context, req ctrl.R
} }
} }
// Update status to RUNNING with retry // Update total image count and status
totalImages := len(fullImagesList.Containers)
if err := r.updateStatusWithRetry(ctx, clusterImageExport, func(export *raczylocomv1.ClusterImageExport) error { if err := r.updateStatusWithRetry(ctx, clusterImageExport, func(export *raczylocomv1.ClusterImageExport) error {
export.Status.Progress = shared.STATUS_RUNNING if export.Status.Progress == "" {
export.Status.Progress = shared.STATUS_PENDING
}
if export.Status.Progress == shared.STATUS_PENDING {
export.Status.Progress = shared.STATUS_RUNNING
}
export.Status.TotalImages = totalImages
return nil return nil
}); err != nil { }); err != nil {
l.Error(err, "unable to update ClusterImageExport status to RUNNING") l.Error(err, "unable to update ClusterImageExport status")
return ctrl.Result{}, err return ctrl.Result{}, err
} }
@@ -196,24 +180,43 @@ func (r *ClusterImageExportReconciler) Reconcile(ctx context.Context, req ctrl.R
} }
} }
// Check if all ClusterImages are completed // Check completion status and update counts
allCompleted, err := r.checkAllClusterImagesCompleted(ctx, clusterImageExport) completedCount := 0
if err != nil { clusterImageList := &raczylocomv1.ClusterImageList{}
l.Error(err, "unable to check ClusterImages status") if err := r.List(ctx, clusterImageList, client.InNamespace(clusterImageExport.Namespace),
client.MatchingFields{"spec.exportName": clusterImageExport.Name}); err != nil {
l.Error(err, "unable to list ClusterImages")
return ctrl.Result{}, err return ctrl.Result{}, err
} }
if allCompleted { for _, ci := range clusterImageList.Items {
if ci.Status.Progress == shared.STATUS_SUCCESS || ci.Status.Progress == shared.STATUS_PRESENT {
completedCount++
}
}
// Update status with completion info
if completedCount == totalImages && totalImages > 0 {
if err := r.updateStatusWithRetry(ctx, clusterImageExport, func(export *raczylocomv1.ClusterImageExport) error { if err := r.updateStatusWithRetry(ctx, clusterImageExport, func(export *raczylocomv1.ClusterImageExport) error {
export.Status.Progress = shared.STATUS_SUCCESS export.Status.Progress = shared.STATUS_SUCCESS
export.Status.CompletedImages = completedCount
return nil return nil
}); err != nil { }); err != nil {
l.Error(err, "unable to update ClusterImageExport status to SUCCESS") l.Error(err, "unable to update ClusterImageExport status")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
} else {
if err := r.updateStatusWithRetry(ctx, clusterImageExport, func(export *raczylocomv1.ClusterImageExport) error {
export.Status.CompletedImages = completedCount
return nil
}); err != nil {
l.Error(err, "unable to update ClusterImageExport status")
return ctrl.Result{}, err return ctrl.Result{}, err
} }
} }
return ctrl.Result{Requeue: !allCompleted}, nil return ctrl.Result{Requeue: true}, nil
} }
// updateStatusWithRetry attempts to update the status of a ClusterImageExport with retries // updateStatusWithRetry attempts to update the status of a ClusterImageExport with retries