mirror of
https://github.com/lukaszraczylo/kubernetes-images-sync-operator.git
synced 2026-06-16 00:51:17 +00:00
Work on flapping exports status
This commit is contained in:
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user